背景
我正在使用 Spring MVC 创建 RESTful 服务。目前,我有以下 Controller 结构:
@RestController
@RequestMapping(path = "myEntity", produces="application/json; charset=UTF-8")
public class MyEntityController {
@RequestMapping(path={ "", "/"} , method=RequestMethod.POST)
public ResponseEntity<MyEntity> createMyEntity(
@RequestBody MyEntity myEntity,
@RequestHeader("X-Client-Name") String clientName) {
myEntity.setClientName(clientName);
//rest of method declaration...
}
@RequestMapping(path={ "/{id}"} , method=RequestMethod.PUT)
public ResponseEntity<MyEntity> updateMyEntity(
@PathVariable Long id,
@RequestBody MyEntity myEntity,
@RequestHeader("X-Client-Name") String clientName) {
myEntity.setClientName(clientName);
//rest of method declaration...
}
@RequestMapping(path={ "/{id}"} , method=RequestMethod.PATCH)
public ResponseEntity<MyEntity> partialUpdateMyEntity(
@PathVariable Long id,
@RequestBody MyEntity myEntity,
@RequestHeader("X-Client-Name") String clientName) {
myEntity.setClientName(clientName);
//rest of method declaration...
}
}
如您所见,所有这三种方法都为 header @RequestHeader("X-Client-Name") String clientName
接收相同的参数,并以相同的方式将其应用于每个方法: myEntity.setClientName(clientName)
。我将创建类似的 Controller ,对于 POST、PUT 和 PATCH 操作,将包含几乎相同的代码,但用于其他实体。目前,大多数实体都设计为通过父类(super class)支持此字段:
public class Entity {
protected String clientName;
//getters and setters ...
}
public class MyEntity extends Entity {
//...
}
此外,我使用拦截器来验证是否为请求设置了 header 。
问题
如何避免通过 Controller 类和方法重复相同的代码?有没有一种干净的方法来实现它?还是我应该声明变量并在各处重复这些行?
西类牙社区也有人问过这个问题。这是 the link .
最佳答案
我的建议是将 header 值存储在 Spring 拦截器或过滤器内的请求作用域 bean 中。然后你可以在任何你想要的地方 Autowiring 这个 bean - 服务或 Controller 并使用存储的客户端名称值。
代码示例:
public class ClientRequestInterceptor extends HandlerInterceptorAdapter {
private Entity clientEntity;
public ClientRequestInterceptor(Entity clientEntity) {
this.clientEntity = clientEntity;
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String clientName = request.getHeader("X-Client-Name");
clientEntity.setClientName(clientName);
return true;
}
}
在你的配置文件中:
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(clientRequestInterceptor());
}
@Bean(name="clientEntity")
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Entity clientEntity() {
return new Entity();
}
@Bean
public ClientRequestInterceptor clientRequestInterceptor() {
return new ClientRequestInterceptor(clientEntity());
}
}
然后,假设我们必须在我们的 Controller 中使用这个 bean:
@RestController
@RequestMapping(path = "myEntity", produces="application/json; charset=UTF-8")
public class MyEntityController {
@Autowired
private Entity clientEntity; // here you have the filled bean
@RequestMapping(path={ "", "/"} , method=RequestMethod.POST)
public ResponseEntity<MyEntity> createMyEntity(@RequestBody MyEntity myEntity) {
myEntity.setClientName(clientEntity.getClientName());
//rest of method declaration...
}
// rest of your class methods, without @RequestHeader parameters
}
我没有编译这段代码,如果有错误请指正。
关于java - 如何装饰所有请求以从 header 中取值并将其添加到正文参数中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36295095/