了解拦截器:
Servlet:处理Request请求和Response响应过滤器(Filter):对Request请求起到过滤的作用,****作用在Servlet之前****,如果配置为/*可以对所有的资源访问(servlet、js/css静态资源等)进行过滤处理。
监听器(Listener):实现了javax.servlet.ServletContextListener 接口的服务器端组件,它随Web应用的启动而启动,只初始化一次,然后会一直运行监视,随Web应用的停止而销毁
- 作用一:做一些初始化工作
- 作用二:监听web中的特定事件,比如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控,比如统计在线人数,利用HttpSessionLisener等。
拦截器(Interceptor):是SpringMVC、Struts等表现层框架自己的,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器方法(Handler)。从配置的角度也能够总结发现:serlvet、filter、listener是配置在web.xml中的,而interceptor是配置在表现层框架自己的配置文件中的在Handler业务逻辑执行之前拦截一次在Handler逻辑执行完毕但未跳转页面之前拦截一次在跳转页面之后拦截一次。
SpringMVC中自定义拦截器
实现HandlerInterceptor接口
package com.springmvc.interceptor;
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;
/**
* SpringMVC中自定义拦截器实现HandlerInterceptor接口
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 之前执行:Handler逻辑真正执行之前执行
* @param request
* @param response
* @param handler
* @return 代表是否放行,true放行,false中止
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HandlerMethod handlerMethod = (HandlerMethod)handler;
System.out.println("===============>>>preHandle0:" + ((HandlerMethod) handler).getMethod().getName());
return true;
}
/**
* 之中执行:Handler逻辑真正执行完成但尚未返回页面
* @param request
* @param response
* @param handler
* @param modelAndView
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
//modelAndView.addObject("nowDate","123");
//modelAndView.setViewName("error");
System.out.println("===============>>>postHandle0");
}
/**
* 之后执行:返回页面之后执行
* @param request
* @param response
* @param handler
* @param ex
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("===============>>>afterCompletion0");
}
}
配置拦截器:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.springmvc.interceptor.MyHandlerInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.springmvc.interceptor.MyHandlerInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.springmvc.interceptor.MyHandlerInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器链(Interceptor Chain):
拦截器链执行时,拦截器链正常流程测试
preHandle按照拦截器配置顺序执行
postHandle按照拦截器配置倒序执行
afterCompletion按照拦截器配置倒序执行
拦截器链中断流程测试
拦截器链中有中断时,整个链中的拦截器的postHandle都不会执行。
拦截器案例(登录控制):
需求
-
有一个登录页面,写一个Handler用于跳转登录页面
-
登录页面有一提交表单的动作。需要在Controller中处理
a) 判断用户名密码是否正确(admin/admin)
b) 如果正确,向session中写入用户信息(写入用户名username)
c) 跳转到登录成功页面
-
开发拦截器
a) 拦截用户请求,判断用户是否登录(登录页面跳转请求和登录提交请求不能拦截)
b) 如果用户已经登录则放行
c) 如果用户未登录则跳转到登录页面
实现
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>xxx系统登录</title>
<style>
div{
width:300px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin-top:-50px;
margin-left:-150px;
}
</style>
</head>
<body>
<div>
<form method="post" action="${pageContext.request.contextPath}/user/login.action">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"/><input type="submit" value="登录"/></td>
</tr>
</table>
</form>
</div>
</body>
</html>
后端处理:
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping("toLogin")
public String toLogin(Model model) {
return "login";
}
@RequestMapping("login")
public String login(Model model, String username, String password, HttpServletRequest request,HttpSession session) {
if("admin".equalsIgnoreCase(username) && "admin".equalsIgnoreCase(password)) {
session.setAttribute("username",username);
return "forward:/default/gotoResult.action";
}
return "redirect:toLogin.action";
}
}
拦截器:
package com.springmvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class RequestIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession httpSession = request.getSession();
Object username = httpSession.getAttribute("username");
if(username == null) {
// 未登录,跳转到登录页面
response.sendRedirect(request.getContextPath() + "/user/toLogin.action");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!--不拦截user下的请求-->
<mvc:exclude-mapping path="/user/**"/>
<bean class="com.springmvc.interceptor.RequestIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
web.xml配置:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!--应用启动直接跳转到登录页面-->
<welcome-file-list>
<welcome-file>/user/toLogin.action</welcome-file>
</welcome-file-list>
</web-app>