您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何對HttpServletRequest中的Header進行增刪”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何對HttpServletRequest中的Header進行增刪”吧!
HttpServletRequest
中定義的對Header的操作全是只讀,沒有修改。
public interface HttpServletRequest extends ServletRequest { ... public long getDateHeader(String name); public String getHeader(String name); public Enumeration<String> getHeaders(String name); public Enumeration<String> getHeaderNames(); public int getIntHeader(String name); ... }
HttpServletRequest
只是一個接口,實現由Servlet容器提供。不管是任何容器,實現類,肯定是要把請求的Header存儲在某個地方,于是可以通過反射來對存儲Header
的容器進行增刪。
這個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<string, string[]> @GetMapping public Object demo (HttpServletRequest request) { Map<String, List<String>> headers = new LinkedHashMap<>(); Enumeration<String> nameEnumeration = request.getHeaderNames(); while (nameEnumeration.hasMoreElements()) { String name = nameEnumeration.nextElement(); List<String> values = headers.get(name); if (values == null) { values = new ArrayList<>(); headers.put(name, values); } Enumeration<String> valueEnumeration = request.getHeaders(name); while (valueEnumeration.hasMoreElements()) { values.add(valueEnumeration.nextElement()); } } return headers; } }
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
,對它進行修改即可。
public class RequestFacade implements HttpServletRequest { protected org.apache.catalina.connector.Request request = null; ... }
public class Request implements HttpServletRequest { protected org.apache.coyote.Request coyoteRequest; ... }
public final class Request { private final org.apache.tomcat.util.http.MimeHeaders headers = new MimeHeaders(); }
假設的場景是,需要對請求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"); } }
可以看到成功添加了x-request-id
header,并且刪除了User-Agent
header。
SpringBoot默認的Servlet容器就是Tomcat
越來越多人使用Undertow作為Servlet容器,據說性能比Tomcat要好很多
只需要把spring-boot-starter-web
中的spring-boot-starter-tomcat
排除,然后手動添加spring-boot-starter-undertow
即可
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> </dependencies>
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的存儲容器,反射獲取它就行。
public final class HttpServletRequestImpl implements HttpServletRequest { private final io.undertow.server.HttpServerExchange exchange; }
public final class HttpServerExchange extends AbstractAttachable { private final HeaderMap requestHeaders; }
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"); } }
感謝各位的閱讀,以上就是“如何對HttpServletRequest中的Header進行增刪”的內容了,經過本文的學習后,相信大家對如何對HttpServletRequest中的Header進行增刪這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。