本文章主要内容如下
拦截器可以干什么 怎么做
拦截器可以干什么
日志记录:记录日志,以便进行信息监控、信息统计、计算PV(Page View)等。
权限检查:如登录检测;
性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,
从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,
只要是多个处理器都需要的即可使用拦截器实现。
OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。
拦截器本质也是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。
怎么实现|怎么做
1 拦截器接口
public interface HandlerInterceptor {
boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler)
throws Exception;
void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(
HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex)
throws Exception;
}
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
2 配置文件设置
<mvc:resources mapping="/resources/**" location="/resources/"></mvc:resources>
<!--
register "global" interceptor beans to apply to all registered HandlerMappings .
Each inteceptor must implement the org.springframework.web.servlet.HandlerInterceptor or
org.springframework.web.context.request.WebRequestInterceptor interface
-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/css/**" />
<mvc:exclude-mapping path="/js/**" />
<mvc:exclude-mapping path="/images/**" />
<bean class="com.fpx.common.auth.mgt.framework.interceptor.ContextInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
或
<mvc:interceptors>
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
<bean class="com.host.app.web.interceptor.AllInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
或
<bean xmlns="http://www.springframework.org/schema/beans" id="authenticateInterceptor"
class="com.javaplus.castle.authenticate.AuthenticateInterceptor">
<property name="uncheckUrls">
<list>
<value>/index</value>
<value>/doLogin</value>
</list>
</property>
</bean>
<!-- 注册 DefaultAnnotationHandlerMapping
如果使用了<mvc:annotation-driven />或者<annotation-driven />它会自动注册
DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter
这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。
当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。-->
<beans:bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<beans:property name="interceptors">
<beans:list>
<beans:ref bean="authenticateInterceptor"/>
<!--<beans:ref bean="logInterceptor"/>-->
</beans:list>
</beans:property>
</beans:bean>
``<servlet>
<servlet-name>airman</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/springmvc.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>airman</servlet-name>
<url-pattern>/</url-pattern> 拦截所有
</servlet-mapping>
<!--这一部分是3.0新加入的特性,加入这个标记会告诉spring此处是本地资源文件不会当做Action处理。如果不加入这个配置引用的js和css将无法加载-->
<resources mapping="/resources/**" location="/resources/"/>
<resources mapping="/ext-4.2.1.883/**" location="/ext-4.2.1.883/"/>
<resources mapping="/common/**" location="/common/"/>
<resources mapping="/CAdminLte/**" location="/CAdminLte/"/>
<view-controller path="/" view-name="redirect:/index"/>
拦截器的实现代码
public class AuthenticateInterceptor extends HandlerInterceptorAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticateInterceptor.class);
private List<String> uncheckUrls;
public void setUncheckUrls(List<String> uncheckUrls) {
this.uncheckUrls = uncheckUrls;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
String contextPath = request.getContextPath();
String requestURI = request.getRequestURI();
LOGGER.info("RequestURI:" + requestURI);
for (String url : uncheckUrls) {
if (requestURI.startsWith(contextPath+url)) {
return true;
}
}
//获取登录用户信息
Account human = (Account) session.getAttribute(CastleSecurityManager.CURRENT_USER);
if (human == null) {
//跳转登录页面
LOGGER.info("human == null RequestURI:" + requestURI);
response.sendRedirect("redirect:/index");
return false;
}
return true;
}
}
@Controller
public class LoginController {
Log log = LogFactory.getLog(this.getClass());
@Autowired(required = false)
private IUserService userService;
@RequestMapping(value = "/index")
public String logincheck(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) {
HttpSession session = request.getSession();
Account human = (Account) session.getAttribute(CastleSecurityManager.CURRENT_USER);
if (human == null) {
return "login";
} else {
return "index";//返回到jsp
}
}
@RequestMapping(value = "/doLogin")
public ModelAndView doLogin( HttpServletRequest request,HttpServletResponse response, @RequestParam Map<String, Object> conditions, ModelAndView mv) {
HttpSession session = request.getSession();
String account = String.valueOf(conditions.get("account"));
String pwd = String.valueOf(conditions.get("pwd"));
Account user = userService.checkLogin(account, pwd);
if (user == null) {
mv.setViewName("login");
mv.addObject("errorMessage", "用户名或密码错误");
return mv;
}
session.setAttribute(CastleSecurityManager.CURRENT_USER, user);
}
其他要点
redirect:/index是返回到requestmapping的请求中
view-name=”index”是到jsp里
getRequestDispatcher是服务器内部跳转,地址栏信息不变,只能跳转到web应用内的网页。
sendRedirect是页面重定向,地址栏信息改变,可以跳转到任意
if(controller instanceof UserLogin){
Object user = request.getSession().getAttribute(“user”);
if(user == null){
log.debug(“———–未登录访问 跳回登录页面—-“);
request.getRequestDispatcher(“/home/loginUI”).forward(request, response);
return false;
}
}
HttpSession session = httpServletRequest.getSession();
SysUser user = (SysUser) session.getAttribute("loginsucess");
if (user != null){
return true;
}
//执行到这里说明没有session,需要拦截
httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(httpServletRequest,httpServletResponse);
return false;
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
boolean flag = false;
String url = request.getRequestURL().toString();
//不拦截上面定义的路径
for (String str : IGNORE_URL) {
if (url.contains(str)) {
flag = true;
break;
}
}
if (!flag) {
User user = (User)request.getSession().getAttribute(“users”);
if (user != null)
flag = true;
else
response.sendRedirect(“/login.jsp”);
return false;
}
return true;
}
request.getRequestDispatcher("/third?name=jay").forward(request, response);
或
request.getRequestDispatcher("third?name=jay").forward(request, response);
或
this.getServletContext().getRequestDispatcher("/third?name=jay").forward(request, response);
response.sendRedirect("http://www.baidu.com");
本文章参考以下文章
http://www.mamicode.com/info-detail-400138.html
getRequestDispatcher 和sendRedirect区别
http://weidongke123-126-com.iteye.com/blog/1461526
SpringMVC中使用Interceptor拦截器
http://elim.iteye.com/blog/1750680
SpringMVC 常用配置说明
http://blog.csdn.net/strivezxq/article/details/45457067
spring拦截器、与filter的区别
http://blog.csdn.net/zqlsnow/article/details/52946826
SpringMVC拦截器(资源和权限管理)
http://blog.csdn.net/tonytfjing/article/details/39207551
spring mvc拦截器和的详解
http://www.cnblogs.com/yangzhilong/p/3725849.html
spring拦截器(里面有模糊匹配和不拦截地址配置代码)
http://www.cnblogs.com/fdzfd/p/5715699.html