java - 如何装饰所有请求以从 header 中取值并将其添加到正文参数中?

标签 java spring rest spring-mvc http-headers

背景

我正在使用 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/

相关文章:

java - Selenium driver.getPageSource() ,将链接更改为绝对

Spring @ConfigurationProperties 继承/嵌套

java - Apache 没有将完整的参数传递给 JBoss 6/Spring Web MVC

java - 如何通过 RESTful API 从 Android 访问 Heroku 上的数据库?

java - 更新时将数据发送到另一台服务器

java - 接口(interface)编程很棒,我 100% 同意,但它总是可行吗?

java - 如何添加输入数字以消除重复的数字?

java - MultipartEntityBuilder 将 Content-Disposition header 添加到二进制文件并破坏它

java - 在 Spring 5.1.0 中加载和切换属性源的最优雅的方式是什么?

Javascript - if(变量)检查 'undefined' 失败