• springmvc拦截器与全局异常


    今天小编将给大家分享拦截器与全局异常

    1.拦截器介绍

    SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
    依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个 controller生命周期之内可以多次调用。

    1.1拦截器与过滤器有何区别?

    过滤器:

    • 依赖与servlet容器,基于在实现上基于函数回调,可以对几乎所有请求进行过滤
    • 基于servlet标准,只要是web工程即可使用,通用性强
    • 过滤器的出现早已拦截器

    拦截器:

    • 属于springmvc技术,必须依赖于springmvc环境采用使用
    • springmvc拦截器通常对处理器(controller)进行拦截
    • 拦截器只能拦截dispatcherServlet处理的请求
    • 可以使用spring提供的容器,及强大的依赖注入

    1.2拦截器的使用场景主要有以下几点

    1)日志记录

    2)权限检查

    3)通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。

    1.3执行流程

    1.4开发示例

    spring-xml配置文件

     创建一个拦截器

     

     

    关于拦截器接口中定义的方法的说明:

    • preHandle方法

    • 作用:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。

    • 执行时机:在处理器方法执行前执行

    • postHandle方法

    • 作用:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改

    • 执行时机:在处理器的方法执行后,视图渲染之前

    • afterCompletion方法

    • 作用:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象

    • 执行时机:视图渲染完成后(整个流程结束之后)

    登录验证, 开发步骤:

    • 开发登录功能,当用户登录成功,将用户记入session
    • 开发拦截器,如果用户访问除登录功能之外的其他资源,则验证是否登录,否则不允许访问

    1) 登录页面

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    3. <html>
    4. <head>
    5. <title>Titletitle>
    6. head>
    7. <body>
    8. <c:if test="${not empty error}">
    9. <div>
    10. ${error}
    11. div>
    12. c:if>
    13. <form action="<%=request.getContextPath()%>/user/login" method="post">
    14. 用户名: <input type="text" name="name"> <br data-tomark-pass> 密码: <input type="password" name="password"><br data-tomark-pass> <input type="submit" value="提交">
    15. form>
    16. body>
    17. html>

    2)登录Controller

    1. @Controller
    2. public class LoginController {
    3. @RequestMapping("/")
    4. public String loginPage() {
    5. return "login";
    6. }
    7. @PostMapping("/user/login")
    8. public String login(String name, String password, HttpSession session, Model model) {
    9. if("admin".equals(name) && "123".equals(password)) {
    10. session.setAttribute("user", name);
    11. return "index";
    12. }
    13. model.addAttribute("error", "用户名或密码错误");
    14. return "login";
    15. }
    16. @GetMapping("/user/logout")
    17. public String logout(HttpSession session) {
    18. session.removeAttribute("user");
    19. return "redirect:/";
    20. }
    21. }

    3)编写index.jsp页面,可以是任何内容,可用于演示即可。 在index中加入退出系统的代码(也是为方便演示)

    <a href="<%=request.getContextPath()%>/user/logout">退出a>
    

    测试可以登录后,可以进行拦截器的编写了

    4)拦截器的编写,参考代码

    1. public class LoginInterceptor implements HandlerInterceptor {
    2. @Override
    3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    4. String uri = request.getRequestURI();
    5. String contextPath = request.getContextPath();
    6. //登录页面,放行
    7. if (uri.endsWith(contextPath+"/") || uri.indexOf("/user/login") > 0) {
    8. return true;
    9. }
    10. //其他情况需要验证登录
    11. HttpSession session = request.getSession();
    12. Object user = session.getAttribute("user");
    13. //已登录,放行
    14. if (Objects.nonNull(user)) {
    15. return true;
    16. }
    17. session.setAttribute("error", "请先登录");
    18. //request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
    19. response.sendRedirect(contextPath+"/");
    20. //不再处理其他拦截器,直接返回
    21. return false;
    22. }
    23. }

    2.全局异常

    为什么使用全局异常?

    因为我们可以把service,dao,contrller里面包含全部有可能出现的异常交给全局异常一起处理,然后返回给异常error.jsp页面

    2.1异常处理流程

     

    2.2 SpringMVC自带的简单异常处理器

    SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口

    1)在spring-mvc.xml 中加入如下配置

    1. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    2. <property name="defaultErrorView" value="error"/>
    3. <property name="exceptionAttribute" value="ex"/>
    4. <property name="exceptionMappings">
    5. <props>
    6. <prop key="java.lang.RuntimeException">errorprop>
    7. props>
    8. property>
    9. bean>

    2)配置错误页面
    在WEB-INF/jsp 目录下,创建error.jsp, 与上面的spring-mvc.xml中的配置相对应

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Titletitle>
    5. head>
    6. <body>
    7. <h1>系统异常,请与管理员联系h1>
    8. body>
    9. html>

    2.3 自定义全局异常

    通过实现异常处理处理接口HandlerExceptionResovler处理全局异常。

    1) 实现接口

    1. @Component
    2. public class GlobalException implements HandlerExceptionResolver {
    3. @Override
    4. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    5. ModelAndView mv = new ModelAndView();
    6. mv.setViewName("error");
    7. if(ex instanceof RuntimeException) {
    8. mv.addObject("msg", ex.getMessage());
    9. }
    10. if(ex instanceof Exception){
    11. 编辑其他异常
    12. }
    13. return mv;
    14. }
    15. }

    2.4 使用注解方式定义全局异常

    定义全局异常处理器:

    1. @ControllerAdvice
    2. public class HandlerGlobalException {
    3. @ExceptionHandler
    4. public ModelAndView handler(Exception ex) {
    5. ModelAndView mv = new ModelAndView();
    6. if(ex instanceof RuntimeException) {
    7. mv.addObject("msg", ex.getMessage());
    8. }
    9. mv.setViewName("error");
    10. //如果系统直接返回JSON格式的错误数据,可以如下操作
    11. //mv.setView(new MappingJackson2JsonView());
    12. return mv;
    13. }
    14. }
  • 相关阅读:
    Postman接口测试工具
    【ROOTFS】1-构建rootfs与nfs调试
    驱动开发:内核测试模式过DSE签名
    图计算:基于SparkGrpahX计算聚类系数
    骨骼动画详解
    基于web在线餐饮网站的设计与实现——蛋糕甜品店铺(HTML+CSS+JavaScript)
    乓乓响再度冲刺港股:来自临时及应急服务客户毛利率达70%
    mysql 索引失效情况/sql提示/覆盖索引和回表查询
    C++的缺陷和思考(六)
    Kubernetes技术--k8s核心技术Helm
  • 原文地址:https://blog.csdn.net/Bugxiu_fu/article/details/126681376