1. 拦截器相关概念
- 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)。底层采用的是aop的思想
- 从配置的角度也能够总结发现:serlvet、filter、listener是配置在web.xml中的,而interceptor是配置在表现层框架自己的配置文件中的
- 在Handler业务逻辑执行之前拦截一次
- 在Handler逻辑执行完毕但未跳转页面之前拦截一次
- 在跳转页面之后拦截一次
2. 自定义拦截器
步骤:
- 实现接口HandlerInterceptor
- 重写方法:
- preHandle:handler之前执行,返回true表示放行
- postHandle:handler逻辑真正执行完成但尚未返回页面
- afterCompletion:返回页面之后
- 自定义拦截器如下:
public class MyHandlerInterceptor implements HandlerInterceptor {
// 在Controller控制器中的Handler方法执行前执行
// 返回值true,执行后续的请求(请求一:执行后续的其他的拦截器,情况二:所有的拦截器搜执行完毕,并放行执行Handler方法)
// 返回值false
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle执行了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion执行了");
}
}
- springmvc.xml配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/**为拦截浏览器所有的请求-->
<mvc:mapping path="/**"/>
<bean id="interceptor" class="com.szz.interceptor.MyHandlerInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
- handler处理请求(Controller层)
@Controller
public class DefaultController {
/**
* 定义方法, 相当于以前Servlet中用于处理请求的方法
*/
@RequestMapping("gotoResult")
public ModelAndView gotoResult(ModelAndView modelAndView){
System.out.println("gotoResult执行了");
// 封装数据
modelAndView.addObject("nowDate",new Date());
//指定页面
modelAndView.setViewName("result");
return modelAndView;
}
}
3. 拦截器登录案例
- 需求分析
- 有一个登录页面,判断用户是否登录,若未登录跳转到登录界面,并写一个Handler用于接收登录请求,实现页面跳转。
- 实现步骤:
- 登录页面有一个提交表单的动作,需要在Controller中做如下处理:
- 判断用户名密码是否正确(zhangsan/123)
- 如果正确,向session中写入用户信息(写入用户名username),跳转到登录成功页面
- 如果不正确, 跳转到登录页面
- 开发拦截器:
- 拦截用户请求,判断用户是否登录(登录页面跳转请求和登录提交请求不能拦截)
- 如果用户已经登录则放行
- 如果用户未登录则跳转到登录页面
3.1 各部分代码设计
- index.jsp 登录页面:
<fieldset>
<h3>测试登录案例</h3>
<form method="post" action="${pageContext.request.contextPath}/user/login.action">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</fieldset>
- UserController
@Controller
@RequestMapping("default")
public class DefaultController {
/**
* 定义方法, 相当于以前Servlet中用于处理请求的方法
*/
@RequestMapping("login")
public String login(String username, String password, HttpServletRequest request){
// 业务判断
if ("zhang3".equals(username)&&"123".equals(password)){
// 登录成功
request.getSession().setAttribute("username",username);
//跳转show页面, 显示数据
return "redirect:/account/findAll.do";
}else {
// 登录失败,跳转到登录页面
return "redirect:http://localhost:8080/index.jsp";
}
}
}
- AccountController负责查询,并跳转到显示页面:
@Controller
@RequestMapping("account")
public class AccountController {
@RequestMapping("findAll")
public String findAll(ModelMap modelMap){
modelMap.addAttribute("message","模拟查询出2条信息");
return "result";
}
}
- 拦截器LoginInterceptor
/*
首先判断是否登录了,如果登录了,放行,如果没有登录,跳转到登录页面
细节:
判断是否是登录请求,如果是登录请求,放行
如果不是登录请求: 判断session中是否存储了用户信息
*/
public class LoginInterceptor implements HandlerInterceptor {
// 用户登录拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器执行了");
// 1.获取当前拦截的请求信息
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
// 2.如果当前请求是否是登录请求,如果是放行
if ("/default/login.do".equals(requestURI)){
return true;
}
// 3.如果当前用户已经登录,用户执行的操作都放行
Object username = request.getSession().getAttribute("username");
if (username == null){
// 用户未登录,跳转到登录页面
response.sendRedirect(request.getContextPath()+"/index.jsp");
return false;
}else {
// 用户登录,放行
return true;
}
}
}
- springmvc.xml的配置
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/**为拦截浏览器所有的请求-->
<mvc:mapping path="/**"/>
<bean id="interceptor" class="com.szz.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>