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) 登录页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <c:if test="${not empty error}">
        <div>
            ${error}
        </div>
    </c:if>
    <form action="<%=request.getContextPath()%>/user/login" method="post">
        用户名: <input type="text" name="name"> <br data-tomark-pass>        密码: <input type="password" name="password"><br data-tomark-pass>        <input type="submit" value="提交">
    </form>
</body>
</html>

2)登录Controller

@Controller
public class LoginController {

    @RequestMapping("/")
    public String loginPage() {
        return "login";
    }

    @PostMapping("/user/login")
    public String login(String name, String password, HttpSession session, Model model) {

        if("admin".equals(name) && "123".equals(password)) {
            session.setAttribute("user", name);
            return "index";
        }
        model.addAttribute("error", "用户名或密码错误");
        return "login";
    }

    @GetMapping("/user/logout")
    public String logout(HttpSession session) {
        session.removeAttribute("user");
        return "redirect:/";
    }
}

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

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

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

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

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();

        //登录页面,放行
        if (uri.endsWith(contextPath+"/") || uri.indexOf("/user/login") > 0) {
            return true;
        }

        //其他情况需要验证登录
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");

        //已登录,放行
        if (Objects.nonNull(user)) {
            return true;
        }

        session.setAttribute("error", "请先登录");
        //request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        response.sendRedirect(contextPath+"/");

        //不再处理其他拦截器,直接返回
        return false;
    }

}

2.全局异常

为什么使用全局异常?

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

2.1异常处理流程

 

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

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

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

   <!-- springmvc提供的简单异常处理器 -->
   <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
       <!-- 定义默认的异常处理页面 ,需要在WEB-INF/jsp 下定义error.jsp 错误页面 -->
       <property name="defaultErrorView" value="error"/>
       <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception --> 
       <property name="exceptionAttribute" value="ex"/>
       <!-- 定义需要特殊处理的异常,这是重要点 --> 
       <property name="exceptionMappings">
           <props>
               <prop key="java.lang.RuntimeException">error</prop>
           </props>
           <!-- 还可以定义其他的自定义异常 -->
       </property>
   </bean> 

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>系统异常,请与管理员联系</h1>
</body>
</html>

2.3 自定义全局异常

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

1) 实现接口

@Component
public class GlobalException implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        if(ex instanceof RuntimeException) {
            mv.addObject("msg", ex.getMessage());
        }
        if(ex instanceof Exception){
        编辑其他异常
        }
        return mv;
    }
}

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

定义全局异常处理器:

@ControllerAdvice
public class HandlerGlobalException {

    @ExceptionHandler
    public ModelAndView handler(Exception ex) {

        ModelAndView mv = new ModelAndView();
        if(ex instanceof RuntimeException) {
            mv.addObject("msg", ex.getMessage());
        }
        mv.setViewName("error");

        //如果系统直接返回JSON格式的错误数据,可以如下操作
        //mv.setView(new MappingJackson2JsonView());
        
        return mv;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值