SpringMVC基础知识点整理(三)【异常处理及拦截器】

一、SpringMVC中的异常处理

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

1. 异常处理的思路

系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图所示:
在这里插入图片描述

2. 代码实现异常处理

  • Step1:编写自定义异常类

    /**
     * 自定义异常类
     */
    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;
        }
    }
    
  • Step2:自定义异常处理器

    /**
     * 异常处理器
     */
    public class SysExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
           //获取到异常对象
            SysException e = null;
            //如果抛出的是系统自定义异常则直接转换
            if (ex instanceof SysException){
                e = (SysException)ex;
            }else {
                //如果抛出的不是系统自定义异常则重新构造一个系统错误异常
                e = new SysException("系统正在维护...");
            }
            //创建ModelAndView对象
            ModelAndView mv = new ModelAndView();
            mv.addObject("errorMessage",e.getMessage());
            mv.setViewName("error");
            return mv;
        }
    }
    
  • Step3:配置异常处理器

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

二、SpringMVC中的拦截器

1. 拦截器的作用

  • Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
  • 拦截器链(Interceptor Chain):就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
  • 拦截器和过滤器的区别:
    • A. 过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
    • B. 过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。拦截器只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
  • 用户可以自己定义一些拦截器来实现特定的功能。如果想自定义拦截器, 要求必须实现:HandlerInterceptor 接口

2. 拦截器的简单入门

  • Step1:编写一个普通类实现HandlerInterceptor接口

    /**
     * 自定义拦截器
     */
    public class MyInterceptor1 implements HandlerInterceptor {
        /**
         * 预处理,controller方法执行前
         * return true:表示放行,执行下一个拦截器,如果没有,执行controller中的方法
         * return false:表示不放行,通过request和response进行跳转
         */
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("MyInterceptor1执行了...");
            return true;
        }
    }
    
  • Step2:配置拦截器(springmvc.xml中)

    <!--配置拦截器-->
    <mvc:interceptors>
       <mvc:interceptor>
           <!--要拦截的具体的方法-->
           <mvc:mapping path="/user/*"/>
           <!--不要拦截的方法-->
           <!--
           <mvc:exclude-mapping path=""/>
           -->
           
           <!--配置拦截器对象-->
           <bean class="com.xiaoxiao.interceptor.MyInterceptor1" />
       </mvc:interceptor>
    </mvc:interceptors>
    
  • Step3:测试运行结果

3. HandlerInterceptor接口中的方法

  • preHandle()
    如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回 true;如果程序员决定不需要再调用其他的组件去处理请求,则返回 false。简单来说,即return true:表示放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法;return false:表示不放行,不会执行controller中的方法,此时可以使用request或者response跳转到指定的页面。
  • postHandle()
    在业务处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求 request 进行处理。即 postHandle()是controller方法执行后执行的方法,在JSP视图执行前。如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  • afterCompletion()
    只有 preHandle 返回 true 才调用,. request或者response不能再跳转页面了。其在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。

4. 拦截器的简单案例(验证用户是否登录)

4.1 需求分析
  1. 有一个登录页面,需要写一个 controller 访问页面
  2. 登录页面有一提交表单的动作。需要在 controller 中处理。
    • 判断用户名密码是否正确
    • 如果正确:向 session 中写入用户信息
    • 返回登录成功
  3. 拦截用户请求,判断用户是否登录
    • 如果用户已经登录,放行
    • 如果用户未登录,跳转到登录页面
4.2 控制器代码
//登陆页面
@RequestMapping("/login")
public String login(Model model)throws Exception{
	return "login"; 
}

//登陆提交
//userid:用户账号,pwd:密码
@RequestMapping("/loginsubmit")
public String loginsubmit(HttpSession session, String userid, String pwd)throws Exception{
	//向 session 记录用户身份信息
	session.setAttribute("activeUser", userid);
	return "redirect:/main.jsp"; 
}

//退出
@RequestMapping("/logout")
public String logout(HttpSession session)throws Exception{
	//session 过期
	session.invalidate();
	return "redirect:index.jsp";
}
4.3 拦截器代码
public class LoginInterceptor implements HandlerInterceptor{
	@Override
	Public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
		//如果是登录页面则放行
		if(request.getRequestURI().indexOf("login.action") >= 0){
			return true; 
		}
		HttpSession session = request.getSession();
		//如果用户已登录也放行
		if(session.getAttribute("user") != null){
			return true; 
		}
		//用户没有登录挑战到登录页面
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
		
		return false; 
	} 
}

版权声明:本文为weixin_44270855原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。