您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何對(duì)HttpServletRequest中的Header進(jìn)行增刪”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何對(duì)HttpServletRequest中的Header進(jìn)行增刪”吧!
HttpServletRequest
中定義的對(duì)Header的操作全是只讀,沒(méi)有修改。
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
只是一個(gè)接口,實(shí)現(xiàn)由Servlet容器提供。不管是任何容器,實(shí)現(xiàn)類(lèi),肯定是要把請(qǐng)求的Header存儲(chǔ)在某個(gè)地方,于是可以通過(guò)反射來(lái)對(duì)存儲(chǔ)Header
的容器進(jìn)行增刪。
這個(gè)Controller很簡(jiǎn)單,把客戶端的所有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 { // 遍歷所有請(qǐng)求Header,響應(yīng)給客戶端。 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),這個(gè)實(shí)現(xiàn)稍微有一點(diǎn)點(diǎ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
實(shí)現(xiàn),它有一個(gè)org.apache.catalina.connector.Request
的對(duì)象。這個(gè)對(duì)象又有一個(gè)org.apache.coyote.Request
的對(duì)象,這個(gè)對(duì)象又有一個(gè)org.apache.tomcat.util.http.MimeHeaders
字段,它就是存儲(chǔ)了客戶端請(qǐng)求頭的容器,只要通過(guò)反射獲取到這個(gè)MimeHeaders
,對(duì)它進(jìn)行修改即可。
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è)的場(chǎng)景是,需要對(duì)請(qǐng)求Header統(tǒng)一添加一個(gè)
x-request-id
,通過(guò)這個(gè)ID來(lái)從日志中定位每一個(gè)請(qǐng)求。
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) { // 添加一個(gè)Header,隨機(jī)生成請(qǐng)求ID mimeHeaders.addValue("x-request-id").setString(UUID.randomUUID().toString());; // 移除一個(gè)header mimeHeaders.removeHeader("User-Agent"); } }
可以看到成功添加了x-request-id
header,并且刪除了User-Agent
header。
SpringBoot默認(rèn)的Servlet容器就是Tomcat
越來(lái)越多人使用Undertow作為Servlet容器,據(jù)說(shuō)性能比Tomcat要好很多
只需要把spring-boot-starter-web
中的spring-boot-starter-tomcat
排除,然后手動(dòng)添加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
實(shí)現(xiàn)它的實(shí)現(xiàn)就比較簡(jiǎn)單
io.undertow.servlet.spec.HttpServletRequestImpl |-io.undertow.server.HttpServerExchange |-io.undertow.util.HeaderMap
io.undertow.servlet.spec.HttpServletRequestImpl
實(shí)現(xiàn)類(lèi)中有一個(gè)屬性對(duì)象io.undertow.server.HttpServerExchange
,這個(gè)屬性對(duì)象又包含了一個(gè)io.undertow.util.HeaderMap
,HeaderMap
就是請(qǐng)求Header的存儲(chǔ)容器,反射獲取它就行。
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"); } }
感謝各位的閱讀,以上就是“如何對(duì)HttpServletRequest中的Header進(jìn)行增刪”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何對(duì)HttpServletRequest中的Header進(jìn)行增刪這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。