springmvc异常处理

骑猪看日落 2022-05-25 01:43 371阅读 0赞

1.通过@ExceptionHandler注释处理异常:

1)Handler—->()

  1. package com.majun.springmvc.test;
  2. import java.io.IOException;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestParam;
  6. import org.springframework.web.multipart.MultipartFile;
  7. @Controller
  8. @RequestMapping("/spring")
  9. public class Test {
  10. @RequestMapping("/testHandlerExceptionResolver")
  11. public String testHandlerExceptionResolver(@RequestParam("i") int i) {//获取页面请求参数,写入到方法当中
  12. System.out.println("result="+ 10/i);
  13. return "success";//返回一个提示没有错误的页面
  14. }}

2)index.jsp 页面:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>Insert title here</title>
  8. </head>
  9. <body>
  10. <!--i=2,传入参数,可以自行修改-->
  11. <a href="spring/testHandlerExceptionResolver?i=2">Test HandlerExceptionResolver</a>
  12. <hr>
  13. </body>
  14. </html>

3)springmvc.xml配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  8. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
  9. <!-- 选择扫描包的位置 -->
  10. <context:component-scan base-package="com.majun.springmvc"></context:component-scan>
  11. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  12. <property name="prefix" value="/WEB-INF/views/"></property>
  13. <property name="suffix" value=".jsp"></property>
  14. </bean>
  15. </beans>

4)处理异常的包:

  1. package com.majun.springmvc.Exception;
  2. import org.springframework.web.bind.annotation.ControllerAdvice;
  3. import org.springframework.web.servlet.ModelAndView;
  4. @ControllerAdvice
  5. public class ExceptionHandler {
  6. // 1.在@ExceptionHandler 方法的入参中可以加入Exception类型的参数,该参数对应异常对象
  7. // 2.@ExceptionHandler 方法的入参中不能传入Map ,若希望将异常信息传到error页面,则需要使用ModelAndView 作为返回值
  8. // 3.@ExceptionHandler 方法标记的异常有优先级问题
  9. // 4.@ControllerAdvice :如当前Handler 中找不到 @ExceptionHandler 方法标记的异常,则将去@ControllerAdvice 标记的类中
  10. // 查找@ExceptionHandler 标记的方法去处理异常
  11. @org.springframework.web.bind.annotation.ExceptionHandler({ArithmeticException.class})
  12. public ModelAndView testArithmeticException(Exception er) {
  13. System.out.println("出异常了"+er);
  14. ModelAndView mc=new ModelAndView("error");//error视图名viewname
  15. mc.addObject("exception",er);//在错误页面增加错误信息,使用${exception}
  16. return mc;//转到错误页面
  17. }
  18. }

5)显示错误信息页面:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>Insert title here</title>
  8. </head>
  9. <body>
  10. <h2>error page</h2>
  11. ${exception }
  12. </body>
  13. </html>

20180505194621498

6)web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  5. version="3.1">
  6. <display-name>springmvc_2</display-name>
  7. <welcome-file-list>
  8. <welcome-file>index.jsp</welcome-file>
  9. </welcome-file-list>
  10. <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
  11. <servlet>
  12. <servlet-name>springDispatcherServlet</servlet-name>
  13. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  14. <init-param>
  15. <param-name>contextConfigLocation</param-name>
  16. <param-value>classpath:springmvc.xml</param-value>
  17. </init-param>
  18. <load-on-startup>1</load-on-startup>
  19. </servlet>
  20. <!-- Map all requests to the DispatcherServlet for handling -->
  21. <servlet-mapping>
  22. <servlet-name>springDispatcherServlet</servlet-name>
  23. <url-pattern>/</url-pattern>
  24. </servlet-mapping>
  25. <!-- 配置 HiddenHttpMethodFilter: 把 POST 请求转为 DELETE、PUT 请求 -->
  26. <filter>
  27. <filter-name>HiddenHttpMethodFilter</filter-name>
  28. <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  29. </filter>
  30. <filter-mapping>
  31. <filter-name>HiddenHttpMethodFilter</filter-name>
  32. <url-pattern>/*</url-pattern>
  33. </filter-mapping>
  34. </web-app>

1. 文件上传

  • Spring 使用 Jakarta Commons FileUpload 技术实现了一个 MultipartResolver 实现类:
    CommonsMultipartResolver;
  • SpringMVC 上下文中默认没有装配 MultipartResolver,因此默认情况下不能处理文件的上传;
    若要使用上传功能,需要在上下文中配置 MultipartResolver;

    // 1. 导入 jar 包

    1. /* commons-fileupload;
    2. * commons-io;
    3. */

    // 2. 配置 MultipartResolver(多媒体解析器)






    // index.jsp

    文件上传


    file1:

    file2:

    file3:



  1. // Demo.java
  2. @RequestMapping(value="/testUpload",method=RequestMethod.POST)
  3. public String testUpload(@RequestParam("upload") MultipartFile[] file)
  4. throws IllegalStateException, IOException {
  5. for(MultipartFile mf : file){
  6. if(!mf.isEmpty()){
  7. mf.transferTo(new File("/Users/用户名/Documents/上传/"+
  8. mf.getOriginalFilename()));
  9. }
  10. }
  11. return "ok";
  12. }

2. 自定义拦截器

  1. 自定义的拦截器必须实现 HandlerInterceptor 接口:

    • preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行
      处理;如果拦截处理后,还需要调用其他的拦截器,或者是业务处理器,则返回 true; 否则,返回false;
    • postHandle():这个方法在业务处理器处理完请求后,但是,DispatcherServlet 向客户端返回
      响应前被调用,处理用户的 request请求;
    • afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方
      法中进行一些资源清理的操作;

    // FirstInterceptor.java
    public class FirstInterceptor implements HandlerInterceptor{

    1. public boolean preHandle(HttpServletRequest req,HttpServletResponse resp,
    2. Object handler)throws Exception{
    3. System.out.println("FirstInterceptor.....preHandle");
    4. return true;
    5. }
    6. public void postHandle(HttpServletRequest req, HttpServletResponse resp,
    7. Object handler, ModelAndView modelAndView)throws Exception{
    8. System.out.println("FirstInterceptor.....postHandle");
    9. }
    10. public void afterCompletion(HttpServletRequest req,HttpServletResponse resp,
    11. Object handler,Exception ex) throws Exception{
    12. System.out.println("FirstInterceptor.....afterCompletion");
    13. }

    }

    // 注册该拦截器

    1. <bean id="firstInterceptor"
    2. class="cn.itcast.springmvc.interceptor.firstInterceptor"/>

    // index.jsp
    示例:点击这里

    // Demo.java
    @Controller
    public class Demo{

    1. @RequestMapping(value="/hellowrold",method=RequestMethod.GET)
    2. public String helloworld(){
    3. System.out.println("======helloworld");
    4. return "ok";
    5. }

    }

运行结果:

1222878-20171104123209451-2127638057.png

2.1 拦截器配置

  1. // 自定义两个拦截器
  2. // FirstInterceptor.java(同上)
  3. // SecondInterceptor.java
  4. public class SecondInterceptor implements HandlerInterceptor{
  5. public boolean preHandle(HttpServletRequest req,HttpServletResponse resp,
  6. Object handler)throws Exception{
  7. System.out.println("SecondInterceptor.....preHandle");
  8. return true;
  9. }
  10. public void postHandle(HttpServletRequest req, HttpServletResponse resp,
  11. Object handler, ModelAndView modelAndView)throws Exception{
  12. System.out.println("SecondInterceptor.....postHandle");
  13. }
  14. public void afterCompletion(HttpServletRequest req,HttpServletResponse resp,
  15. Object handler,Exception ex) throws Exception{
  16. System.out.println("SecondInterceptor.....afterCompletion");
  17. }
  18. }
  19. // 注册拦截器
  20. <mvc:interceptors>
  21. <bean id="firstInterceptor"
  22. class="cn.itcast.springmvc.interceptor.FirstInterceptor"/>
  23. <mvc:interceptor>
  24. <mvc:mapping path="/emps"></mvc:mapping>
  25. <bean id="secondInterceptor"
  26. class="cn.itcast.springmvc.interceptor.SecondInterceptor"/>
  27. </mvc:interceptor>
  28. </mvc:interceptors>
  29. // Demo.java
  30. @Controller
  31. public class Demo{
  32. @RequestMapping(value="/emps",method=RequestMethod.GET)
  33. public String list(Map<String,Object> map){
  34. System.out.println("emps .... 执行");
  35. map.put("employees",employeeService.getAll());
  36. return "list";
  37. }
  38. }
  39. // index.jsp
  40. 查询所有员工: <a href="${pageContext.request.contextPath}/emps">查询所有</a>
结果分析
  • 第一个拦截器 preHandler 返回 true,第二个也为 true;

1222878-20171104123230951-845925520.png

  • 第一个拦截器返回 false,第二个为true或false;

1222878-20171104123240873-1170080086.png

  • 第一个拦截器返回 true,第二个为 false;

1222878-20171104123259732-1490369580.png

3. 异常处理

  1. SpringMVC 通过 HandlerExceptionResolver接口处理程序的异常,包括Handler映射,数据绑定以
    及目标方法执行时,发生的异常;
  2. SpringMVC 提供的 HandlerExceptionResolver接口的实现类:

    • ExceptionHandlerExceptionResolver;
    • DefaultHandlerExceptionResolver;
    • ResponseStatusExdeptionResolver;
    • SimpleMappingExceptionResolver;

3.1 HandlerExceptionResolver

  • @ExceptionHandler只处理当前 handler 方法中抛出的异常

    // index.jsp
    异常示例:异常处理1

    // Demo.java
    @Controller
    public class Demo{

    1. @RequestMapping(value="/testHandler",method=RequestMethod.GET)
    2. public String testHandler(@RequestParam("age") Integer age){
    3. int result = 10 / age;
    4. System.out.println(result);
    5. return "ok";
    6. }
    7. // 如果请求参数 age=0, 会报异常
    8. // error.jsp
    9. <body>
    10. 抱歉,系统繁忙,请稍候在试....
    11. </body>
    12. // 第一种方式: 返回到错误页面,不带异常信息
    13. @ExceptionHandler(value={ArithmeticException.class})
    14. public String dealHandlerExceptionResolver(Exception e){
    15. System.out.println("111111"+e.getMessage());
    16. return "error";
    17. }
    18. // 第二种方式: 将异常信息返回到错误页面, 需要使用 ModelAndView, 不能使用 Map
    19. @ExceptionHandler(value={ArithmeticException.class})
    20. public ModelAndView dealHandlerExceptionResolver(Excetption e){
    21. System.out.println("22222"+e.getMessage());
    22. ModelAndView mv = new ModelAndView();
    23. mv.addObject("myexception",e.getMessage());
    24. mv.setViewName("error");
    25. return mv;
    26. }
    27. // error.jsp
    28. <body>
    29. 抱歉,系统繁忙,请稍候在试....<br/>
    30. 异常信息:${requestScope.myexception}
    31. </body>
    32. // 异常优先级问题
    33. // ArithmeticExcetion 继承了 RuntimeException
    34. // 如果一个类中既有ArithmeticException, 也有 RuntimeException
    35. // 如果出现 ArithmeticException, 会执行ArithmeticException
    36. @ExceptionHandler(value={RuntimeException.class})
    37. public ModelAndView dealHandlerExceptionResolver2(Excetption e){
    38. System.out.println("33333"+e.getMessage());
    39. ModelAndView mv = new ModelAndView();
    40. mv.addObject("myexception",e.getMessage());
    41. mv.setViewName("error");
    42. return mv;
    43. }

    }

1222878-20171104123327701-144783387.png

3.2 @ControllerAdvice

  • 将所有异常存放在 exception 包下,将业务方法和处理异常的方法分离;
  • @ExceptionHandler中找不到的话,就去@ControllerAdvice标记的类里面查找标记了
    @ExceptionHandler的方法;

    // cn.itcast.springmvc.exception.CommonHelperException 类

    @ControllerAdvice
    public class CommonHelperException{

    1. @ExceptionHandler(value={ArithmeticException.class})
    2. public ModelAndView dealHandlerExceptionResolver(Excetption e){
    3. System.out.println("44444"+e.getMessage());
    4. ModelAndView mv = new ModelAndView();
    5. mv.addObject("myexception",e.getMessage());
    6. mv.setViewName("error");
    7. return mv;
    8. }

    }

3.3 ReponseStatusExceptionResolver

  1. // 模拟账户锁定,自定义一个 MyUserLockException 继承了 RuntimeException 的异常类
  2. // index.jsp
  3. 账户锁定异常:
  4. <a href="${pageContext.request.contextPath}/testResponse?username=lisi">异常示例</a>
  5. // cn.itcast.springmvc.exception.MyUserLockException 类
  6. @ResponseStatus(value=HttpStatus.LOCKED,reason="账户被锁定,请拨打10086")
  7. public class MyUserLockException extends RuntimeException{
  8. private static final long serialVersionUID = 1L;
  9. }
  10. // Demo.java
  11. @Controller
  12. public class Demo{
  13. @RequestMapping(value="/testResponse",method=RequestMethod.GET)
  14. public String testResponse(@RequestParam("username") String username){
  15. // username=zhangsan, 抛出异常
  16. if("zhangsan".equalsIgnoreCase(username)){
  17. throw new MyUserLockException();
  18. }
  19. return "ok";
  20. }
  21. //第二种用法,@ResponseStatus 用在方法上
  22. // 如果 name=zhangsan, 报 MyUserLockException,
  23. // 如果 name 为其他,报 Not Found
  24. @RequestMapping(value="/testResponse",method=RequestMethod.GET)
  25. @ResponseStatus(value=HttpStatus.NOT_FOUND,reason="测试...")
  26. public String testResponse(@RequestParam("username") String username){
  27. // username=zhangsan, 抛出异常
  28. if("zhangsan".equalsIgnoreCase(username)){
  29. throw new MyUserLockException();
  30. }
  31. return "ok";
  32. }
  33. }

1222878-20171104123350951-1599260766.png

1222878-20171104123401779-21668157.png

3.4 SimpleMappingExceptionResolver

  1. // 示例: 数组下标越界异常
  2. // springDispatcherServlet-servlet.xml 配置
  3. <bean id="simpleMappingExceptionResolver"
  4. class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  5. <!-- 可以自定义 requestScope.异常名称 --
  6. <property name="exceptionAttribute" value="自定义异常名称"/>
  7. <property name="exceptionMappings">
  8. <props>
  9. <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
  10. </props>
  11. </property>
  12. </bean>
  13. // index.jsp
  14. 异常示例:<a href="${pageContext.request.contextPath}/testSimple?id=3">数组下标越界</a>
  15. // error.jsp
  16. <body>
  17. 抱歉,系统繁忙,请稍候在试!<br/>
  18. 数组下标越界:${requestScope.exception}<br/>
  19. </body>
  20. // Demo.java
  21. @Controller
  22. public class Demo{
  23. @RequestMapping(value="/testSimple",method=RequestMethod.GET)
  24. public String testSimple(@RequestParam("id") Integer id){
  25. int[] arr = new int[10];
  26. System.out.println(arr[id]);
  27. return "ok";
  28. }
  29. }

1222878-20171104123418998-132266875.png

发表评论

表情:
评论列表 (有 0 条评论,371人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringMVC 异常处理

    如果在请求处理的时候,出现了异常,那它的输出依然会是Servlet响应。异常必须要以某种方式转换为响应。 Spring提供了多种方式将异常转换为响应: 1. 特定的Spr

    相关 SpringMVC处理异常

    Spring提供了多种方式将异常转换为响应:     1.特定的Spring异常将会自动映射为指定的HTTP状态码;     2.异常上可以添加@ResponseSta

    相关 springMVC异常处理

    异常处理思路: 系统中异常包括两种:预期异常和运行时异常RuntimeException.前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异

    相关 SpringMVC异常处理

      在Spring MVC中,所有用于处理在请求映射和请求处理过程中抛出的异常的类,都要实现 HandlerExceptionResolver 接口。 一个基于Spring

    相关 SpringMVC 异常处理

    如果我们的代码出现异常时一般会在页面很生硬的把异常打印出来,一是这样很难看再就是显得页面很没有水准,此时我们就可以使用异常处理器使页面出现异常时跳转到一个比较友好的错误提示页面