這篇文章主要講解了“如何對HttpServletRequest中的Header進行增刪”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何對HttpServletRequest中的Header進行增刪”吧!
創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)公司、成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設(shè)計,對服務(wù)成都發(fā)電機維修等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗。創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報價服務(wù),我們深知市場的競爭激烈,認真對待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進步,是我們永遠的責任!
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
只是一個接口,實現(xiàn)由Servlet容器提供。不管是任何容器,實現(xiàn)類,肯定是要把請求的Header存儲在某個地方,于是可以通過反射來對存儲Header
的容器進行增刪。
這個Controller很簡單,把客戶端的所有Header,以JSON形似響應(yīng)給客戶端。
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,響應(yīng)給客戶端。 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使用了外觀模式(Facade),這個實現(xiàn)稍微有一點點復(fù)雜
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
實現(xiàn),它有一個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(); }
假設(shè)的場景是,需要對請求Header統(tǒng)一添加一個
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容器,據(jù)說性能比Tomcat要好很多
只需要把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
HttpServletRequest
實現(xiàn)它的實現(xiàn)就比較簡單
io.undertow.servlet.spec.HttpServletRequestImpl |-io.undertow.server.HttpServerExchange |-io.undertow.util.HeaderMap
io.undertow.servlet.spec.HttpServletRequestImpl
實現(xiàn)類中有一個屬性對象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進行增刪”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對如何對HttpServletRequest中的Header進行增刪這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!