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


本文摘自classinstance.cn。

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

相关阅读 >>

Java 中的 io 流

Java 动态代理详解

Java 面向对象编程三大特性: 封装 继承 多态

Java 中判断两个字符串值是否相等

Java stream接口操作 count,anymatch,allmatch,nonematch

Java:阐述servlet和cgi的区别?

Java 获取汉字的拼音首字母

hashcode 与 equals

Java通过域名获取域名的ip地址

Java 中 string 和 int 类型的互相转化

更多相关阅读请进入《Java》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...