文章目录
一、什么是拦截器
原理图:
如上图所示,配置了拦截器之后,我们的Controller在被访问前,会先被拦截器中的preHandle()方法进行拦截,Controller在被访问后会被拦截器的postHandler()进行拦截,最后还会被拦截器的afterCompletion()方法处理。
在springmvc中,给我们提供了拦截器(HandlerInterceptor接口)。
拦截器的作用是用于权限验证。
类似于传统的javaweb中的过滤器。springmvc中的拦截器是AOP的一个体现。
通过拦截器我们可以轻松的实现页面之间的权限的验证,还可以造请求访问前后做一些私人订制。
使用拦截器的好处:
- 采用横切的方式进行拦截处理
- 不会对原本的代码产生丝毫的影响
- 使用简单,方便、快捷
二、拦截器的使用
在springmvc中给我们提供了一个接口HandlerInterceptor,当一个类实现了该接口之后,那么该类便成了拦截器,最后我们还需要造spring-mvc.xml中配置 <mvc: interceptors>。
第一步:实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
}
比较有意思的是,该接口并不强制我们写任何方法,这个从侧面说明了,拦截器其实可以什么也不做
第二步:实现方法
我们这个主要讲一下preHandle()方法
public class MyInterceptor implements HandlerInterceptor {
//返回值为false,则说明禁止访问
//返回值为true,则说明允许访问
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String pathInfo = request.getRequestURI();
System.out.println(pathInfo);
if (pathInfo.contains("login")){
return true;
}
if (request.getSession().getAttribute("username")==null){
response.sendRedirect("/index.jsp");
}else{
return true;
}
System.out.println("方法执行前.......");
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("方法执行后.......");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("清理.......");
}
}
我在preHandle()中简单的实现了一个页面权限的验证(登录后可以访问,否自直接去登陆页面)
我们可以发现方法的参数是request和response,这就意味值拦截器的作用就大了去了。
preHandle()方法时有返回值的:
false,则说明禁止访问
true,则说明允许访问
我们在拦截器中一般都会使用重定向和请求转发将合法或不合法的请求送到它应该去的地方。
第三步:配置<mvc: interceptors>
spring-mvc.xml:
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/* 表示/下面的所有请求都会被拦截器处理(所有的请求)-->
<mvc:mapping path="/*/*"/>
<!--不拦截指定的页面-->
<!--<mvc:exclude-mapping path="/index*"/>-->
<!--定位连接器类-->
<bean class="com.sdpei.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<mvc:mapping path=""/>:配置进行拦截的请求
<mvc:exclude-mapping path=""/>:配置不进行拦截的请求
< bean class=""/>:定位拦截器
三、解决因配置了拦截器,导致静态资源失效的问题
就整个问题,真的是折腾了我好久,也怪我的Tomcat不争气,时而好用,时而不好用。
解决因配置了拦截器,导致静态资源失效的方法有二种。但是其中的一种我试了,不管用(很可能是因为我的Tomcat的问题)
方法一 :(推荐)
<mvc:default-servlet-handler />和web.xml相结合
在springmvc中因为DispatcherServlet的使用,导致所有的请求资源不会根据后缀名区分,没有区别,静态资源依然会被拦截,所以有如下的解决方法
spring-mvc.xml:声明过滤(不处理)静态资源的配置
<mvc:default-servlet-handler />
只要你使用了DispatcherServlet,那么这个是必须要写的,不然静态资源会404.
如果你还使用了HandlerInterceptor ,那么下面也是必须操作
web.xml:声明不被连接的资源类型(路径)
<!--因为配置了拦截器,用来过滤静态资源的-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>/staticSources/*"</url-pattern>
</servlet-mapping>
上面的配置也一定要写在DispatcherServlet的前面。
方法二:
spring-mvc.xml:配置对静态资源的访问
<!-- 对静态资源文件的访问-->
<mvc:resources mapping="/images/*" location="/images/"/>
<mvc:resources mapping="/css/*" location="/css/" />
<mvc:resources mapping="/js/*" location="/js/" />
<mvc:resources mapping="/favicon.ico" location="favicon.ico" />
四、你可能会遇到的问题
Error:Invalid mapping pattern detected: /**/.css ^ No more pattern data allowed after {…} or ** pattern element
原因:
路径通配问题,查找发现是spring升级到5.3之后路径通配发生了变化,官方给出的解释是:
“In Spring MVC, the path was previously analyzed by AntPathMatcher, but it was changed to use PathPatternParser introduced in WebFlux from Spring 5.3.0.”
通配符发生了变化。把/** 改为 /*即可。