SpringMVC----异常解析器+拦截器

接上一篇:FastJson

1. 异常解析器

1.1 现有方案,分散处理

Controller中的每个Handler自己处理异常

	 public User2 test3(){
        User2 user2 = null;
        try {
            user2 = new User2(1,null,null,new Date(),22222.38);
            System.out.println(user2);
            //调用Servlet
        } catch (Exception1 e) {
            e.printStackTrace();
            return "redirect:/xx/error1";
        } catch (Exception2 e){
            e.printStackTrace();
            return "redirect:/xx/error2";
        }
        return user2;
    }
     public User2 test4(){
        User2 user2 = null;
        try {
            user2 = new User2(2,null,null,new Date(),2333.18);
            System.out.println(user2);
            //调用Servlet
        } catch (Exception1 e) {
            e.printStackTrace();
            return "redirect:/xx/error1";
        } catch (Exception2 e){
            e.printStackTrace();
            return "redirect:/xx/error2";
        }
        return user2;
    }

此种处理方案,异常处理逻辑,分散在各个handler中,不利于集中管理

1.2 异常解析器,统一处理

Controller中的每一个Handler不再自己处理异常,而是直接throws所有异常,定义在一个”异常解析器“集中捕获处理所有异常

  1. 把所有异常处理放在ex包下

SpringMVC----异常解析器+拦截器_第1张图片
2. resolver包下定义异常解析器:MyExceptionResolver
3. 其他新建如下:

SpringMVC----异常解析器+拦截器_第2张图片

//异常解析器
//任何一个Handler中抛出异常时,都会被该异常处理器捕获处理,Handler就是controller里面的方法
public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView modelAndView = new ModelAndView();
        if (ex instanceof MyException1) {
            modelAndView.setViewName("redirect:/error1.jsp");
        } else if (ex instanceof MyException2) {
            modelAndView.setViewName("redirect:/error2.jsp");
        } else if (ex instanceof MyException3) {
            modelAndView.setViewName("redirect:/error3.jsp");
        }
        return modelAndView;
    }
}

SpringMVC----异常解析器+拦截器_第3张图片

  1. mvc.xml配置
	
    <bean class="com.lyx.resolver.MyExceptionResolver">bean>
    

SpringMVC----异常解析器+拦截器_第4张图片

  1. controller
@RequestMapping("/ex")
@Controller
public class ExController {

    @RequestMapping("/test")
    public String test(Integer id) throws Exception {
        if(id==1){
            throw new MyException1("testex1");
        }
        return "success";
    }
}

  1. Tomcat运行,访问http://localhost:8080/ex/test?id=1

SpringMVC----异常解析器+拦截器_第5张图片
SpringMVC----异常解析器+拦截器_第6张图片

2. 拦截器

2.1 现存问题

  • 当用户登录成功后在session作用域中添加一个key:value保存一下用户登录状态,代码如下
@Controller
@RequestMapping("/login")
@SessionAttributes("state")
public class LoginController {

    @RequestMapping("/save")
    public String save(Model model){
        //登录后留取状态标记
        model.addAttribute("state","ok");
        return "index";
    }
}
  • 其他方法,要先去判断static是否等于ok,来判断用户是否登录,如果登录了再执行对应的业务,但是如果没有登录,就会跳到登录页面,所以这两个判断和跳转,每一个方法都要判断/跳转一遍,且代码是一样的,这就是Handler中存在的冗余问题
    SpringMVC----异常解析器+拦截器_第7张图片

2.2 拦截器

  • 针对上述问题,我们可以把上面冗余的代码,写在一个方法里,然后其他方法复用该方法,实现这个效果的就是拦截器
  • 拦截器的实现原理就是,当一个方法被调用时,先不执行里面的方法,会先经过拦截器,拦截器里面会执行相关的逻辑,只有拦截器里面的逻辑顺利执行了,拦截器才会放行方法
  • 来写一个拦截器
  1. 新建一个interceptor包,包下新建一个MyInterceptor.java
  2. 该类implements 了HandlerInterceptor
  3. 重写了HandlerInterceptor里面的三个方法,preHandle():在handler之前执行,postHandle():在handler之后执行,响应之前执行,afterCompletion():在视图渲染完毕后执行
  4. 由此可见后面两个方法没有太大的作用
  5. 代码如下:

SpringMVC----异常解析器+拦截器_第8张图片
SpringMVC----异常解析器+拦截器_第9张图片
SpringMVC----异常解析器+拦截器_第10张图片
代码:

public class MyInterceptor1 implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
  • 只写preHandle()方法
    代码如下:

SpringMVC----异常解析器+拦截器_第11张图片

package com.lyx.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class MyInterceptor1 implements HandlerInterceptor{
    //在handler之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断登录状态
        HttpSession session = request.getSession();
        if(session.getAttribute("state")!=null){
            return true;
        }
        //中断之后,响应请求
        response.sendRedirect("/login.jsp");
        return false;
    }

    //在handler之后执行,响应之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    //在视图渲染之后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

2.3 mvc.xml配置

SpringMVC----异常解析器+拦截器_第12张图片


    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/login/test2"/>
            <mvc:mapping path="/login/test3"/>
            <bean class="com.lyx.interceptor.MyInterceptor1">
            bean>
        mvc:interceptor>
    mvc:interceptors>

2.4 Tomcat运行

  1. 访问http://localhost:8080/login/test1,未登录,拦截器拦截,跳转到登录页面
  2. 访问http://localhost:8080/login/test2,未登录,拦截器拦截,跳转到登录页面
  3. 访问http://localhost:8080/login/save,登录,跳转到index
  4. 再次访问http://localhost:8080/login/test1,已经登录,拦截器不拦截,执行当前test1中的方法

2.5 mvc.xml配置拦截/不拦截路径

SpringMVC----异常解析器+拦截器_第13张图片

    
    <mvc:interceptors>
        <mvc:interceptor>


            <mvc:mapping path="/login/*"/>
            <mvc:mapping path="/login/**"/>
            <mvc:mapping path="/login/test*"/>
            <mvc:exclude-mapping path="/login/save"/>
            <bean class="com.lyx.interceptor.MyInterceptor1">
            bean>
        mvc:interceptor>
    mvc:interceptors>
  1. 对应拦截路径配置: ,Tomcat运行,访问路径:http://localhost:8080/login/b/test1,就不会被拦截

你可能感兴趣的