如何修饰所有从标头中获取值并将其添加到body参数中的请求? [英] How to decorate all requests to take a value from header and add it in the body parameter?

查看:217
本文介绍了如何修饰所有从标头中获取值并将其添加到body参数中的请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring MVC创建RESTful服务.当前,我具有以下控制器结构:

I'm creating RESTful services using Spring MVC. Currently, I have the following structure for a 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...
    }
}

如您所见,这三种方法都为头文件@RequestHeader("X-Client-Name") String clientName接收相同的参数,并以相同的方式将其应用于每种方法:myEntity.setClientName(clientName).我将创建类似的控制器,并且对于POST,PUT和PATCH操作将包含几乎相同的代码,但适用于其他实体.当前,大多数实体旨在通过超类来支持该字段:

As you can see, all these three methods receive the same parameter for the header @RequestHeader("X-Client-Name") String clientName and applies it in the same way on each method: myEntity.setClientName(clientName). I will create similar controllers and for POST, PUT and PATCH operations will contain almost the same code but for other entities. Currently, most entities are designed to support this field vía a super class:

public class Entity {
    protected String clientName;
    //getters and setters ...
}
public class MyEntity extends Entity {
    //...
}

此外,我使用拦截器来验证是否已为请求设置标头.

Also, I use an interceptor to verify that the header is set for requests.

如何避免通过控制器类和方法重复相同的代码?有没有一种干净的方法来实现它?还是应该声明该变量并在各处重复这些行?

How can I avoid repeating the same code through controller classes and methods? Is there a clean way to achieve it? Or should I declare the variable and repeat those lines everywhere?

这个问题在西班牙社区也被问到了.这是链接.

This question was also asked in the Spanish community. Here's the link.

推荐答案

我在西班牙语站点(我也发布了此问题)上得到了一个有趣的答案,并基于该答案我可以生成适合此需求的我的答案.这是我对SOes的回答.

I've got an interesting answer in the Spanish site (where I also posted this question) and based on that answer I could generate mine that adapts to this need. Here's my answer on SOes.

基于 @PaulVargas的答案和@jasilva的想法(在控制器中使用继承),我基于这种情况下更强大的解决方案.设计由两部分组成:

Based on @PaulVargas's answer and an idea from @jasilva (use inheritance in controller) I though on a stronger solution for this case. The design consists of two parts:

  1. 为具有此行为的控制器定义超类.我将此类称为BaseController<E extends Entity>,因为Entity是几乎所有我的实体的超类(在问题中解释).在此类中,我将检索@RequestBody E entity参数的值并将其分配给@ModelAttribute参数,如@PaulVargas所解释的.泛型功能在这里有很大帮助.

  1. Define a super class for controllers with this behavior. I call this class BaseController<E extends Entity> because Entity is the super class for almost al my entities (explained in the question). In this class I'll retrieve the value of @RequestBody E entity parameter and assign it into a @ModelAttribute parameter like @PaulVargas explains. Generics power helps a lot here.

我的控制器将扩展BaseController<ProperEntity>,其中ProperEntity是我需要使用该控制器处理的适当实体类.然后,在这些方法中,只注入@ModelAttribute(如果需要),而不是注入@RequestBody@RequestHeader参数.

My controllers will extend BaseController<ProperEntity> where ProperEntity is the proper entity class I need to handle with that controller. Then, in the methods, instead of injecting @RequestBody and @RequestHeader parameters, I'll only inject the the @ModelAttribute (if needed).

描述性的描述:

//1.
public abstract class BaseController<E extends Entity> {

    @ModelAttribute("entity")
    public E populate(
            @RequestBody(required=false) E myEntity,
            @RequestHeader("X-Client-Name") String clientName) {
        if (myEntity != null) {
            myEntity.setCreatedBy(clientName);
        }
        return myEntity;
    }
}

//2.
@RestController
@RequestMapping(path = "myEntity", produces="application/json; charset=UTF-8")
public class MyEntityController extends BaseController<MyEntity> {

    @RequestMapping(path={ "", "/"} , method=RequestMethod.POST)
    public ResponseEntity<MyEntity> createMyEntity(
        @ModelAttribute("entity") MyEntity myEntity) {
        //rest of method declaration...
    }

    @RequestMapping(path={ "/{id}"} , method=RequestMethod.PUT)
    public ResponseEntity<MyEntity> updateMyEntity(
        @PathVariable Long id,
        @ModelAttribute("entity") MyEntity myEntity) {
        //rest of method declaration...
    }

    @RequestMapping(path={ "/{id}"} , method=RequestMethod.PATCH)
    public ResponseEntity<MyEntity> partialUpdateMyEntity(
        @PathVariable Long id,
        @ModelAttribute("entity") MyEntity myEntity) {
        //rest of method declaration...
    }    
}

通过这种方式,我不需要在每个方法和控制器中重写这些代码行,即可实现我所要求的.

In this way, I don't need to rewrite those lines of code in every method and controller, achieving what I've asked.

这篇关于如何修饰所有从标头中获取值并将其添加到body参数中的请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆