【SpringMVC】 4.2 异常处理

前端之家收集整理的这篇文章主要介绍了【SpringMVC】 4.2 异常处理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

SpringMVC学习记录

注意:以下内容是学习 北京动力节点 的SpringMVC视频后所记录的笔记、源码以及个人的理解等,记录下来仅供学习

第4章 SpringMVC 核心技术

4.2异常处理

 SpringMVC框架处理异常的常用方式:使用@ExceptionHandler注解处理异常。

异常处理步骤:

  1. 新建maven web项目
  2. 加入依赖
  3. 新建一个自定义异常类 MyUserException,再定义它的子类NameException,AgeException
  4. 在controller抛出NameException,AgeException
  5. 创建一个普通类,作用全局异常处理类
    (1). 在类的上面加入@ControllerAdvice
    (2). 在类中定义方法方法的上面加入@ExceptionHandler
  6. 创建处理异常的视图页面
  7. .创建springmvc的配置文件
    (1).组件扫描器 ,扫描@Controller注解
    (2).组件扫描器,扫描@ControllerAdvice所在的包名
    (3).声明注解驱动

项目结构:

@H_301_48@

4.2.1 @ExceptionHandler 注解

 使用注解@ExceptionHandler可以将一个方法指定为异常处理方法。该注解只有一个可 选属性value,为一个Class<?>数组,用于指定该注解的方法所要处理的异常类,即所要匹 配的异常。
 而被注解的方法,其返回值可以是ModelAndView、String,或void,方法名随意,方法 参数可以是 Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会 自动为这些方法参数赋值。
对于异常处理注解的用法,也可以直接将异常处理方法注解于Controller之中。

(1) 自定义异常类

 定义三个异常类:NameException、AgeException、MyUserException。其中 MyUserException 是另外两个异常的父类
MyUserException.java

  1. package com.bjpowernode.exception;
  2. public class MyUserException extends Exception {
  3. public MyUserException() {
  4. super();
  5. }
  6. public MyUserException(String message) {
  7. super(message);
  8. }
  9. }

AgeException.java

  1. package com.bjpowernode.exception;
  2. //当年龄有问题时,抛出的异常
  3. public class AgeException extends MyUserException {
  4. public AgeException() {
  5. super();
  6. }
  7. public AgeException(String message) {
  8. super(message);
  9. }
  10. }

NameException.java

  1. package com.bjpowernode.exception;
  2. //表示当用户的姓名有异常,抛出NameException
  3. public class NameException extends MyUserException {
  4. public NameException() {
  5. super();
  6. }
  7. public NameException(String message) {
  8. super(message);
  9. }
  10. }

(2) 修改 Controller 抛出异常

MyController.java

  1. package com.bjpowernode.controller;
  2. import com.bjpowernode.exception.AgeException;
  3. import com.bjpowernode.exception.MyUserException;
  4. import com.bjpowernode.exception.NameException;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import org.springframework.web.servlet.ModelAndView;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import javax.servlet.http.HttpSession;
  12. import javax.xml.ws.RequestWrapper;
  13. /**
  14. * @RequestMapping:
  15. * value : 所有请求地址的公共部分,叫做模块名称
  16. * 位置: 放在类的上面
  17. */
  18. @Controller
  19. public class MyController {
  20. @RequestMapping(value = "/some.do")
  21. public ModelAndView doSome(String name,Integer age) throws MyUserException {
  22. //处理some.do请求了。 相当于service调用处理完成了。
  23. ModelAndView mv = new ModelAndView();
  24. //try {
  25. //根据请求参数抛出异常
  26. if (!"zs".equals(name)) {
  27. throw new NameException("姓名不正确!!!");
  28. }
  29. if (age == null || age > 80) {
  30. throw new AgeException("年龄比较大!!!");
  31. }
  32. //}catch(Exception e){
  33. // e.printStackTrace();
  34. //}
  35. mv.addObject("myname",name);
  36. mv.addObject("myage",age);
  37. mv.setViewName("show");
  38. return mv;
  39. }
  40. }

(3) 定义异常请求以及响应页面

请求页面
index.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%
  3. String basePath = request.getScheme() + "://" +
  4. request.getServerName() + ":" + request.getServerPort() +
  5. request.getContextPath() + "/";
  6. %>
  7. <html>
  8. <head>
  9. <title>Title</title>
  10. <base href="<%=basePath%>" />
  11. </head>
  12. <body>
  13. <p>处理异常的,全局异常处理</p>
  14. <form action="some.do" method="post">
  15. 姓名:<input type="text" name="name"> <br/>
  16. 年龄:<input type="text" name="age"> <br/>
  17. <input type="submit" value="提交请求">
  18. </form>
  19. </body>
  20. </html>

响应页面
ageError.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. ageError.jsp <br/>
  8. 提示信息:${msg} <br/>
  9. 系统异常消息:${ex.message}
  10. </body>
  11. </html>

defaultError.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. defaultError.jsp <br/>
  8. 提示信息:${msg} <br/>
  9. 系统异常消息:${ex.message}
  10. </body>
  11. </html>

nameError.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. nameError.jsp <br/>
  8. 提示信息:${msg} <br/>
  9. 系统异常消息:${ex.message}
  10. </body>
  11. </html>

(4) 定义全局异常处理类

不过,一般不这样使用。而是将异常处理方法专门定义在一个类中,作为全局的异常处理类。需要使用注解@ControllerAdvice,字面理解就是“控制器增强”,是给控制器对象增强功能的。使用@ControllerAdvice 修饰的类中可以使用@ExceptionHandler。当使用@RequestMapping 注解修饰的方法抛出异常时,会执行@ControllerAdvice 修饰的类中的异常处理方法@ControllerAdvice 是使用@Component 注解修饰的,可以context:component-scan扫描到@ControllerAdvice 所在的类路径(包名),创建对象。

GlobalExceptionHandler.java

  1. package com.bjpowernode.handler;
  2. import com.bjpowernode.exception.AgeException;
  3. import com.bjpowernode.exception.NameException;
  4. import org.springframework.web.bind.annotation.ControllerAdvice;
  5. import org.springframework.web.bind.annotation.ExceptionHandler;
  6. import org.springframework.web.servlet.ModelAndView;
  7. /**
  8. * @ControllerAdvice : 控制器增强(也就是说给控制器类增加功能--异常处理功能
  9. * 位置:在类的上面。
  10. * 特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明组件扫描器。
  11. * 指定@ControllerAdvice所在的包名
  12. */
  13. @ControllerAdvice
  14. public class GlobalExceptionHandler {
  15. //定义方法,处理发生的异常
  16. /*
  17. 处理异常的方法和控制器方法的定义一样, 可以有多个参数,可以有ModelAndView,String,void,对象类型的返回值
  18. 形参:Exception,表示Controller中抛出的异常对象。
  19. 通过形参可以获取发生的异常信息。
  20. @ExceptionHandler(异常的class):表示异常的类型,当发生此类型异常时,
  21. 由当前方法处理
  22. */
  23. @ExceptionHandler(value = NameException.class)
  24. public ModelAndView doNameException(Exception exception){
  25. //处理NameException的异常。
  26. /*
  27. 异常发生处理逻辑:
  28. 1.需要把异常记录下来, 记录到数据库,日志文件
  29. 记录日志发生的时间,哪个方法发生的,异常错误内容
  30. 2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员。
  31. 3.给用户友好的提示
  32. */
  33. ModelAndView mv = new ModelAndView();
  34. mv.addObject("msg","姓名必须是zs,其它用户不能访问");
  35. mv.addObject("ex",exception);
  36. mv.setViewName("nameError");
  37. return mv;
  38. }
  39. //处理AgeException
  40. @ExceptionHandler(value = AgeException.class)
  41. public ModelAndView doAgeException(Exception exception){
  42. //处理AgeException的异常。
  43. /*
  44. 异常发生处理逻辑:
  45. 1.需要把异常记录下来, 记录到数据库,日志文件
  46. 记录日志发生的时间,哪个方法发生的,异常错误内容
  47. 2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员。
  48. 3.给用户友好的提示
  49. */
  50. ModelAndView mv = new ModelAndView();
  51. mv.addObject("msg","你的年龄不能大于80");
  52. mv.addObject("ex",exception);
  53. mv.setViewName("ageError");
  54. return mv;
  55. }
  56. //处理其它异常, NameException,AgeException以外,不知类型的异常
  57. @ExceptionHandler
  58. public ModelAndView doOtherException(Exception exception){
  59. //处理其它异常
  60. ModelAndView mv = new ModelAndView();
  61. mv.addObject("msg",exception);
  62. mv.setViewName("defaultError");
  63. return mv;
  64. }
  65. }

@ControllerAdvice 是使用@Component 注解修饰的
这句话看了源码是这样的,ControllerAdvice类是用@Component 注解的,
  @Component 作用:把普通pojo类实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>
  @Component,@Service,@Controller,@Repository注解的类,并把这些类纳入进spring容器中管理。

(5) 定义 Spring 配置文件

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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  7. <!--声明组件扫描器-->
  8. <context:component-scan base-package="com.bjpowernode.controller" />
  9. <!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
  10. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  11. <!--前缀:视图文件的路径-->
  12. <property name="prefix" value="/WEB-INF/view/" />
  13. <!--后缀:视图文件的扩展名-->
  14. <property name="suffix" value=".jsp" />
  15. </bean>
  16. <!--处理需要的两步-->
  17. <context:component-scan base-package="com.bjpowernode.handler" />
  18. <mvc:annotation-driven />
  19. </beans>

web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!--声明,注册springmvc的核心对象DispatcherServlet
  7. 需要在tomcat服务器启动后,创建DispatcherServlet对象的实例。
  8. 为什么要创建DispatcherServlet对象的实例呢?
  9. 因为DispatcherServlet在他的创建过程中, 会同时创建springmvc容器对象,
  10. 读取springmvc的配置文件,把这个配置文件中的对象都创建好, 当用户发起
  11. 请求时就可以直接使用对象了。
  12. servlet的初始化会执行init()方法。 DispatcherServlet在init()中{
  13. //创建容器,读取配置文件
  14. WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
  15. //把容器对象放入到ServletContext中
  16. getServletContext().setAttribute(key,ctx);
  17. }
  18. 启动tomcat报错,读取这个文件 /WEB-INF/springmvc-servlet.xml(/WEB-INF/myweb-servlet.xml)
  19. springmvc创建容器对象时,读取的配置文件默认是/WEB-INF/<servlet-name>-servlet.xml .
  20. -->
  21. <servlet>
  22. <servlet-name>myweb</servlet-name>
  23. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  24. <!--自定义springmvc读取的配置文件的位置-->
  25. <init-param>
  26. <!--springmvc的配置文件的位置的属性-->
  27. <param-name>contextConfigLocation</param-name>
  28. <!--指定自定义文件的位置-->
  29. <param-value>classpath:springmvc.xml</param-value>
  30. </init-param>
  31. <!--在tomcat启动后,创建Servlet对象
  32. load-on-startup:表示tomcat启动后创建对象的顺序。它的值是整数,数值越小,
  33. tomcat创建对象的时间越早。 大于等于0的整数。
  34. -->
  35. <load-on-startup>1</load-on-startup>
  36. </servlet>
  37. <servlet-mapping>
  38. <servlet-name>myweb</servlet-name>
  39. <!--
  40. 使用框架的时候, url-pattern可以使用两种值
  41. 1. 使用扩展名方式, 语法 *.xxxx,xxxx是自定义的扩展名。 常用的方式 *.do,*.action,*.mvc等等
  42. 不能使用 *.jsp
  43. http://localhost:8080/myweb/some.do
  44. http://localhost:8080/myweb/other.do
  45. 2.使用斜杠 "/"
  46. -->
  47. <url-pattern>*.do</url-pattern>
  48. </servlet-mapping>
  49. </web-app>

猜你在找的SpringMVC相关文章