今天springMVC开发遇到一个问题就是:
用了@RestController或者@ResponseBody注解之后,再用 拦截器拦截( HandlerInterceptor)的时候, 里面的 postHandle 的方法的参数ModelAndView 不管怎么弄都是null,很纠结,看了官网文档才知道加了这2个注解其实就不走视图转换而是走的这个类RequestResponseBodyMethodProcessor。
解决办法是加一个切面,然后在切面里面设置返回的参数到request(也可以设置到ThreadLocal)里面 然后拦截器里面在从request或者ThreadLocal里拿即可
切面类如下
@Aspect
@Component
public class GateWayAOP {
private ThreadLocal entityThreadLocal=new ThreadLocal();
//Controller层切点路径
@Pointcut("execution(* com.yihu.wlyy.web..*.*(..))")
public void controllerAspect() {
}
public GateWayAOP() {
//System.out.println("Observer---------------------------------------");
}
@Around("controllerAspect()")
public Object checkToken(ProceedingJoinPoint point) throws Throwable {
Object obj = null;
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
try {
obj = point.proceed();
}catch (Exception e){
e.printStackTrace();
}
request.setAttribute("returnObj",obj);//先把结果放进
return obj;
}
}
拦截器里面拿
@Component
public class GateWayInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(GateWayInterceptor.class);
@Autowired
private GcHttpLogDao httpLogDao;
@Autowired
private GcTokenDao gcTokenDaoDao;
/**
* preHandle:预处理回调方法
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
/**
* 后处理回调方法
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
String output = "";
if (modelAndView != null) {
output = JSONObject.fromObject(modelAndView.getModelMap()).toString();
} else {
Object returnObj = request.getAttribute("returnObj"); //再把结果放进
if (returnObj != null) {
output = JSONObject.fromObject(returnObj).toString();
}
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
// response.getOutputStream()
String token = request.getHeader("accesstoken");
String ip = NetworkUtil.getIpAddress(request);
saveHttpLog(ip,
JSONObject.fromObject(request.getParameterMap()).toString(),
output,
token,
request.getRequestURI(),
GcHttpLog.flagEm.success.getCode(),
null);
}
/**
* 整个请求处理完毕回调方法
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
这边要注意的是
因为每次请求都是新的request,所以是线程安全的
用ThreadLocal也是线程安全的