我试图在控制器处理程序方法实际执行之前创建一个方面来覆盖HttpServletRequest
参数。但结果是HttpServletRequest
始终是RequestFacade
示例,即使我在方面方法中将其替换为自定义HttpServletRequestWrapper
。
代码如下:
// the annotation:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
}
// the aspect:
@Component
@Aspect
@Slf4j
public class MyAspect {
@Pointcut("@annotation(com.example.springtest.annotation.MyAnnotation)")
public void pointcut() {
}
@Around("pointcut()")
public Object setHeader(ProceedingJoinPoint pjp) throws Throwable {
var args = pjp.getArgs();
var signature = (MethodSignature) pjp.getSignature();
var method = signature.getMethod();
var annotations = method.getDeclaredAnnotations();
var need = Arrays.stream(annotations).anyMatch(a -> a.annotationType().equals(MyAnnotation.class));
if (!need) {
return pjp.proceed();
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg instanceof HttpServletRequest request) {
args[i] = new HttpServletRequestWrapper(request) {
@Override
public String getHeader(String name) {
if (name.equalsIgnoreCase("my-header")) {
return "my-header";
} else {
return super.getHeader(name);
}
}
};
}
}
return pjp.proceed();
}
}
// the bootstrap class:
@Configurable
@EnableAspectJAutoProxy
@SpringBootApplication
public class SpringtestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringtestApplication.class, args);
}
}
// and the controller
@RestController
public class TestController {
private static final Logger log = LoggerFactory.getLogger(TestController.class);
@MyAnnotation
@GetMapping("/get-my-header")
public String getMyHeader(HttpServletRequest request) {
if (Objects.requireNonNull(request) instanceof HttpServletRequestWrapper) {
log.info("is wrapper");
} else {
log.info("request:{}", request.getClass());
}
return request.getHeader("my-header");
}
}
字符串
发生了什么事?在我替换了HttpServletRequest
参数之后,是否有其他代理类示例更改了我的参数?
日志显示方面和控制器中的请求参数都是RequestFacade
示例。
我还尝试创建一个服务方法,并直接将我的自定义HttpServletRequestWrapper
示例发送给它。这一次参数没有改变。
1条答案
按热度按时间j9per5c41#
我恐怕摆弄请求头的修改不是那么容易的。我也担心这方面不是一条路要走。
这里是Sping Boot 2的一个最小且可重复的示例,通过在自定义拦截器中设置一个命名的
attribute
来实现您想要的内容,该拦截器在@RestController
的方法中捕获。拦截器
字符串
配置
型
控制器
我让属性在body中返回。
型
测试一下: