java 获取HttpRequest Header 的几种方法

本文介绍如何使用 HTTP Header 实现单点登录(SSO),并提供多种获取 HTTP Header 的 Java 示例代码,包括利用 HttpServletRequest 和 Spring MVC 框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开发应用程序的过程中,如果有多个应用,通常会通过一个portal 门户来集成,这个portal  是所有应用程序的入口,用户一旦在portal 登录之后,进入另外一个系统,就需要类似的单点登录(SSO). 进入各个子系统的时候,就不需要再次登录, 当然类似的功能,你可以通过专业的单点登录软件来实现,也可以自己写数据库token 等方式来实现。其实还有一个比较简单的方法,就是通过 portal 封装已经登录过的用户的消息,写到http header 之中,然后把请求forward 到各个子系统中去,而各子系统从 http header 中获取用户名,作为是否登录过的校验或者合法的校验。总结了几种处理http Header 的方法:

利用 HttpServletRequest 

程序代码 程序代码

import javax.servlet.http.HttpServletRequest;

  //...
  private HttpServletRequest request;

  //get request headers
  private Map<String, String> getHeadersInfo() {

    Map<String, String> map = new HashMap<String, String>();

    Enumeration headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
        String key = (String) headerNames.nextElement();
        String value = request.getHeader(key);
        map.put(key, value);
    }

    return map;
  }


一个典型的例子如下:
程序代码 程序代码

"headers" : {
    "Host" : "yihaomen.com",
    "Accept-Encoding" : "gzip,deflate",
    "X-Forwarded-For" : "66.249.x.x",
    "X-Forwarded-Proto" : "http",
    "User-Agent" : "Mozilla/5.0 (compatible; Googlebot/2.1; + http://www.google.com/bot.html)",
    "X-Request-Start" : "1389158003923",
    "Accept" : "*/*",
    "Connection" : "close",
    "X-Forwarded-Port" : "80",
    "From" : "googlebot(at)googlebot.com"
}


获取 user-agent 
程序代码 程序代码

import javax.servlet.http.HttpServletRequest;

  //...
  private HttpServletRequest request;

  private String getUserAgent() {
    return request.getHeader("user-agent");
  }

一个典型的例子如下:
程序代码 程序代码

Mozilla/5.0 (compatible; Googlebot/2.1; + http://www.google.com/bot.html)


利用 spring mvc 获取  HttpRequest Header 的例子 
程序代码 程序代码

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/site")
public class SiteController {

    @Autowired
    private HttpServletRequest request;

    @RequestMapping(value = "/{input:.+}", method = RequestMethod.GET)
    public ModelAndView getDomain(@PathVariable("input") String input) {

        ModelAndView modelandView = new ModelAndView("result");

        modelandView.addObject("user-agent", getUserAgent());
        modelandView.addObject("headers", getHeadersInfo());

        return modelandView;

    }

    //get user agent
    private String getUserAgent() {
        return request.getHeader("user-agent");
    }

    //get request headers
    private Map<String, String> getHeadersInfo() {

        Map<String, String> map = new HashMap<String, String>();

        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }

        return map;
    }

}


也许有人会说,Http Header  是可以模拟的,那么自己可以构造一个用来欺骗这些系统, 是的,的确是这样,所以在用Http Header 来传值得时候,一定要记得,所有的请求都必须经过 portal 来处理,然后 forward 到各子系统,就不会出现这个问题了。因为portal 首先拦截用户发起的所有的请求,如果是构造的用户,在portal 的sessiion 也是没有记录的,仍然会跳转到登录页面,如果在protal 的 session 中记录,而且  Http Header 中也有记录,那么在子系统就是合法的用户,然后自己可以根据一些要求处理业务逻辑了。


原文链接:http://www.yihaomen.com/article/java/459.htm

<think>我们讨论的是Java中RestTemplate和WebClient的拦截方式种类。根据之前的知识和引用内容,我们可以总结如下:1.**RestTemplate的拦截方式**:-**ClientHttpRequestInterceptor**:这是RestTemplate提供的拦截器接口,允许我们在发送请求前和收到响应后执行自定义逻辑。我们可以通过实现该接口并添加到RestTemplate的拦截器链中。-**AOP(面向切面编程)**:我们可以使用SpringAOP来拦截RestTemplate的方法调用,例如在方法执行前后进行日志记录、性能监控等。2.**WebClient的拦截方式**:-**ExchangeFilterFunction**:这是WebClient提供的过滤器函数,类似于拦截器。我们可以通过定义ExchangeFilterFunction并将其添加到WebClient的过滤器链中,在请求发送前和响应处理前执行自定义逻辑。-**AOP(面向切面编程)**:同样,我们也可以使用AOP来拦截WebClient的方法调用,但由于WebClient是异步非阻塞的,使用AOP拦截其方法可能不如使用内置的ExchangeFilterFunction方便和直接。下面我们分别详细说明这两种客户端的不同拦截方式。###1.RestTemplate的拦截方式####方式一:使用ClientHttpRequestInterceptor这是RestTemplate内置的拦截机制。我们可以创建一个或多个拦截器,并将它们添加到RestTemplate中。每个拦截器都会在请求执行前后被调用。**示例代码:**```javaimportorg.springframework.http.HttpRequest;importorg.springframework.http.client.ClientHttpRequestExecution;importorg.springframework.http.client.ClientHttpRequestInterceptor;importorg.springframework.http.client.ClientHttpResponse;importjava.io.IOException;publicclassLoggingInterceptorimplementsClientHttpRequestInterceptor{@OverridepublicClientHttpResponseintercept(HttpRequestrequest,byte[]body,ClientHttpRequestExecutionexecution)throwsIOException{//在请求执行前的逻辑System.out.println("RequestURI:"+request.getURI());System.out.println("RequestMethod:"+request.getMethod());//执行请求ClientHttpResponseresponse=execution.execute(request,body);//在响应处理前的逻辑System.out.println("ResponseStatusCode:"+response.getStatusCode());returnresponse;}}```将拦截器添加到RestTemplate:```java@BeanpublicRestTemplaterestTemplate(){RestTemplaterestTemplate=newRestTemplate();restTemplate.getInterceptors().add(newLoggingInterceptor());returnrestTemplate;}```####方式二:使用AOP拦截我们可以定义一个切面,针对RestTemplate的方法进行拦截。这种方式可以拦截到RestTemplate的任意方法,比如`getForObject`、`postForEntity`等。**示例代码:**```javaimportorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;@Aspect@ComponentpublicclassRestTemplateAspect{@Around("execution(*org.springframework.web.client.RestTemplate.*(..))")publicObjectlogRestTemplateCall(ProceedingJoinPointjoinPoint)throwsThrowable{//方法执行前的逻辑System.out.println("BeforeRestTemplatemethod:"+joinPoint.getSignature().getName());Objectresult=joinPoint.proceed();//执行原方法//方法执行后的逻辑System.out.println("AfterRestTemplatemethod:"+joinPoint.getSignature().getName());returnresult;}}```###2.WebClient的拦截方式####方式一:使用ExchangeFilterFunctionWebClient使用过滤器链来处理请求。我们可以定义一个或多个ExchangeFilterFunction,并将其添加到WebClient中。**示例代码:**```javaimportorg.springframework.web.reactive.function.client.ExchangeFilterFunction;importreactor.core.publisher.Mono;publicclassLoggingFilter{publicstaticExchangeFilterFunctionlogRequest(){returnExchangeFilterFunction.ofRequestProcessor(clientRequest->{System.out.println("Request:"+clientRequest.method()+""+clientRequest.url());returnMono.just(clientRequest);});}publicstaticExchangeFilterFunctionlogResponse(){returnExchangeFilterFunction.ofResponseProcessor(clientResponse->{System.out.println("ResponseStatus:"+clientResponse.statusCode());returnMono.just(clientResponse);});}}```将过滤器添加到WebClient:```java@BeanpublicWebClientwebClient(){returnWebClient.builder().filter(LoggingFilter.logRequest()).filter(LoggingFilter.logResponse()).build();}```####方式二:使用AOP拦截同样,我们可以使用AOP来拦截WebClient的方法调用。但由于WebClient的方法返回的是Mono或Flux,我们需要特别注意异步处理。**示例代码:**```javaimportorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;@Aspect@ComponentpublicclassWebClientAspect{@Around("execution(*org.springframework.web.reactive.function.client.WebClient.*(..))")publicObjectlogWebClientCall(ProceedingJoinPointjoinPoint)throwsThrowable{//方法执行前的逻辑System.out.println("BeforeWebClientmethod:"+joinPoint.getSignature().getName());Objectresult=joinPoint.proceed();//执行原方法//注意:这里返回的可能是Mono或Flux,我们可以对它们进行日志记录,但不要阻塞returnresult;}}```###总结对比|客户端|拦截方式|特点||--------------|------------------------------|----------------------------------------------------------------------||RestTemplate|ClientHttpRequestInterceptor|同步拦截,直接操作请求和响应对象,简单易用。||RestTemplate|AOP|可以拦截任意方法,但可能对性能有影响,且需要处理同步调用。||WebClient|ExchangeFilterFunction|异步非阻塞,适合响应式编程,可以操作请求和响应的发布者。||WebClient|AOP|可以拦截任意方法,但由于异步特性,处理起来相对复杂,可能不直观。|###建议-对于RestTemplate,推荐使用`ClientHttpRequestInterceptor`,因为它专为同步HTTP请求设计,使用简单。-对于WebClient,推荐使用`ExchangeFilterFunction`,因为它与响应式编程模型紧密结合,可以非阻塞地处理请求和响应。###相关问题§§相关问题§§1.如何在RestTemplate的拦截器中修改请求头?2.在WebClient的过滤器中如何实现重试机制?3.使用AOP拦截RestTemplate时,如何避免对某些特定方法进行拦截?4.在WebClient的过滤器中如何读取和修改请求体?5.RestTemplate和WebClient在异常处理上有什么不同,如何在拦截中进行统一异常处理?</think>### Java中RestTemplate和WebClient拦截方式种类 在Java中,对RestTemplate和WebClient进行拦截主要通过以下两种核心方式实现: #### 一、RestTemplate拦截方式 1. **ClientHttpRequestInterceptor(内置拦截器)** RestTemplate原生支持的拦截机制,通过实现接口拦截HTTP请求/响应: ```java public class CustomInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { // 请求前逻辑(如修改header) request.getHeaders().add("X-Trace-ID", UUID.randomUUID().toString()); // 执行请求 ClientHttpResponse response = execution.execute(request, body); // 响应后逻辑(如日志记录) System.out.println("Response status: " + response.getStatusCode()); return response; } } // 注册拦截器 RestTemplate restTemplate = new RestTemplate(); restTemplate.getInterceptors().add(new CustomInterceptor()); ``` **特点**:直接操作请求/响应对象,同步阻塞模型[^2]。 2. **AOP(面向切面编程)** 通过Spring AOP拦截RestTemplate方法调用: ```java @Aspect @Component public class RestTemplateAspect { @Around("execution(* org.springframework.web.client.RestTemplate.*(..))") public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); // 执行原方法 long duration = System.currentTimeMillis() - start; System.out.println("Method " + joinPoint.getSignature().getName() + " executed in " + duration + "ms"); return result; } } ``` **特点**:可拦截所有方法调用,适用于监控/日志等横切关注点[^2]。 --- #### 二、WebClient拦截方式 1. **ExchangeFilterFunction(内置过滤器)** WebClient原生支持的响应式拦截机制: ```java ExchangeFilterFunction logFilter = (request, next) -> { System.out.println("Request: " + request.method() + " " + request.url()); return next.exchange(request).doOnNext(response -> System.out.println("Response: " + response.statusCode()) ); }; WebClient client = WebClient.builder() .filter(logFilter) .build(); ``` **特点**:非阻塞异步模型,支持链式处理[^1]。 2. **AOP(面向切面编程)** 拦截WebClient构建过程或方法调用: ```java @Aspect @Component public class WebClientAspect { @Before("execution(* org.springframework.web.reactive.function.client.WebClient.*(..))") public void logWebClientCall(JoinPoint joinPoint) { System.out.println("WebClient method invoked: " + joinPoint.getSignature().getName()); } } ``` **特点**:适用于方法级拦截,但需注意异步特性(如Reactor的Mono/Flux)[^1]。 --- ### 核心对比总结 | 特性 | RestTemplate | WebClient | |---------------------|---------------------------------------|------------------------------------| | **拦截机制** | `ClientHttpRequestInterceptor` | `ExchangeFilterFunction` | | **编程模型** | 同步阻塞 | 异步非阻塞 | | **AOP适用性** | 方法级拦截简单 | 需处理响应式类型(Mono/Flux) | | **典型场景** | 传统应用/简单拦截 | 高并发/响应式系统 | | **请求修改能力** | 直接操作HttpRequest对象 | 通过ClientRequest.from()克隆修改 | > **最佳实践建议**: > - 优先使用原生拦截机制(`ClientHttpRequestInterceptor`/`ExchangeFilterFunction`)进行HTTP层拦截 > - AOP更适合业务层拦截(如统一日志、性能监控) > - WebClient拦截需配合Reactor操作符(如`doOnNext`, `doOnError`)处理异步流[^1][^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值