一:统一处理访问请求(配置拦截器进行处理HandlerInterceptor):
一般情况下,controller中入参很少需要HttpServletRequest和HttpServletResponse参数,但是有时我们需要对访问参数进行日志打印,查看请求ip或入参等信息时,就需要在入参加上request和response,这样每个controller都会增加这两个参数,为了方便维护,可以配置一个interceptor进行统一拦截处理。
package com.test.demo.interceptor.logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
/**
* Created by fz
*/
public class LoggerIntercept implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(LoggerIntercept.class);
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object
o) throws Exception {
String method = httpServletRequest.getMethod();
String remoteAddr = httpServletRequest.getHeader("X-Forwarded-For");
String requestURI = httpServletRequest.getRequestURI();
String queryString = httpServletRequest.getQueryString();
logger.info("请求方法={},请求ip={},请求URI={},QueryString={},请求时间={}",
method, remoteAddr,requestURI, queryString, LocalDateTime.now());
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
/*无法获取到@ResponseBody的返回值*/
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
/*pass*/
}
}
在spring-web.xml中进行配置:
二:返回值/响应体(@ControllerAdvice,ResponseBodyAdvice)
ResponseBodyAdvice是spring4.1的新特性,其作用是在响应体写出之前做一些处理;比如,修改返回值、加密等。
我在项目中的用到@ControllerAdvice,ResponseBodyAdvice的目的,是为每个请求的返回json中修改一个属性值。
package org.springframework.web.servlet.mvc.method.annotation;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
/**
* Allows customizing the response after the execution of an {@code @ResponseBody}
* or an {@code ResponseEntity} controller method but before the body is written
* with an {@code HttpMessageConverter}.
Implementations may be may be registered directly with
* {@code RequestMappingHandlerAdapter} and {@code ExceptionHandlerExceptionResolver}
* or more likely annotated with {@code @ControllerAdvice} in which case they
* will be auto-detected by both.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public interface ResponseBodyAdvice {
/**
* Whether this component supports the given controller method return type
* and the selected {@code HttpMessageConverter} type.
* @param returnType the return type
* @param converterType the selected converter type
* @return {@code true} if {@link #beforeBodyWrite} should be invoked, {@code false} otherwise
*/
boolean supports(MethodParameter returnType, Class> converterType);
/**
* Invoked after an {@code HttpMessageConverter} is selected and just before
* its write method is invoked.
* @param body the body to be written
* @param returnType the return type of the controller method
* @param selectedContentType the content type selected through content negotiation
* @param selectedConverterType the converter type selected to write to the response
* @param request the current request
* @param response the current response
* @return the body that was passed in or a modified, possibly new instance
*/
T beforeBodyWrite(T body, MethodParameter returnType, MediaType selectedContentType,
Class> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
实战代码如下:
package com.test.demo.interceptor.logger;
import com.test.demo.platform.common.result.base.Result;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
* Created by fz
*/
@ControllerAdvice
public class LoggerAdvice implements ResponseBodyAdvice {
private Logger logger = LoggerFactory.getLogger(LoggerAdvice.class);
@Override
public boolean supports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType) {
/*支持所有方法*/
return true;
}
@Override
public Result beforeBodyWrite(Result body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
String methodName = returnType.getMethod().getName();
logger.info("{}方法返回值={}", methodName, JSON.toJSONString(body));
return body;
}
}
result:
package com.test.demo.platform.common.result.base;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@ApiModel("服务端响应报文格式")
public class Result implements Serializable {
private static final long serialVersionUID = -1791232625706807828L;
@ApiModelProperty("响应头数据")
@JSONField(
name = "head",
ordinal = 0
)
private ResultHead head;
@ApiModelProperty("响应体数据")
@JSONField(
name = "body",
ordinal = 1
)
protected T body;
public Result() {
}
public T getBody() {
return this.body;
}
public void setBody(T body) {
this.body = body;
}
public ResultHead getHead() {
return this.head;
}
public void setHead(ResultHead head) {
this.head = head;
}
public String toString() {
return "Result{head=" + this.getHead().toString() + ",data=" + this.body + '}';
}
}