当前位置: 首页 > wzjs >正文

怎么看网站用哪个系统做的西安旅游景点排名前十名

怎么看网站用哪个系统做的,西安旅游景点排名前十名,wordpress静态路由,网站的宗旨在微服务架构中,获取 HTTP 请求头信息与在单体 Spring MVC 应用中类似,但也需要考虑一些微服务特有的场景,比如服务间的调用和上下文传播。 以下是在基于 Spring (特别是 Spring Boot / Spring Cloud) 的微服务中获取请求头信息的几种主要方…

在微服务架构中,获取 HTTP 请求头信息与在单体 Spring MVC 应用中类似,但也需要考虑一些微服务特有的场景,比如服务间的调用和上下文传播。

以下是在基于 Spring (特别是 Spring Boot / Spring Cloud) 的微服务中获取请求头信息的几种主要方式:

1. 在 Controller 层使用 @RequestHeader (最常用)

这是最直接、最标准的方式,与传统 Spring MVC 完全一致。当请求到达微服务 Controller 时,可以使用 @RequestHeader 注解将特定的请求头值注入到方法参数中。

import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;
import java.util.Optional;@RestController
public class HeaderApiController {// 1. 获取单个必需的 Header@GetMapping("/api/service-a/resource")public ResponseEntity<String> getResource(@RequestHeader("Authorization") String authorizationToken,@RequestHeader("X-Request-ID") String requestId) { // 例如,用于分布式追踪的请求 IDSystem.out.println("Authorization Token: " + authorizationToken);System.out.println("Request ID: " + requestId);// ... 处理业务逻辑 ...return ResponseEntity.ok("Resource data from Service A, Request ID: " + requestId);}// 2. 获取单个可选的 Header (带默认值)@GetMapping("/api/service-a/config")public ResponseEntity<String> getConfig(@RequestHeader(name = "X-Tenant-ID", defaultValue = "default_tenant") String tenantId) {System.out.println("Processing request for Tenant ID: " + tenantId);// ... 根据 tenantId 处理逻辑 ...return ResponseEntity.ok("Configuration for tenant: " + tenantId);}// 3. 获取单个可选的 Header (可能为 null 或使用 Optional)@GetMapping("/api/service-a/optional")public ResponseEntity<String> getOptionalData(@RequestHeader(name = "X-User-Preferences", required = false) String preferences,@RequestHeader(name = "X-Device-Type", required = false) Optional<String> deviceType) {String prefMessage = (preferences != null) ? "Preferences: " + preferences : "Preferences header missing.";String deviceMessage = deviceType.map(dt -> "Device Type: " + dt).orElse("Device Type header missing.");System.out.println(prefMessage);System.out.println(deviceMessage);return ResponseEntity.ok(prefMessage + " | " + deviceMessage);}// 4. 获取所有 Headers (推荐使用 HttpHeaders)@GetMapping("/api/service-a/all-headers")public ResponseEntity<String> getAllHeaders(@RequestHeader HttpHeaders headers) {// HttpHeaders 提供了便捷方法访问各种标准和自定义头String contentType = String.valueOf(headers.getContentType());long traceId = headers.getFirst("X-B3-TraceId") != null ? Long.parseLong(headers.getFirst("X-B3-TraceId"), 16) : -1L; // 示例:处理追踪头System.out.println("Received Headers: " + headers);System.out.println("Content-Type: " + contentType);System.out.println("Trace ID (if present): " + traceId);// 不太推荐的方式:// @RequestHeader Map<String, String> headerMap // 可能丢失多值 Header// @RequestHeader MultiValueMap<String, String> headerMultiMap // 可以处理多值 Headerreturn ResponseEntity.ok("Processed request with headers. Trace ID (long): " + traceId);}
}

2. 通过 HttpServletRequest (方法参数注入)

虽然不如 @RequestHeader 直接,但你仍然可以像在传统 Servlet 应用中那样,将 HttpServletRequest 注入到 Controller 方法中,然后调用其 getHeader(), getHeaders(), getHeaderNames() 等方法。

import javax.servlet.http.HttpServletRequest;
// ... 其他 imports ...@RestController
public class ServletHeaderController {@GetMapping("/api/service-b/info")public ResponseEntity<String> getServiceInfo(HttpServletRequest request) {String userAgent = request.getHeader("User-Agent");String customHeader = request.getHeader("X-Custom-Data");// 获取某个 header 的所有值 (如果允许重复)java.util.Enumeration<String> acceptHeaders = request.getHeaders("Accept");System.out.println("User-Agent (via HttpServletRequest): " + userAgent);System.out.println("X-Custom-Data (via HttpServletRequest): " + customHeader);StringBuilder acceptHeaderString = new StringBuilder();if (acceptHeaders != null) {while(acceptHeaders.hasMoreElements()) {acceptHeaderString.append(acceptHeaders.nextElement()).append(", ");}}System.out.println("Accept Headers: " + acceptHeaderString);// ... 业务逻辑 ...return ResponseEntity.ok("Info from Service B. User-Agent starts with: " + (userAgent != null ? userAgent.substring(0, 10) : "N/A"));}
}

何时使用? 当需要访问 @RequestHeader 不直接支持的功能,或者需要更底层的控制时(虽然比较少见)。

3. 在过滤器 (Filter) 或拦截器 (Interceptor) 中获取

在微服务中,很多横切关注点(Cross-Cutting Concerns)如认证、授权、日志记录、分布式追踪上下文传播等,在请求到达 Controller 之前处理。这时,可以在 FilterInterceptor 中获取请求头。

示例 (使用 Servlet Filter):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC; // 用于日志上下文
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; // 保证每个请求只执行一次import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;@Component // 让 Spring 管理这个 Filter
public class LoggingAndTraceFilter extends OncePerRequestFilter {private static final Logger log = LoggerFactory.getLogger(LoggingAndTraceFilter.class);private static final String TRACE_ID_HEADER = "X-Trace-ID";private static final String TENANT_ID_HEADER = "X-Tenant-ID";private static final String TRACE_ID_MDC_KEY = "traceId";private static final String TENANT_ID_MDC_KEY = "tenantId";@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {// 1. 从请求头获取或生成 Trace IDString traceId = request.getHeader(TRACE_ID_HEADER);if (traceId == null || traceId.isEmpty()) {traceId = UUID.randomUUID().toString();log.debug("Generated new Trace ID: {}", traceId);// 如果需要传播,可将生成的 ID 添加到响应头或下游请求头}// 2. 从请求头获取 Tenant IDString tenantId = request.getHeader(TENANT_ID_HEADER);if (tenantId == null) {tenantId = "unknown"; // Or handle as an error depending on requirements}// 3. 将信息放入 MDC (Mapped Diagnostic Context) 以便日志自动包含这些信息MDC.put(TRACE_ID_MDC_KEY, traceId);MDC.put(TENANT_ID_MDC_KEY, tenantId);log.info("Request received: {} {} for Tenant: {}", request.getMethod(), request.getRequestURI(), tenantId);try {// 继续处理请求链 (最终会到达 Controller)filterChain.doFilter(request, response);} finally {// 4. 请求处理完毕后,清理 MDC,避免影响线程池中的下一个请求MDC.remove(TRACE_ID_MDC_KEY);MDC.remove(TENANT_ID_MDC_KEY);log.info("Request completed: {} {}", request.getMethod(), request.getRequestURI());}}
}

场景:

  • 分布式追踪: 获取或生成追踪 ID (如 X-Request-ID, X-B3-TraceId),放入日志上下文 (MDC),并在调用下游服务时传递。Spring Cloud Sleuth 等库会自动处理很多这类逻辑。
  • 认证/授权: 读取 Authorization 头,验证 Token,并将用户信息放入安全上下文 (SecurityContextHolder)。Spring Security 等框架会做这些。
  • 多租户: 读取 X-Tenant-ID 头,设置当前线程的租户上下文。
  • 通用日志: 记录所有请求的某些通用头信息。

4. 在 Service 层或更深层访问 (需要传递或使用上下文)

如果业务逻辑层 (Service Layer) 或其他非 Controller 组件需要访问请求头信息,不推荐直接依赖 HttpServletRequestRequestContextHolder (因为它会耦合业务逻辑与 Web 层)。

推荐的方式是:

  • 参数传递 (首选): 在 Controller 层使用 @RequestHeader 获取所需头信息,然后将其作为参数传递给 Service 方法。这是最清晰、最解耦、最易于测试的方式。

    // Controller
    @GetMapping("/api/service-c/process")
    public ResponseEntity<String> processData(@RequestHeader("X-User-ID") String userId,@RequestHeader("X-Correlation-ID") String correlationId) {String result = myService.processUserData(userId, correlationId); // 传递给 Servicereturn ResponseEntity.ok(result);
    }// Service
    @Service
    public class MyService {public String processUserData(String userId, String correlationId) {// 使用 userId 和 correlationId 进行处理System.out.println("Service processing for User: " + userId + ", Correlation: " + correlationId);// ...return "Processed data for user " + userId;}
    }
    
  • 使用线程本地上下文 (ThreadLocal): 对于像追踪 ID、租户 ID、用户 ID 这样需要在整个请求处理链中都可用的信息,可以在 Filter/Interceptor 中将其读取并存入自定义的 ThreadLocal 变量或使用现成的上下文机制(如 Spring Security 的 SecurityContextHolder、日志的 MDC、或自定义的 TenantContextHolder)。然后在 Service 层或其他地方从该上下文中读取。

    // 在 Filter/Interceptor 中设置 (如上面的 LoggingAndTraceFilter 示例设置 MDC)// 在 Service 层获取
    @Service
    public class AnotherService {private static final Logger log = LoggerFactory.getLogger(AnotherService.class);public void doSomething() {String traceId = MDC.get("traceId"); // 从 MDC 获取String tenantId = MDC.get("tenantId");// 或者从 SecurityContextHolder 获取用户信息// Authentication authentication = SecurityContextHolder.getContext().getAuthentication();// String username = (authentication != null) ? authentication.getName() : "N/A";// 使用这些上下文信息log.info("Doing something within service context. Trace ID: {}, Tenant ID: {}", traceId, tenantId);// ...}
    }
    

总结与建议

  1. Controller 层: 优先使用 @RequestHeader。清晰、简洁,是 Spring 推荐的方式。使用 HttpHeaders 参数可以获取所有头信息。
  2. Filter/Interceptor: 用于处理横切关注点,如日志、认证、追踪、多租户等,获取相关头信息,并可以设置请求/线程上下文(如 MDC, SecurityContext, 自定义 ThreadLocal)。
  3. Service 层及以下: 优先通过方法参数传递从 Controller 获取的头信息。如果信息是全局上下文(如追踪 ID、用户 ID、租户 ID),则通过 Filter/Interceptor 设置并在需要时从线程本地上下文(MDC, SecurityContextHolder, 自定义 ContextHolder)读取。避免直接依赖 Web 层 API
  4. 框架利用: 充分利用 Spring Cloud Sleuth (用于追踪头传播)、Spring Security (用于认证头处理) 等框架,它们能自动处理很多常见的头信息获取和上下文管理工作。

根据具体需求选择最合适的方式。在微服务中,清晰的处理和传递请求头对于保证服务的正确性、可观测性和安全性至关重要。

http://www.dtcms.com/wzjs/836887.html

相关文章:

  • 个人如何做seo推广深圳网站seo哪家快
  • 公司网站制作需要什么步骤网推拉新怎么做
  • 怎样提高网站速度加强
  • 什么网站做招聘效果好17网站一起做网店后台
  • 门户网站建设哪专业动漫制作技术与动漫设计
  • 如何建设一个属于自己的网站哪个网站好
  • 电商网站更适合电商服务
  • 顺义网站开发国家中小学网络云平台
  • 南昌简单做网站网站开发与规划
  • 房产机构网站建设目标定位网站建设意味着什么
  • 网站收录情况人工智能公司
  • 网站幻灯通栏代码下载app并安装到手机
  • 大连市网站推广公司网站做友链盈利
  • 黄骅市做网站深圳网站设计按天收费
  • 成都建设施工安全协会网站网站接广告平台
  • 婚纱网站建设微信群网站建设与维护教学计划
  • 手机网站功能分析wordpress为用户添加积分
  • 西安网站建设个人忻州集团网站建设
  • 学校网站建设项目背景北京网站开发浩森宇特
  • vs2010网站开发实例网站建设应注意什么问题
  • 做简历网站知乎seo综合诊断工具
  • 专业做网站排名公司电话做的好详情页网站
  • 网站制作零基础学习定制网站开发流程图
  • 东莞市企业网站建设哪家好开设类似于京东商城这类购物网站
  • 网站设计网wordpress++群晖
  • 网络推广网站有哪些学网站开发容易吗
  • 网站添加对联广告代码网站管理系统后台不能发布文章了
  • 自适应平台网站WordPress图片方案
  • 网站开发如何设置视频wordpress插件doc
  • 网站中数据查询如何做做门窗五金的网站