ServletRequest转HttpServletRequest设置header之后取不到header的问题
原创 2019-09-25 20:27 阅读(8126)次
java中,我们在filter经常会设置请求头,比如token,各种参数标识啊,如下代码设置token到头部:
@Order(Ordered.HIGHEST_PRECEDENCE+49)
@Component
public class FilterA implements Filter{
private static final Logger log = LoggerFactory.getLogger("adminLogger");
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
reflectSetparam(request, "token", "aaaaa");//设置token到头部
}catch (Exception e) {
e.printStackTrace();
}
chain.doFilter(req, res);
}
/**
* 修改header信息,key-value键值对儿加入到header中
* @param request
* @param key
* @param value
*/
private void reflectSetparam(HttpServletRequest request,String key,String value){
Class<? extends HttpServletRequest> requestClass = request.getClass();
//System.out.println("request实现类="+requestClass.getName());
try {
Field request1 = requestClass.getDeclaredField("request");
request1.setAccessible(true);
Object o = request1.get(request);
Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
coyoteRequest.setAccessible(true);
Object o1 = coyoteRequest.get(o);
//System.out.println("coyoteRequest实现类="+o1.getClass().getName());
Field headers = o1.getClass().getDeclaredField("headers");
headers.setAccessible(true);
MimeHeaders o2 = (MimeHeaders)headers.get(o1);
o2.addValue(key).setString(value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
接下来可能就要用另一个过滤器或者代码中获得刚刚设置的请求头,比如:
@Order(Ordered.HIGHEST_PRECEDENCE+50)
@Component
public class FilterB implements Filter{
private static final Logger log = LoggerFactory.getLogger("adminLogger");
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String token = request.getHeader("token");
}catch (Exception e) {
e.printStackTrace();
}
chain.doFilter(req, res);
}
}
你会发现这个过滤器取不到,用如下代码:
HttpServletRequest requests = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
String token = requests.getHeader("token");
也取不到。我遇到这个问题时,搞了有一会,为了下次不再掉坑里,我把我的解决方案记一下,就是在用request设置头部时用自己的包装类,代码如下:
@Order(Ordered.HIGHEST_PRECEDENCE+49)
@Component
public class FilterA implements Filter{
private static final Logger log = LoggerFactory.getLogger("adminLogger");
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(request);
requestWrapper.addHeader("token","aaa");
chain.doFilter(requestWrapper, res);
}catch (Exception e) {
e.printStackTrace();
}
chain.doFilter(req, res);
}
}
/**
* 自定义请求包装类
*
*/
public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
/**
* construct a wrapper for this request
*
* @param request
*/
public HeaderMapRequestWrapper(HttpServletRequest request) {
super(request);
}
private Map<String, String> headerMap = new HashMap<>();
/**
* add a header with given name and value
*
* @param name
* @param value
*/
public void addHeader(String name, String value) {
headerMap.put(name, value);
}
@Override
public String getHeader(String name) {
String headerValue = super.getHeader(name);
if (headerMap.containsKey(name)) {
headerValue = headerMap.get(name);
}
return headerValue;
}
/**
* get the Header names
*/
@Override
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
for (String name : headerMap.keySet()) {
names.add(name);
}
return Collections.enumeration(names);
}
@Override
public Enumeration<String> getHeaders(String name) {
List<String> values = Collections.list(super.getHeaders(name));
if (headerMap.containsKey(name)) {
values = Arrays.asList(headerMap.get(name));
}
return Collections.enumeration(values);
}
}
这样就解决了ServletRequest转HttpServletRequest设置header之后取不到header的问题