spring 如何使用aspect将我的自定义头添加到HttpServletRequest?

wz1wpwve  于 2023-08-02  发布在  Spring
关注(0)|答案(1)|浏览(149)

我试图在控制器处理程序方法实际执行之前创建一个方面来覆盖HttpServletRequest参数。但结果是HttpServletRequest始终是RequestFacade示例,即使我在方面方法中将其替换为自定义HttpServletRequestWrapper
代码如下:

  1. // the annotation:
  2. @Target({ElementType.METHOD})
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Documented
  5. public @interface MyAnnotation {
  6. }
  7. // the aspect:
  8. @Component
  9. @Aspect
  10. @Slf4j
  11. public class MyAspect {
  12. @Pointcut("@annotation(com.example.springtest.annotation.MyAnnotation)")
  13. public void pointcut() {
  14. }
  15. @Around("pointcut()")
  16. public Object setHeader(ProceedingJoinPoint pjp) throws Throwable {
  17. var args = pjp.getArgs();
  18. var signature = (MethodSignature) pjp.getSignature();
  19. var method = signature.getMethod();
  20. var annotations = method.getDeclaredAnnotations();
  21. var need = Arrays.stream(annotations).anyMatch(a -> a.annotationType().equals(MyAnnotation.class));
  22. if (!need) {
  23. return pjp.proceed();
  24. }
  25. for (var i = 0; i < args.length; i++) {
  26. var arg = args[i];
  27. if (arg instanceof HttpServletRequest request) {
  28. args[i] = new HttpServletRequestWrapper(request) {
  29. @Override
  30. public String getHeader(String name) {
  31. if (name.equalsIgnoreCase("my-header")) {
  32. return "my-header";
  33. } else {
  34. return super.getHeader(name);
  35. }
  36. }
  37. };
  38. }
  39. }
  40. return pjp.proceed();
  41. }
  42. }
  43. // the bootstrap class:
  44. @Configurable
  45. @EnableAspectJAutoProxy
  46. @SpringBootApplication
  47. public class SpringtestApplication {
  48. public static void main(String[] args) {
  49. SpringApplication.run(SpringtestApplication.class, args);
  50. }
  51. }
  52. // and the controller
  53. @RestController
  54. public class TestController {
  55. private static final Logger log = LoggerFactory.getLogger(TestController.class);
  56. @MyAnnotation
  57. @GetMapping("/get-my-header")
  58. public String getMyHeader(HttpServletRequest request) {
  59. if (Objects.requireNonNull(request) instanceof HttpServletRequestWrapper) {
  60. log.info("is wrapper");
  61. } else {
  62. log.info("request:{}", request.getClass());
  63. }
  64. return request.getHeader("my-header");
  65. }
  66. }

字符串
发生了什么事?在我替换了HttpServletRequest参数之后,是否有其他代理类示例更改了我的参数?
日志显示方面和控制器中的请求参数都是RequestFacade示例。
我还尝试创建一个服务方法,并直接将我的自定义HttpServletRequestWrapper示例发送给它。这一次参数没有改变。

j9per5c4

j9per5c41#

我恐怕摆弄请求头的修改不是那么容易的。我也担心这方面不是一条路要走。
这里是Sping Boot 2的一个最小且可重复的示例,通过在自定义拦截器中设置一个命名的attribute来实现您想要的内容,该拦截器在@RestController的方法中捕获。

拦截器

  1. @Component
  2. public class CustomInterceptor implements HandlerInterceptor {
  3. @Override
  4. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
  5. request.setAttribute("fooAttribute", "fooValue");
  6. return true;
  7. }
  8. }

字符串

配置

  1. @Configuration
  2. public class WebMvcConfiguration implements WebMvcConfigurer {
  3. @Autowired
  4. private CustomInterceptor customInterceptor;
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. registry.addInterceptor(customInterceptor);
  8. }
  9. }

控制器

我让属性在body中返回。

  1. @GetMapping("hello")
  2. public ResponseEntity<String> hello(@RequestAttribute String fooAttribute) {
  3. return ResponseEntity.ok(fooAttribute);
  4. }


测试一下:

  1. curl http://localhost:8080/hello
  1. fooValue
展开查看全部

相关问题