SpringMvc(拦截器)
1、SpringMvc拦截器
1.1、SpringMvc拦截器的概念
拦截器采用AOP的设计思想,它跟过滤器类似,用来拦截处理方法在之前和之后执行的一些和主业务没有关系的一些公共功能。
比如:权限控制,日志,异常处理,记录方法的执行时间等等。
要定义一个拦截器,我们必须实现 HandlerInterceptor 接口
1.2、定义一个SpringMvc拦截器
1、定义一个方法,并实现HandlerInterceptor接口。
2、spring的配置文件中引入当前定义的拦截器。
3、重写相应的方法。
<!-- 引入自定义的拦截器 -->
<mvc:interceptors>
<bean class="interceptor.MyInterceptor"></bean>
</mvc:interceptors>
package interceptor;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
/**
* @author dujlc
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 在请求执行前执行
*
* @param request 可以在请求进来之前更改 request 中的属性值
* @param response
* @param handler 封装了当前处理方法的信息
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/*
当经过controller的请求映射的处理方法映射时,实现类才是HandlerMethod
如果是经过视图控制器的话,实现类是 ParameterizableViewController
所以这块强制转换需要添加条件
*/
if (handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod)handler;
}
/*System.out.println("类:["+handlerMethod.getBean().getClass().getName()+"]\n" +
"方法名["+handlerMethod.getMethod().getName()+"]\n" +
"参数["+ Arrays.toString(handlerMethod.getMethodParameters()) +"]");*/
System.out.println("前置处理");
return true;
}
/**
* 如果preHandle返回false,则不会运行该方法
* 在请求执行后执行,在视图渲染之前完成
* 当处理方法出现了异常则不会执行方法
* @param request
* @param response 可以在方法执行后去更改response中的信息
* @param handler 封装了当前处理方法的信息
* @param modelAndView 封装了Model和View,当请求结束后可以修改model里卖弄的数据或者新增model里面的数据,也可以修改view
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("后置处理");
}
/**
* 如果preHandle返回false,则不会运行该方法
* 在视图渲染之后执行 相当于 try catch finally中的finally
* @param request
* @param response
* @param handler
* @param ex 在这里边可以做一些记录日志的功能
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("编译后置处理");
}
}
2、过滤器和拦截器的区别
2.1、过滤器和拦截器的执行顺序
我们在这里再创建一个过滤器和上面的拦截器同时执行,看结果
示例如下:
package cool.ale.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author dujlc
*/
@WebFilter("/*")
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器前执行");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤器后执行");
}
public void destroy() {
}
}
2.2、过滤器和拦截器的区别
1、过滤器是基于函数回调的,拦截器是基于java反射的。
2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。拦截器依赖于SpringMvc。
3、过滤器对于所有的请求都起作用(就比如jsp就只有过滤器可以),而拦截器只对SpringMvc请求起作用。
4、拦截器可以访问处理方法的上下文(就比如类名,方法名,方法参数等等),而过滤器不可以。
3、使用拦截器实现登录权限的拦截
1、定义一个拦截器。
2、设置拦截的jsp,除了get请求的login页面不拦截之外。
代码示例:
package cool.ale.interceptor;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @author dujlc
*/
public class CheckLoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// 如果没有登录
if(StringUtils.isEmpty(session.getAttribute("userName"))){
response.sendRedirect(request.getContextPath() + "/login");
return false;
}else{
return true;
}
}
}
<!-- 引入自定义的拦截器,在Spring的配置文件中 -->
<mvc:interceptors>
<!-- 直接配置一个Bean会拦截SpringMvc的所有请求 -->
<bean class="cool.ale.interceptor.MyInterceptor"></bean>
<!-- 如果不是所有的请求都要拦截,可以加一个子拦截器 <mvc:interceptor> -->
<mvc:interceptor>
<!-- 需要拦截的请求 -->
<mvc:mapping path="/**"/>
<!-- 不需要拦截的请求 (只会拦截Get请求) -->
<mvc:exclude-mapping path="/login"/>
<!-- 拦截器 -->
<bean class="cool.ale.interceptor.CheckLoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>