如何对HttpServletRequest中的Header进行增删
这篇文章主要讲解了“如何对HttpServletRequest中的Header进行增删”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何对HttpServletRequest中的Header进行增删”吧!
创新互联,为您提供网站建设公司、成都网站制作、网站营销推广、网站开发设计,对服务成都发电机维修等多个行业拥有丰富的网站建设及推广经验。创新互联网站建设公司成立于2013年,提供专业网站制作报价服务,我们深知市场的竞争激烈,认真对待每位客户,为客户提供赏心悦目的作品。 与客户共同发展进步,是我们永远的责任!
HttpServletRequest 没有提供修改/删除的Api
HttpServletRequest
中定义的对Header的操作全是只读,没有修改。
public interface HttpServletRequest extends ServletRequest { ... public long getDateHeader(String name); public String getHeader(String name); public EnumerationgetHeaders(String name); public Enumeration getHeaderNames(); public int getIntHeader(String name); ... }
HttpServletRequest
只是一个接口,实现由Servlet容器提供。不管是任何容器,实现类,肯定是要把请求的Header存储在某个地方,于是可以通过反射来对存储Header
的容器进行增删。
先定义一个测试的Controller
这个Controller很简单,把客户端的所有Header,以JSON形似响应给客户端。
import java.util.ArrayList; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/demo") public class DemoController { // 遍历所有请求Header,响应给客户端。 map@GetMapping public Object demo (HttpServletRequest request) { Map > headers = new LinkedHashMap<>(); Enumeration nameEnumeration = request.getHeaderNames(); while (nameEnumeration.hasMoreElements()) { String name = nameEnumeration.nextElement(); List values = headers.get(name); if (values == null) { values = new ArrayList<>(); headers.put(name, values); } Enumeration valueEnumeration = request.getHeaders(name); while (valueEnumeration.hasMoreElements()) { values.add(valueEnumeration.nextElement()); } } return headers; } }
使用Tomcat作为容器
Tomcat对HttpServletRequest的实现
Tomcat使用了外观模式(Facade),这个实现稍微有一点点复杂
org.apache.catalina.connector.RequestFacade |-org.apache.catalina.connector.Request |-org.apache.coyote.Request |-org.apache.tomcat.util.http.MimeHeaders
首先是 org.apache.catalina.connector.RequestFacade
实现,它有一个org.apache.catalina.connector.Request
的对象。这个对象又有一个org.apache.coyote.Request
的对象,这个对象又有一个org.apache.tomcat.util.http.MimeHeaders
字段,它就是存储了客户端请求头的容器,只要通过反射获取到这个MimeHeaders
,对它进行修改即可。
org.apache.catalina.connector.RequestFacade
public class RequestFacade implements HttpServletRequest { protected org.apache.catalina.connector.Request request = null; ... }
org.apache.catalina.connector.Request
public class Request implements HttpServletRequest { protected org.apache.coyote.Request coyoteRequest; ... }
org.apache.coyote.Request coyoteRequest
public final class Request { private final org.apache.tomcat.util.http.MimeHeaders headers = new MimeHeaders(); }
在Filter中通过反射对请求Header进行增删
假设的场景是,需要对请求Header统一添加一个
x-request-id
,通过这个ID来从日志中定位每一个请求。
import java.io.IOException; import java.lang.reflect.Field; import java.util.UUID; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.RequestFacade; import org.apache.tomcat.util.http.MimeHeaders; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; @WebFilter(urlPatterns = "/*") @Component @Order(-999) public class RequestIdGenFilter extends HttpFilter { /** * */ private static final long serialVersionUID = 1787347739651657706L; @Override protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { try { // 从 RequestFacade 中获取 org.apache.catalina.connector.Request Field connectorField = ReflectionUtils.findField(RequestFacade.class, "request", Request.class); connectorField.setAccessible(true); Request connectorRequest = (Request) connectorField.get(req); // 从 org.apache.catalina.connector.Request 中获取 org.apache.coyote.Request Field coyoteField = ReflectionUtils.findField(Request.class, "coyoteRequest", org.apache.coyote.Request.class); coyoteField.setAccessible(true); org.apache.coyote.Request coyoteRequest = (org.apache.coyote.Request) coyoteField.get(connectorRequest); // 从 org.apache.coyote.Request 中获取 MimeHeaders Field mimeHeadersField = ReflectionUtils.findField(org.apache.coyote.Request.class, "headers", MimeHeaders.class); mimeHeadersField.setAccessible(true); MimeHeaders mimeHeaders = (MimeHeaders) mimeHeadersField.get(coyoteRequest); this.mineHeadersHandle(mimeHeaders); } catch (Exception e) { throw new RuntimeException(e); } super.doFilter(req, res, chain); } protected void mineHeadersHandle (MimeHeaders mimeHeaders) { // 添加一个Header,随机生成请求ID mimeHeaders.addValue("x-request-id").setString(UUID.randomUUID().toString());; // 移除一个header mimeHeaders.removeHeader("User-Agent"); } }
请求Controller获取响应结果
可以看到成功添加了x-request-id
header,并且删除了User-Agent
header。
SpringBoot默认的Servlet容器就是Tomcat
使用Undertow作为容器
越来越多人使用Undertow作为Servlet容器,据说性能比Tomcat要好很多
SpringBoot替换Tomcat为Undertow
只需要把spring-boot-starter-web
中的spring-boot-starter-tomcat
排除,然后手动添加spring-boot-starter-undertow
即可
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat org.springframework.boot spring-boot-starter-undertow
Undertow中的HttpServletRequest
实现
它的实现就比较简单
io.undertow.servlet.spec.HttpServletRequestImpl |-io.undertow.server.HttpServerExchange |-io.undertow.util.HeaderMap
io.undertow.servlet.spec.HttpServletRequestImpl
实现类中有一个属性对象io.undertow.server.HttpServerExchange
,这个属性对象又包含了一个io.undertow.util.HeaderMap
,HeaderMap
就是请求Header的存储容器,反射获取它就行。
io.undertow.servlet.spec.HttpServletRequestImpl
public final class HttpServletRequestImpl implements HttpServletRequest { private final io.undertow.server.HttpServerExchange exchange; }
io.undertow.server.HttpServerExchange
public final class HttpServerExchange extends AbstractAttachable { private final HeaderMap requestHeaders; }
在Filter中通过反射对请求Header进行增删
import java.io.IOException; import java.lang.reflect.Field; import java.util.UUID; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import io.undertow.server.HttpServerExchange; import io.undertow.servlet.spec.HttpServletRequestImpl; import io.undertow.util.HeaderMap; import io.undertow.util.HttpString; @WebFilter(urlPatterns = "/*") @Component @Order(-999) public class RequestIdGenFilter extends HttpFilter { /** * */ private static final long serialVersionUID = 1787347739651657706L; @Override protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { try { // 从HttpServletRequestImpl中获取HttpServerExchange Field exchangeField = ReflectionUtils.findField(HttpServletRequestImpl.class, "exchange", HttpServerExchange.class); exchangeField.setAccessible(true); HttpServerExchange httpServerExchange = (HttpServerExchange) exchangeField.get(req); // 从HttpServerExchange中获取HeaderMap Field headerMapField = ReflectionUtils.findField(HttpServerExchange.class, "requestHeaders", HeaderMap.class); headerMapField.setAccessible(true); HeaderMap requestHeaderMap = (HeaderMap) headerMapField.get(httpServerExchange); this.handleRequestHeaderMap(requestHeaderMap); } catch (Exception e) { throw new RuntimeException(e); } super.doFilter(req, res, chain); } private void handleRequestHeaderMap(HeaderMap requestHeaderMap) { // 添加Header requestHeaderMap.add(new HttpString("x-request-id"), UUID.randomUUID().toString()); // 移除Header requestHeaderMap.remove("User-Agent"); } }
请求Controller获取结果
感谢各位的阅读,以上就是“如何对HttpServletRequest中的Header进行增删”的内容了,经过本文的学习后,相信大家对如何对HttpServletRequest中的Header进行增删这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!
网页题目:如何对HttpServletRequest中的Header进行增删
文章出自:http://myzitong.com/article/ijgosp.html