实现拦截器有两种方法:一是实现HandlerInterceptor接口,二是继承抽象类HandlerInterceptorAdapter
拦截器
package com.mingde.interceptor;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class UserInterceptor implements HandlerInterceptor{
//在执行控制层之前被调用,返回true表示不拦截他,对该内容进行放行,这样才会执行后续的拦截器,返回false将对其进行拦截,不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
//获取客户端发送的请求访问路径
StringBuffer requestURL = request.getRequestURL();
//将登录界面排除在外(不拦截登录界面)
if(requestURL.indexOf("toLogin")>=0 || requestURL.indexOf("login")>=0)return true;
//获取登录的用户(这里在页面登录时,后台进行对该用户存放进入session)
Object user = request.getSession().getAttribute("user");
//如果用户为登录的话就拦截住,不允许访问,如果用户有登录,不等于null就运行访问页面信息
if(null!=user)return true;
else{
request.setAttribute("msg", "请先登录!");
request.getRequestDispatcher("/WEB-INF/student/toLogin.jsp").forward(request, response);
}
/** 重点:如果有添加权限的话,那就先获取该用户的所有权限,然后然后根据要访问的地址来判断该用户是否有该访问地址的权限
* 如:http://localhost:8080/SpringMVC_Student/stu/delete.action
* 而用户只有 list、add的权限而没有delete(删除)的权限,那么就无法访问该地址
* 注意:访问地址时会先进入该拦截器的preHandle()方法,只有当返回的是true的话,才能进行下一步的操作,才能进入控制器进行删除操作
* **/
return false;
}
//在执行控制层方法后调用,但在视图层渲染之前被调用,如果上面的preHandle()方法返回false,则不会执行到这里
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView modelAndView)
throws Exception {
//可获取调用方法视图名
String viewName = modelAndView.getViewName();
//可获取调用方法model的数据
Map<String, Object> model = modelAndView.getModel();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
SpringMVC配置拦截器
方式一:使用拦截器拦截所有请求
<!-- 配置拦截器 (使用该拦截器拦截所有请求)-->
<mvc:interceptors>
<bean class="com.mingde.interceptor.UserInterceptor"></bean>
</mvc:interceptors>
方式二:使用拦截器拦截指定的控制器
<mvc:interceptors>
<mvc:interceptor>
<!-- 下面只拦截控制器interceptor2下的所有方法 ;映射的是某个要拦截控制器 ,若改为/**则为拦截所有的控制器 -->
<mvc:mapping path="/interceptor2/"/>
<!-- 配置自定义的拦截器 -->
<bean class="com.mingde.interceptor.UserInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
控制层
//进行登录
@RequestMapping("login")
public String login(User user,HttpSession session,Model model)throws Exception{
User find = ud.find(user);
if(null!=find){
session.setAttribute("user", find);
return "redirect:list.action";
}
model.addAttribute("msg","用户名或密码错误");
return "toLogin";
}
拦截器的生命周期
preHandle先执行再去执行控制器的方法,若preHandle返回false,则不会再执行下去(控制器和其他后面的都将不会执行),执行完控制器后再执行postHandle,然后在再跳到JSP页面,最后执行afterCompletion
拦截器的执行先后顺序
如果有多个拦截器的话,preHandler方法按在配置拦截器的先后顺序执行,而postHandle和afterCompletion则先执行后配置的再执行前配置的拦截器的方法
先执行先配置的preHandle→后执行后配置
preHandle
先执行后配置的postHandle→后执行先配置的postHandle
先执行后配置的afterCompletion→后执行先配置的afterCompletion