SpringMVC(6)异常处理及拦截器

1、异常处理

1.1、异常处理的思路

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

​ 系统的 dao、 service、 controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图 :

1.2、SpringMVC的异常处理

1.自定义异常类

public class SysException extends Exception {

    private String message;

    public SysException(String message) {

        this.message = message;
} @Override
public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} }

2.定义异常处理器

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class SysExceptionResolver implements HandlerExceptionResolver { /**
* 处理异常业务逻辑
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//获取异常对象
SysException ex = null;
if (e instanceof SysException){
ex = (SysException)e;
}else {
ex = new SysException("系统正在维护....");
}
//创建ModelAndvies对象
ModelAndView mv = new ModelAndView();
mv.addObject("error",ex.getMessage());
mv.setViewName("error");
return mv;
}
}

3.配置异常处理器对象

<!--配置异常处理器对象-->
<bean id="sysExceptionResolver" class="wf.exception.SysExceptionResolver"/>

4.测试异常处理的jsp

<a href="user/teseException">拦截器</a>

5.测试异常处理控制器

@RequestMapping("/teseException")
public String teseException() throws SysException {
System.out.println("teseException方法执行了"); try {
int a = 10/0;
} catch (Exception e) {
e.printStackTrace();
throw new SysException("查询用户错误");
}
return "success";
}

2、拦截器

2.1、拦截器概述

Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。

用户可以自己定义一些拦截器来实现特定的功能。

谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:

过滤器是 servlet 规范中的一部分, 任何 java web 工程都可以使用。

拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。

过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。

拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp, html,css,image 或者 js 是不会进行拦

截的。

它也是 AOP 思想的具体应用。

我们要想自定义拦截器, 要求必须实现: HandlerInterceptor 接口。

2.2、自定义拦截器

1.创建拦截器类

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor {
/**
* 预处理,controller方法执行前
* return true,放行执行下一个拦截器,若没有则执行controller
* false不放行请求失败
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器执行了....前111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
} /**
* 后处理方法,controller方法之后,success方法之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器执行了....后111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /**
* success.jsp页面执行后,该方法执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("success.jsp页面执行后,该方法执行111");
}
}

2.在配置文件springmvc.xml中配置拦截器

<!--配置拦截器-->
<mvc:interceptors>
<!--配置具体拦截器-->
<mvc:interceptor>
<!--要拦截的具体方法-->
<mvc:mapping path="/user/*"/>
<!--不拦截的方法
<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean id="myInterceptor" class="wf.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

然后在访问controller时就会先经过拦截器在进行之后操作

2.3、拦截器的HandlerInterceptor接口中的方法

public interface HandlerInterceptor {
/**
* 如何调用:
* 按拦截器定义顺序调用
* 何时调用:
* 只要配置了都会调用
* 有什么用:
* 如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去
* 进行处理,则返回 true。
* 如果程序员决定不需要再调用其他的组件去处理请求,则返回 false。
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)
throws Exception {
return true;
}
/**
* 如何调用:
* 按拦截器定义逆序调用
* 何时调用:
* 在拦截器链内所有拦截器返成功调用
* 有什么用:
* 在业务处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前被调用,
* 在该方法中对用户请求 request 进行处理。
*/
default void postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception { }
/**
* 如何调用:
* 按拦截器定义逆序调用
* 何时调用:
* 只有 preHandle 返回 true 才调用
* 有什么用:
* 在 DispatcherServlet 完全处理完请求后被调用,
* 可以在该方法中进行一些资源清理的操作。
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler,
@Nullable Exception ex) throws Exception { }
}

2.4、多个拦截器的执行顺序

多个拦截器是按照配置的顺序决定的。

多个拦截器的springmvc.xml配置

<!--配置拦截器-->
<mvc:interceptors>
<!--配置具体拦截器-->
<mvc:interceptor>
<!--要拦截的具体方法-->
<mvc:mapping path="/user/*"/>
<!--不拦截的方法
<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean id="myInterceptor1" class="wf.interceptor.MyInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<!--要拦截的具体方法-->
<mvc:mapping path="/user/*"/>
<!--不拦截的方法
<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象-->
<bean id="myInterceptor2" class="wf.interceptor.MyInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>

执行顺序

多个拦截器,如果其中一个拦截器拦截请求,那么之后就会逐级执行前一个拦截器的afterCompletion方法

最新文章

  1. js 闭包之一
  2. C++中为什么要将析构函数定义成虚函数
  3. Unity3D 面试题汇总
  4. 《DSP using MATLAB》示例Example5.6
  5. iOS 的基本框架
  6. 【转载】ANSYS的APDL与C语言混合编程(实例)
  7. asp xmlhttp 读取文件
  8. freemarker 集成 sitemesh 装饰html页面 shiro 标签
  9. TinyMapper 使用总结
  10. 【codeforces 698C】LRU
  11. 为什么腾讯有QQ,还要推出微信?
  12. 你所忽略的DNS---DNS实战及深度解读
  13. java枚举使用 总结
  14. ES6的字符串和数值的扩展
  15. QLabel-标签控件的应用
  16. 短信验证登陆-中国网建提供的SMS短信平台
  17. 【第一次玩Travis CI】终于弄好了我的马鸭
  18. nowcoder 203A Knight(贪心+打表)
  19. POJ 2449 Remmarguts&#39; Date (K短路 A*算法)
  20. 解题:BZOJ 4808 马

热门文章

  1. su和sudo的区别与使用【华为云技术分享】
  2. 转:关于JAVA项目中CLASSPATH路径详解
  3. luogu P2947 [USACO09MAR]向右看齐Look Up |单调队列
  4. MongoDB第三天(正则,管道,聚合,字符串,算术,日期,java连接MongoDB)
  5. 【解决】image ... could not be accessed on a registry to record its digest.
  6. 2018 ICPC南京网络赛 Set(字典树 + 合并 + lazy更新)
  7. HDU-3339 IN ACTION(Dijkstra +01背包)
  8. Django 2.0.7 使用小知识
  9. [ Coding七十二绝技 ] 如何利用Java异常快速分析源码
  10. 【Nodejs】375- 如何加快 Node.js 应用的启动速度