Spring MVC中,配置拦截器有两种方式,第一种是在配置文件springmvc-servlet.xml中,使用mvc:interceptors标签来实现;第二种方式是,直接向HandlerMapping的实现类中,注入拦截器。
首先,要写一个拦截器,该拦截器要实现HandlerInterceptor接口(本例中使用的是HandlerInterceptorAdapter,该类最终也是实现了HandlerInterceptor接口)
public class ParamValidateInterceptor extends HandlerInterceptorAdapter {
@Getter
@Setter
private String requisiteParam;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(requisiteParam.equals(request.getParameter("requisiteParam"))) {
return true;
}else {
response.sendRedirect("https://blog.csdn.net/fyk844645164?t=1");
return false;
}
}
}
该拦截器的意思是,在处理前端请求之前,如果带入的参数(requisiteParam)的值,与配置的值相同,则可以进行请求处理,否则重定向到我的博客地址。
现在,使用第一种方式,上一步中的拦截器注入到Spring MVC中的请求链中,即在springmvc-servlet.xml中增加配置如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/admin/**"/>
<bean id="paramValidateInterceptor" class="com.fyk.core.config.interceptors.ParamValidateInterceptor">
<property name="requisiteParam" value="fyk"/>
</bean>
</mvc:interceptor>
</mvc:interceptors>
以上配置中,mvc:mapping的意思就是所有的请求都会走这个拦截器;而mvc:exclude-mapping的意思就是在这些所有请求中,要排除掉的请求,即mvc:exclude-mapping配置的请求地址,不会走该拦截器;
说明:可以配置多个mvc:interceptor拦截器;
使用第二种方式配置拦截器就是直接在RequestMappingHandlerMapping(HandlerMapping的一个实现类,在DispatcherServlet.properties配置文件中可以找到,详见配置DispatcherServlet)中增加拦截器,先上代码:
<bean id="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.fyk.core.config.interceptors.ParamValidateInterceptor">
<property name="requisiteParam" value="fyk"/>
</bean>
</list>
</property>
</bean>
使用这种方式配置的拦截,经常会遇到一个问题:RequestMappingHandlerMapping中配置的拦截器为什么不起作用?
原因很简单,在配置DispatcherServlet中已经说明,默认的配置可以被后来的配置覆盖,我们这里也是使用这种方式,用自定义的handlerMapping来覆盖默认的配置,那为什么还不起作用呢?——实际上没有覆盖到默认的bean。
这里Spring MVC中要覆盖默认的bean,那得知道这个bean的名字是什么,在本例中,我使用的bean的id为:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping。为什么知道这个id就可以覆盖默认的配置中的bean呢?同样在配置DispatcherServlet中有说明,我们可以获取到当前DispatcherServlet的上下文,从而看下这个上下文中,配置的默认的bean的名字是什么:
@PostMapping("/hello")
public String sayHello(HttpServletRequest request, String name) {
WebApplicationContext context = RequestContextUtils.findWebApplicationContext(request);
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
log.info(beanName+"==");
}
return String.format("%s,你好!", name);
}
比如,在这里,我把这个上下文中的bean都输出来了,从这些个名称中,我知道了我要覆盖的bean的名字是org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping。
可能由于Spring版本不一样,这里得到的bean的名称还可能不一样。