先说说为什么要使用springMVC的全局拦截器,比如 当我们在访问接口的时候,我们一般都会先判断这个用户是否登陆,我们就要在每个接口的前面都要判断一下,想想是不是很蛋疼,那工作量。。。
这时候,我们需要一个拦截器,他的作用就是,在每个请求的时候会先被它拦截,同时,还会得到request、response、请求url等等参数。
是不是很炫酷
话不多说,直接上代码
这个类是springMVC给我们实现的,只需要继承 HandlerInterceptorAdapter 类就可以了
HttpInterceptor.java
package com.mmall.controller.common.interceptor; import com.google.common.collect.Maps; import com.mmall.common.Const; import com.mmall.common.ServerResponse; import com.mmall.pojo.User; import com.mmall.util.CookieUtil; import com.mmall.util.JsonUtil; import com.mmall.util.RedisShardedPoolUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; import java.io.PrintWriter; import java.util.Arrays; import java.util.Iterator; import java.util.Map; /** * Created by 敲代码的卡卡罗特 */ public class AuthorityInterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(AuthorityInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //请求controller中的方法名 HandlerMethod handlerMethod = (HandlerMethod)handler; //解析HandlerMethod String methodName = handlerMethod.getMethod().getName(); String className = handlerMethod.getBean().getClass().getSimpleName(); StringBuffer requestParamBuffer = new StringBuffer(); Map paramMap = request.getParameterMap(); Iterator it = paramMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String mapKey = (String) entry.getKey(); String mapValue = ""; //request的这个参数map的value返回的是一个String[] Object obj = entry.getValue(); if (obj instanceof String[]){ String[] strs = (String[])obj; mapValue = Arrays.toString(strs); } //只是得到请求参数然后拼接成字符串 requestParamBuffer.append(mapKey).append("=").append(mapValue); } //对于拦截器中拦截manage下的login.do的处理,对于登录不拦截,直接放行 if(StringUtils.equals(className,"UserManageController") && StringUtils.equals(methodName,"login")){ logger.info("权限拦截器拦截到请求,className:{},methodName:{}",className,methodName);//如果是拦截到登录请求,不打印参数,因为参数里面有密码,全部会打印到日志中,防止日志泄露 return true; } logger.info("权限拦截器拦截到请求,className:{},methodName:{},param:{}",className,methodName,requestParamBuffer); // User user = (User)request.getSession().getAttribute(Const.CURRENT_USER); User user = null; String loginToken = CookieUtil.readLoginToken(request); if(StringUtils.isNotEmpty(loginToken)){ String userJsonStr = RedisShardedPoolUtil.get(loginToken); user = JsonUtil.string2Obj(userJsonStr,User.class); } if(user == null || (user.getRole().intValue() != Const.Role.ROLE_ADMIN)){ //返回false.即不会调用到controller里的方法 response.reset();//geelynote 这里要添加reset,否则报异常 getWriter() has already been called for this response response.setCharacterEncoding("UTF-8");//geelynote 这里要设置编码,否则会乱码 // response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json;charset=UTF-8");//geelynote 这里要设置返回值类型,因为全部是json接口。 PrintWriter out = response.getWriter(); //上传由于富文本的控件要求,要特殊处理返回值,这里面区分是否登录以及是否有权限 if(user == null){ if(StringUtils.equals(className,"ProductManageController") && (StringUtils.equals(methodName,"richtextImgUpload") )){ Map resultMap = Maps.newHashMap(); resultMap.put("success",false); resultMap.put("msg","请登录管理员"); out.print(JsonUtil.obj2String(resultMap)); }else{ out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户未登录"))); } }else{ if(StringUtils.equals(className,"ProductManageController") && (StringUtils.equals(methodName,"richtextImgUpload") )){ Map resultMap = Maps.newHashMap(); resultMap.put("success",false); resultMap.put("msg","无权限操作"); out.print(JsonUtil.obj2String(resultMap)); }else{ out.print(JsonUtil.obj2String(ServerResponse.createByErrorMessage("拦截器拦截,用户无权限操作"))); } } out.flush();//geelynote 这里要关闭流 out.close(); //geelynote return false;//这里虽然已经输出,但是还会走到controller,所以要return false } 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"); } }
解释一下上面的方法,一共需要实现三个方法。第一个方法意思是,每次请求之前先被它拦截到,然后返回true的时候继续实现我们controller层的业务,接口完成之后会继续到第二个方法,然后再到第三个方法。
那第二个方法和第三个方法有什么区别呢?????
第二个方法是controller层不报错的情况下才会走这个方法,如果报错就不走,但是第三个方法肯定会走。
方法里面的业务逻辑是我随便写的,可以忽略,就是得到request的url和参数。然后日志记录下 然后判断是否登陆,是否是管理员,然后会根据一些特殊的请求的url和方法做一些特殊的处理 比如说 请求登陆接口的时候就放行 等等~~~
最后,我们需要在spring-servlet.xml中声明一下
<mvc:interceptors>
<!-- 定义在这里会拦截指定的请求url -->
<mvc:mapping path="/manage/**"/>
<bean class="com.mmall.common.HttpInterceptor" />
</mvc:interceptors>
注意一下:这里面你可以在拦截器里面写具体拦截或者不拦截的方法也可以在spring-servlet.xml中写
大功告成!!!