HttpServletRequestWrapper采用装饰模式重新封装request,并打印request请求相关参数。



说明: 本篇文章采用过滤器的方式,通过HttpServletRequestWrapper重新封装request,以用来实现打印请求相关日志的操作。其中,该日志过滤器主要针对
POST中传值在BODY中的方式,来实现相关日志打印的操作。


具体的说明以及代码如下:


1。 RequestLoggingFilter过滤器,以及相关的工具类等。
package com.ffcs.icity.log;


import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;


import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;


import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;


import com.ffcs.icity.config.ApplicationConfigHolder;
import com.ffcs.icity.config.BaseApplicationConfig;
import com.ffcs.icity.config.RequestContextHolder;
import com.ffcs.icity.util.JSONHelper;
import com.ffcs.icity.util.RequestUtils;


public class RequestLoggingFilter implements Filter {


private final static Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class);


private RequestDumper requestDumper = new RequestDumper();



@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {


putMDC(request);
try {
// if (isDumpRequest()){
if(true) {
long startTime = System.currentTimeMillis();
//采用装饰器模式,重新封装一次HttpServletRequest,供后部的程序使用
ResettableStreamRequestWrapper requestWrapper = new ResettableStreamRequestWrapper((HttpServletRequest) request);
this.requestDumper.dumpRequest(requestWrapper);
requestWrapper.resetInputStream();
chain.doFilter(requestWrapper, response);


long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("request processing time: {} ms", elapsedTime);


} else {
chain.doFilter(request, response);
}
} finally {
MDC.clear();
}


}


private void putMDC(ServletRequest request) {
MDC.put("IP", RequestUtils.getIp((HttpServletRequest) request));
String requestId = RequestUtils.generateRequestId();
//在日志配置文件中设置好相关REQUEST_ID显示的设置
//<property name="ENCODER_PATTERN" value="%d{yyyy-MM-dd  HH:mm:ss.SSS} [%X{REQUEST_ID}] [%thread] %-5level %logger{80} - %msg%n" />
MDC.put("REQUEST_ID", requestId);
RequestContextHolder.setRequestId(requestId);
}

private boolean isDumpRequest() {
return getApplicationConfig().isDumpRequest();
}


private BaseApplicationConfig getApplicationConfig() {
return ApplicationConfigHolder.getApplicationConfig();
}

@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub


}


@Override
public void destroy() {
// TODO Auto-generated method stub

}

private static class RequestDumper {


private final static Logger logger = LoggerFactory.getLogger(RequestDumper.class);


public void dumpRequest(HttpServletRequest request) {
try {
if (logger.isInfoEnabled()) {
logger.info("--------------------request dump  begin-------------------------");
logger.info("request uri: {}", request.getRequestURI());
logger.info("request type: {}", request.getClass().getName());
logger.info("request method: {}", request.getMethod());
logger.info("request characterEncoding: {}", request.getCharacterEncoding());
dumpRequestHeaders(request);
dumpSession(request);
dumpRequestParams(request);
dumpRequestBody(request);
logger.info("--------------------request dump  end---------------------------");
}
} catch (Throwable e) {
logger.info("failure to dump request", e);
}
}


@SuppressWarnings("unchecked")
private void dumpRequestHeaders(HttpServletRequest request) {
for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
String headerName = headerNames.nextElement();
String value = request.getHeader(headerName);
logger.info("request header[{}]:{}", headerName, value);
}
}


@SuppressWarnings("unchecked")
public void dumpSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (null != session) {
for (Enumeration<String> attributeNames = session.getAttributeNames(); attributeNames.hasMoreElements();) {
String attributeName = attributeNames.nextElement();
Object value = session.getAttribute(attributeName);
logger.info("session[{}]:{}", attributeName, JSONHelper.toJSONStringQuietly(value, false));
}
}
}


@SuppressWarnings("unchecked")
private void dumpRequestParams(HttpServletRequest request) {
for (Enumeration<String> paramNames = request.getParameterNames(); paramNames.hasMoreElements();) {
String paramName = paramNames.nextElement();
String[] values = request.getParameterValues(paramName);
logger.info("request param[{}]:{}", paramName, JSONHelper.toJSONStringQuietly(values, false));
}
}


private void dumpRequestBody(HttpServletRequest request) {
if (isPayloadInBody(request)) {
String body = RequestUtils.resolveBody(request);
logger.info("request body:{}", body);
} else {
logger.info("request body:[unsupported payload:[{},{}]]", request.getMethod(), request.getContentType());
}
}


private boolean isPayloadInBody(HttpServletRequest request) {
String method = request.getMethod();
if (!("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method))) {
return false;
}
String contentType = request.getContentType();

return StringUtils.containsIgnoreCase(contentType, "application/json") 
|| StringUtils.containsIgnoreCase(contentType, "text/plain") 
|| StringUtils.containsIgnoreCase(contentType, "text/xml")
|| StringUtils.containsIgnoreCase(contentType, "text/html");
}


}


private static class ResettableStreamRequestWrapper extends HttpServletRequestWrapper {


private static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";


private byte[] bodyData;
private HttpServletRequest request;
private ResettableServletInputStream resettableServletInputStream;


public ResettableStreamRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
this.resettableServletInputStream = new ResettableServletInputStream();
}


public void resetInputStream() {
if (this.bodyData != null) {
this.resettableServletInputStream.is = new ByteArrayInputStream(this.bodyData);
}
}


@Override
public ServletInputStream getInputStream() throws IOException {
if (this.bodyData == null) {
resolveBodyData();
}
return this.resettableServletInputStream;
}


@Override
public BufferedReader getReader() throws IOException {
if (this.bodyData == null) {
resolveBodyData();
}
return new BufferedReader(new InputStreamReader(this.resettableServletInputStream));
}


private void resolveBodyData() throws IOException {
this.bodyData = IOUtils.toByteArray(this.request.getReader(), getCharacterEncoding());
this.resettableServletInputStream.is = new ByteArrayInputStream(this.bodyData);
}


public String getCharacterEncoding() {
return super.getCharacterEncoding() != null ? super.getCharacterEncoding() : DEFAULT_CHARACTER_ENCODING;
}


private class ResettableServletInputStream extends ServletInputStream {


private InputStream is;


@Override
public int read() throws IOException {
return this.is.read();
}
}
}

}


说明:ResettableStreamRequestWrapper继承HttpServletRequestWrapper,通过覆盖相关方法实现request的重新设置工作。
2。 RequestUtils以及JSONHelper两个工具类
package com.ffcs.icity.util;


import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;


import javax.servlet.http.HttpServletRequest;


import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 请求工具类.
 * 
 * 
 */
public abstract class RequestUtils {


private static final Logger logger = LoggerFactory.getLogger(RequestUtils.class);


/**
* 生成请求ID

*  @return
*/
public static String generateRequestId() {
return Long.toString(new Date().getTime());
}


/**
* 获取请求参数.如果请求参数为空时,返回一个默认值.

* @param request
* @param name 参数名
* @param defaultValue 默认值
* @return
*/
public static String getRequestParam(HttpServletRequest request, String name, String defaultValue) {
String value = request.getParameter(name);
return value != null ? value : defaultValue;
}


/**
* 获取请求参数.如果请求参数为空时,返回一个默认值.

* @param request
* @param name 参数名
* @param defaultValue 默认值
* @return
*/
public static int getRequestParam(HttpServletRequest request, String name, int defaultValue) {
String value = request.getParameter(name);
return StringUtils.isNotBlank(value) ? Integer.valueOf(value) : defaultValue;
}


/**
* 获取请求头列表

* @param request
* @return
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> resolveHeaders(HttpServletRequest request) {
Map<String, Object> result = new HashMap<String, Object>();
for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
String headerName = headerNames.nextElement();
result.put(headerName, request.getHeader(headerName));
}
return result;
}


/**
* 获取请求参数列表

* @param request
* @return
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> resolveParams(HttpServletRequest request) {
Map<String, Object> result = new HashMap<String, Object>();
for (Enumeration<String> paramNames = request.getParameterNames(); paramNames.hasMoreElements();) {
String paramName = paramNames.nextElement();
result.put(paramName, request.getParameter(paramName));
}
return result;
}


/**
* 获取请求体

* @param request
* @return
*/
public static String resolveBody(HttpServletRequest request) {
String result;
try {
result = IOUtils.toString(request.getInputStream());
} catch (IOException e) {
logger.error("failure to resolve body", e);
result = "[failure to resolve body]";
}
return result;
}


/**
* 获取绝对路径,以"/"开头.

* @param request
* @param path 相对路径
* @return
*/
public static String getFullPath(HttpServletRequest request, String path) {


String tmp = StringUtils.defaultIfBlank(path, "");


if (StringUtils.startsWithAny(tmp.toLowerCase(), "http", "https")) {
return path;
}


if (!StringUtils.startsWith(path, "/")) {
path = "/" + path;
}


return request.getContextPath()+ request.getServletPath() + path;
}


/**
* 获取完整的URL.

* @param request
* @param path 相对URL
* @return
*/
public static String getFullUrl(HttpServletRequest request, String path) {
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + getFullPath(request, path);
}


/**
* 格式化URL

* @param url
* @return
*/
public static String normalizeUrl(String url) {
return url.replaceAll("/{2,}", "/");
}


/**
* 获取客户端的请求IP.

* @param request
* @return
*/
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("X-Real-IP");
if (null == ip) {
ip = request.getRemoteAddr();
}
return ip;
}


}


package com.ffcs.icity.util;


import java.util.Map;


import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.core.JsonParser;


/**
 * json工具类.
 *
 * 
 */
public class JSONHelper {


private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private final static ObjectMapper LCWU_OBJECT_MAPPER = new ObjectMapper();

static{
OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,true);
OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES,true);

LCWU_OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
LCWU_OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,true);
LCWU_OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES,true);
LCWU_OBJECT_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}

/**
* 将json字符串转换成Map对象

*  json类型与java类型的对应关系查看:http://wiki.fasterxml.com/JacksonInFiveMinutess

* @param json
* @return Map
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map<String,Object> toMap(String json) throws Exception {
return OBJECT_MAPPER.readValue(json, Map.class);
}


/**
* 将对象转换成json字符串

* @param object
* @param camelCaseToLowerCaseWithUnderscores 将小写下划线分割的json属性名到驼峰格式的java属性名
* @return String
* @throws Exception
*/
public static String toJSONString(Object object, boolean camelCaseToLowerCaseWithUnderscores) throws Exception {
ObjectMapper mapper = camelCaseToLowerCaseWithUnderscores ? LCWU_OBJECT_MAPPER : OBJECT_MAPPER;
return mapper.writeValueAsString(object);
}

/**
* 将对象转换成json字符串

* @param object
* @return String
* @throws Exception
*/
public static String toJSONString(Object object) throws Exception {
return toJSONString(object, false);
}


/**
* 类似toJSONString()方法,除了在转换过程出现异常时,返回""(空串).

* @param object
* @param camelCaseToLowerCaseWithUnderscores 将小写下划线分割的json属性名到驼峰格式的java属性名
* @return String
*/
public static String toJSONStringQuietly(Object object, boolean camelCaseToLowerCaseWithUnderscores) {
ObjectMapper mapper = camelCaseToLowerCaseWithUnderscores ? LCWU_OBJECT_MAPPER : OBJECT_MAPPER;
try {
return mapper.writeValueAsString(object);
} catch (Exception e) {
return "";
}
}

/**
* 类似toJSONString()方法,除了在转换过程出现异常时,返回""(空串).

* @param object
* @return String
*/
public static String toJSONStringQuietly(Object object) {
return toJSONStringQuietly(object, false);
}


@SuppressWarnings("unchecked")
public static <T> T getValue(String json, String... paths) throws Exception {
Object value = null;
Map<String, Object> node = OBJECT_MAPPER.readValue(json, Map.class);
for (int i = 0; i < paths.length; i++) {
value = node.get(paths[i]);
if (i == paths.length - 1) {
break;
} else if (value instanceof Map) {
node = (Map<String, Object>) value;
} else {
return null;
}
}
return (T)value;
}

}


3。 slf4j中的logback.xml的配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 应用名称 -->
<property name="APP_NAME" value="Spring" />
<!--日志文件的保存路径,首先查找系统属性-Dlog.dir,如果存在就使用其;否则,在当前目录下创建名为logs目录做日志存放的目录 -->
<property name="LOG_HOME" value="${log.dir:-logs}/${APP_NAME}" />
<!-- 日志输出格式 -->
<property name="ENCODER_PATTERN"
value="%d{yyyy-MM-dd  HH:mm:ss.SSS} [%thread] IP[%X{IP}] REQUEST_ID[%X{REQUEST_ID}] %-5level %logger{80} - %msg%n"/>
<contextName>${APP_NAME}</contextName>


<!-- 控制台日志:输出全部日志到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>${ENCODER_PATTERN}</Pattern>
</encoder>
</appender>


<!-- 文件日志:输出全部日志到文件 -->
<appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/output.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${ENCODER_PATTERN}</pattern>
</encoder>
</appender>


<!-- 错误日志:用于将错误日志输出到独立文件 -->
<appender name="ERROR_FILE"   class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${ENCODER_PATTERN}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>

<!-- 设置日志级别,从配置文件中获取日志级别 -->
<property name="LOGGER_ROOT_LEVEL"  value="${log.logger.root.level:-DEBUG}" />

<root>
<level value="${LOGGER_ROOT_LEVEL}" />
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="ERROR_FILE" />
</root>

</configuration>


说明:
        <!-- 设置日志级别,从配置文件中获取日志级别 -->
<property name="LOGGER_ROOT_LEVEL"  value="${log.logger.root.level:-DEBUG}" />
                表示properties被spring配置文件加载后,该logback.xml中能够获取到的数值.


4.  config.properties配置文件配置内容,如下:
#log level
log.logger.root.level=DEBUG


#log open flag
log.isDumpRequest=true


5。 web.xml中添加该过滤器
<filter>
<filter-name>requestLoggingFilter</filter-name>
<filter-class>com.ffcs.icity.log.RequestLoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestLoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


6。 使用POST在BODY中传值的方式,实现如下的日志打印功能:
2014-12-12  10:45:57.449 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - --------------------request dump  begin-------------------------
2014-12-12  10:45:57.450 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request uri: /Spring/prototype/test
2014-12-12  10:45:57.450 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request type: com.ffcs.icity.log.RequestLoggingFilter$ResettableStreamRequestWrapper
2014-12-12  10:45:57.450 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request method: POST
2014-12-12  10:45:57.450 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request characterEncoding: UTF-8
2014-12-12  10:45:57.451 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[host]:localhost:8080
2014-12-12  10:45:57.451 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[user-agent]:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[accept]:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[accept-language]:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[accept-encoding]:gzip, deflate
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[content-type]:application/json; charset=UTF-8
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[content-length]:454
2014-12-12  10:45:57.452 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[connection]:keep-alive
2014-12-12  10:45:57.453 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[pragma]:no-cache
2014-12-12  10:45:57.453 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request header[cache-control]:no-cache
2014-12-12  10:45:57.544 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - request body:{
 "org_code":"unknow",
 "city_code":"unknow",
 "client_type":"unknow",
 "imsi":"imsi123",
 "imei":"imei123",
 "longitude":"longitude123",
 "latitude":"latitude123",
 "product_id":"123",
 "client_version":"123",  
 "client_channel_type":"123",
 "os_type":"123",
 "timestamp":"2014-11-21 00:00:00", 
 "mobile":"13338290745", 
 "type":"1", 
 "relaKey":"relaKey", 
 "sign":"MMl81q28tiyHA0KENSQTQNxYpmv18wna2AAMt7eBzjctqg1%2F5jHVBI2qEyYGKvp4Y6ywgnk9GMU%3D"
}
2014-12-12  10:45:57.544 [http-8080-1] IP[127.0.0.1] REQUEST_ID[1418352357443] INFO  com.ffcs.icity.log.RequestLoggingFilter$RequestDumper - --------------------request dump  end---------------------------


其中REQUEST_ID为单次某一线程请求的唯一标识,可供后期的查询搜索使用。



























































































  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpServletRequestWrapper是一个装饰器模式的实现,它允许我们在不改变原始请求的情况下,对请求进行修改。在Interceptor中,我们可以通过HttpServletRequestWrapper来修改request参数。 首先,我们需要自定义一个类继承HttpServletRequestWrapper,重写getParameter方法,以实现修改request参数的功能。具体实现如下: ``` public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper { private Map<String, String[]> params = new HashMap<>(); public MyHttpServletRequestWrapper(HttpServletRequest request) { super(request); this.params.putAll(request.getParameterMap()); } @Override public String getParameter(String name) { String[] values = params.get(name); if (values == null || values.length == 0) { return null; } return values[0]; } @Override public Map<String, String[]> getParameterMap() { return params; } @Override public Enumeration<String> getParameterNames() { return Collections.enumeration(params.keySet()); } public void addParameter(String name, String value) { if (params.containsKey(name)) { String[] values = params.get(name); values = Arrays.copyOf(values, values.length + 1); values[values.length - 1] = value; params.put(name, values); } else { params.put(name, new String[]{value}); } } } ``` 接下来,在Interceptor中,我们可以通过如下代码来使用MyHttpServletRequestWrapperrequest参数进行修改: ``` public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getMethod().equalsIgnoreCase("get")) { // 使用MyHttpServletRequestWrapper请求参数进行修改 MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(request); requestWrapper.addParameter("key", "value"); // 将修改后的request传给下一个Interceptor或Controller request = requestWrapper; } return true; } ``` 上述代码中,我们先判断请求的方法是否为get,如果是,则使用MyHttpServletRequestWrapper请求参数进行修改,然后将修改后的request传给下一个Interceptor或Controller。如果请求方法不为get,则直接将原始request传给下一个Interceptor或Controller。 需要注意的是,使用HttpServletRequestWrapperrequest参数进行修改时,只有在下一个Interceptor或Controller真正使用request参数时,修改后的参数才会生效。如果在当前Interceptor中进行了修改,但在下一个Interceptor或Controller中并没有使用修改后的参数,那么修改就会失效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值