ServletRequest转HttpServletRequest设置header之后取不到header的问题

原创 2019-09-25 20:27 阅读(7524)次

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的问题