SpringMVC-异常处理和拦截器

异常处理

概述

  • SpringMVC也有自己的异常处理机制。SpringMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver接口,当然这也包括使用Spring已经为我们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver;另一种是使用注解的方式实现一个专门用于处理异常的Controller即
    @ExceptionHandler注解。除此之外还有第三种处理方式,使用
    @ControllerAdvice注解。下面我们将通过代码来展示异常处理器的应用。

异常处理步骤:

  1. 新建maven web项目
  2. 加入依赖
  3. 新建一个自定义异常类 MyUserException , 再定义它的子类NameException ,AgeException
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  1. 在controller抛出NameException , AgeException
    在这里插入图片描述

  2. 创建一个普通类,作用全局异常处理类

    1. 在类的上面加入@ControllerAdvice
    2. 在类中定义方法,方法的上面加入@ExceptionHandler
      在这里插入图片描述
  3. 创建处理异常的视图页面

  4. 创建springmvc的配置文件
    1)组件扫描器 ,扫描@Controller注解
    2)组件扫描器,扫描@ControllerAdvice所在的包名
    3)声明注解驱动在这里插入图片描述

拦截器

  • 拦截器 Interceptor 的拦截功能是基于 Java 的动态代理来实现的,Interceptor拦截器用于拦截Controller层接口,表现形式有点像Spring的AOP,但是AOP是针对单一的方法。Interceptor是针对Controller接口以及可以处理的request和response对象。

  • 在SpringMVC 中定义一个Interceptor是比较非常简单的,主要有两种方式:

  • 第一种是实现HandlerInterceptor 接口,或者是继承实现了HandlerInterceptor 接口的类;第二种实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类

  • SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

过滤器与拦截器的区别:拦截器是AOP思想的具体应用。

过滤器
servlet规范中的一部分,任何java web工程都可以使用
在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
拦截器
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的

HandlerInterceptor接口

HandlerInterceptor接口中的三个方法,对应的作用说明如表所示。
在这里插入图片描述

  • SpringMVC还提供了HandlerInterceptorAdapter 抽象类,该类也是HandlerInterceptor的子类,在实现了HandlerInterceptor的三个函数后还增加了一个函数。
    (1)preHandle: 在执行controller处理之前执行,返回值为boolean ,返回值为true时接着执行postHandle和afterCompletion,如果返回值为false则中断执行。
    (2)postHandle:在执行controller的处理之后ModelAndView的处理前执行。
    (3)afterCompletion :在DispatchServlet执行完ModelAndView之后执行。
    (4)afterConcurrentHandlingStarted:这个方法会在Controller方法异步执行时开始执行,而Interceptor的postHandle方法则是需要等到Controller的异步执行完才能执行,只要继承这个类并实现其方法就可以了。

  • 注意:preHandle方法的返回值表示是否继续触发后面的请求,即是否拦截,如果返回值为true则放行,否则拦截将不再继续运行。

  • 在WEB-INF/springMVC-config.xml配置文件中,需要配置拦截器并且标注出拦截规则和对应的自定义拦截器。

WebRequestInterceptor接口

  • WebRequestInterceptor接口中也定义了三个方法,同HandlerInterceptor接口的用法相似,它也是通过复写这三个方法来对用户的请求进行拦截处理的,不同的是WebRequestInterceptor接口中的preHandle方法没有返回值,而且WebRequestInterceptor的三个方法的参数都是WebRequest,。这个WebRequest 到底是什么呢?其实WebRequest 是 Spring 中定义的一个接口,它里面的方法定义跟 HttpServletRequest 类似,在WebRequestInterceptor中对 WebRequest 进行的所有操作都将同步到 HttpServletRequest 中,然后在当前请求中依次传递。

  • 在 Spring 框架之中,还提供了一个和WebRequestInterceptor接口长的很像的抽象类,那就是WebRequestInterceptorAdapter,其实现了AsyncHandlerInterceptor接口,并在内部调用了WebRequestInterceptor接口,如表所示。

在这里插入图片描述

拦截器链

注意:当多个拦截器一起执行时,则根据拦截器声明的先后顺序执行,直到拦截器的方法都执行完了,才会去执行真正资源

自定义拦截器

那如何实现拦截器呢?
想要自定义拦截器,必须实现 HandlerInterceptor 接口。

  1. 新建一个Moudule , springmvc-07-Interceptor , 添加web支持
  2. 配置web.xml 和 springmvc-servlet.xml 文件
  3. 编写一个拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
    //在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
    public boolean preHandle(HttpServletRequest httpServletRequest,
                             HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("------------处理前------------");
        return true;
    }
    //在请求处理方法执行之后执行
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse, Object o, ModelAndView
                                   modelAndView) throws Exception {
        System.out.println("------------处理后------------");
    }
    //在dispatcherServlet处理后执行,做清理工作.
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse, Object o, Exception e) throws
            Exception {
        System.out.println("------------清理------------");
    }
}
  1. 在springmvc的配置文件中配置拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--/** 包括路径及其子路径-->
        <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-
        ->
        <!--/admin/** 拦截的是/admin/下的所有-->
        <mvc:mapping path="/**"/>
        <!--bean配置的就是拦截器-->
        <bean class="com.kuang.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

path的讲解:
path=”/” 什么都不拦截
path=”/*”能拦截:/dept.action,不能拦截/dept/list.action
path=”/**”能拦截所有
path=”/dept/*” 能拦截/dept/下面的所有

或者用注解配置

在配置类中,需要首先配置拦截器Bean,然后重写addInterceptors方法注册拦截器,示例代码如下:

/**
* 配置拦截器Bean
 */
@Bean
public MyInteceptor MyInteceptor() {
	return new MyInteceptor();
}
/**
 * 重写addInterceptors方法注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
	registry.addInterceptor(MyInteceptor());
}
  1. 编写一个Controller,接收请求
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
//测试拦截器的控制器
@Controller
public class InterceptorController {
    @RequestMapping("/interceptor")
    @ResponseBody
    public String testFunction() {
        System.out.println("控制器中的方法执行了");
        return "hello";
    }
}
  1. 前端 index.jsp
<a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>
  1. 启动tomcat 测试一下!
    在这里插入图片描述

验证用户是否登录 (认证用户)

实现思路

  1. 有一个登陆页面,需要写一个controller访问页面。
  2. 登陆页面有一提交表单的动作。需要在controller中处理。判断用户名密码是否正确。如果正确,
    向session中写入用户信息。返回登陆成功。
  3. 拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面
  4. 编写一个登陆页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<h1>登录页面</h1>
<hr>
<body>
<form action="${pageContext.request.contextPath}/user/login">
    用户名:<input type="text" name="username"> <br>
    密码: <input type="password" name="pwd"> <br>
    <input type="submit" value="提交">
</form>
</body>
</html>
  1. 编写一个Controller处理请求
package com.kuang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/user")
public class UserController {
    //跳转到登陆页面
    @RequestMapping("/jumplogin")
    public String jumpLogin() throws Exception {
        return "login";
    }

    //跳转到成功页面
    @RequestMapping("/jumpSuccess")
    public String jumpSuccess() throws Exception {
        return "success";
    }

    //登陆提交
    @RequestMapping("/login")
    public String login(HttpSession session, String username, String
            pwd) throws Exception {
// 向session记录用户身份信息
        System.out.println("接收前端===" + username);
        session.setAttribute("user", username);
        return "success";
    }

    //退出登陆
    @RequestMapping("logout")
    public String logout(HttpSession session) throws Exception {
// session 过期
        session.invalidate();
        return "login";
    }
}
  1. 编写用户登录拦截器
package com.kuang.interceptor;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws ServletException,
            IOException {
// 如果是登陆页面则放行
        System.out.println("uri: " + request.getRequestURI());
        if (request.getRequestURI().contains("login")) {
            return true;
        }
        HttpSession session = request.getSession();
// 如果用户已登陆也放行
        if (session.getAttribute("user") != null) {
            return true;
        }
// 用户没有登陆跳转到登陆页面
        request.getRequestDispatcher("/WEBINF/
                jsp / login.jsp").forward(request, response);
        return false;
    }

    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse, Object o, ModelAndView
                                   modelAndView) throws Exception {

    }

    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse, Object o, Exception e) throws
            Exception {
    }
}
  1. 在Springmvc的配置文件中注册拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean id="loginInterceptor"
              class="com.kuang.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值