第一章:SpringMVC 框架中的拦截器
-
拦截器的概述:
- SpringMVC 框架中的拦截器用于对处理器进行预处理和后处理的技术
- 可以自定义拦截链,拦截链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行
- 拦截器和过滤器的功能比较类似,有区别:
- 过滤器是 Servlet 规范的一部分,任何框架都可以使用过滤器技术
- 过滤器是 SpringMVC 框架独有的
- 过滤器配置了 /*,可以拦截任何资源
- 拦截器只会对控制器中的方法进行拦截
- 拦截器也是 AOP 思想的一种实现方式:
- 想要自定义拦截器,需要实现接口 HandlerInterceptor 接口
-
自定义拦截器步骤:
- Controller 中的方法:
@Controller @RequestMapping("/dept") public class DeptController { /** * 拦截器测试方法 */ @RequestMapping("/findAll") public String findAll(){ System.out.println("findAll方法执行了"); return "suc"; } }
- 创建类,实现 HandlerInterceptor 接口,重写需要的方法:
public class MyInterceptor implements HandlerInterceptor { /** * 拦截 controller 中的方法,放行后执行 controller 方法中的逻辑 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器 preHandler 方法执行了"); //手动跳转页面 // request.getRequestDispatcher("/WEB-INF/pages/suc.jsp").forward(request,response); //拦截,不放行 // return false; //放行 return true; } }
- 在 springmvc.xml 中配置拦截器类:
<!-- 配置拦截器 --> <mvc:interceptors> <!-- 配置拦截器 --> <mvc:interceptor> <!-- 该拦截器拦截哪些资源 --> <mvc:mapping path="/dept/**"/> <!-- 配置不拦截资源 --> <!-- <mvc:exclude-mapping path=""/>--> <!-- 配置拦截对象 --> <bean class="com.qcby.mybatis.util.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
- Controller 中的方法:
-
HandlerInterceptor 接口中的方法:
- perHandle 方法:
- 是 controller 方法执行前拦截的方法:
- 可以使用 request 或者 response 跳转到指定的页面
- return true:放行,执行下一个拦截器,如果后面没有拦截器,执行 controller 中的方法
- return false:不放行,不会执行 controller 中的方法
- postHandle方法:
- 是 controller 方法执行后拦截的方法,在 JSP 视图前执行
- 可以使用 request 或者 response 跳转到指定页面
- 如果指定了跳转的页面,那么 controller 方法跳转的页面将不会显示
- 示例:
public class MyInterceptor implements HandlerInterceptor { /** * 拦截 controller 中的方法,放行后执行 controller 方法中的逻辑 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器 preHandler 方法执行了"); //手动跳转页面 // request.getRequestDispatcher("/WEB-INF/pages/suc.jsp").forward(request,response); //拦截,不放行 // return false; //放行 return true; } /** * controller 方法执行后,要拦截的方法 * @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("PostHandler 方法执行了..."); //进行页面跳转 request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * controller 跳转的 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("afterCompletion 方法执行了..."); } }
- perHandle 方法:
-
配置多个拦截器:
- 再编写一个拦截器的类:
public class MyInterceptor2 implements HandlerInterceptor { /** * 拦截 controller 中的方法,放行后执行 controller 方法中的逻辑 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器 MyInterceptor3 的 preHandler 方法执行了"); //放行 return true; } /** * controller 方法执行后,要拦截的方法 * @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("MyInterceptor3 的 PostHandler 方法执行了..."); //进行页面跳转 request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * controller 跳转的 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("MyInterceptor3 的 afterCompletion 方法执行了..."); } }
- springmvc.xml 文件中配置两个拦截器:
<!-- 配置拦截器 --> <mvc:interceptors> <!-- 配置拦截器 --> <mvc:interceptor> <!-- 该拦截器拦截哪些资源 --> <mvc:mapping path="/dept/**"/> <!-- 配置不拦截资源 --> <!-- <mvc:exclude-mapping path=""/>--> <!-- 配置拦截对象 --> <bean class="com.qcby.mybatis.util.MyInterceptor"/> </mvc:interceptor> <!-- 配置拦截器 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.qcby.mybatis.util.MyInterceptor2"/> </mvc:interceptor> </mvc:interceptors>j
- 再编写一个拦截器的类:
第二章:SpringMVC 的异常处理
-
异常处理思路:
- Controller 层调用 service 层,service 层调用 dao 层,异常都是向上抛出的,最终有 DispatcherServlet 找异常处理器进行异常的处理
-
SpringMVC 的异常处理:
- controller 代码:
@Controller @RequestMapping("/role") public class RoleController { /** * 自己手动处理异常 * */ @RequestMapping("/findException") public String findException(){ try { System.out.println("方法已被执行"); //模拟异常 int a = 1 / 0; }catch (Exception e){ e.printStackTrace(); //跳转提示页面 ··· } return "suc"; } /** * 使用异常处理器方式 */ @RequestMapping("/findAll") public String findAll(){ System.out.println("执行了"); //模拟异常 int a = 1 / 0; return "suc"; } }
- 自定义异常类:
public class SysException extends Exception{ //提示消息 private String message; @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SysException(String message) { this.message = message; } }
- 自定义异常处理器:
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) { //在控制台打印异常的信息 e.printStackTrace(); //做强转 SysException exception = null; //判断 if(e instanceof SysException){ exception = (SysException) e; }else { exception = new SysException("系统正在维护,请联系管理员"); } //存入异常提示信息 ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",e.getMessage()); //设置跳转页面 mv.setViewName("error"); return mv; } }
- 配置异常处理器:
<bean id="sysExceptionResolver" class="com.qcby.mybatis.util.SysExceptionResolver"/>
- JSP 页面代码:
<%-- Created by IntelliJ IDEA. User: L-J-X Date: 2025/1/14 Time: 23:03 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>错误提示页面</title> </head> <body> <h3>错误提示页面</h3> ${errorMsg} </body> </html>
- controller 代码: