Как преобразовать RequestHeader в пользовательский объект в Spring

У меня есть метод в моем контроллере:

@RequestMapping(method = RequestMethod.POST)
public CustomObject createCustomObject(final @RequestHeader("userId") Long userId) {
   ...
}

Могу ли я написать какой-нибудь пользовательский конвертер или что-то подобное, чтобы преобразовать этот параметр UserId RequestHeader в объект User, поэтому мой метод будет:

@RequestMapping(method = RequestMethod.POST)
public CustomObject createCustomObject(final User user) {
   ...
}

Можно ли сделать с spring -mvc?

Ответ 1

В основном я закончил с предложением из комментариев. Я приведу лишь краткий пример. Допустим, у нас есть следующий контроллер и пользователь POJO:

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;

@RestController
public class SimpleController {

    @GetMapping("/user")
    public String greeting(@RequestHeader(name = "userId") User user) {
        return "Hey, " + user.toString();
    }
}

public class User {
    private String id;
    private String firstName;
    private String lastName;
    ...
}

А потом мы создадим конвертер:

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class UserFromHeaderConverter implements Converter<String, User> {

    @Override
    public User convert(final String userId) {
        // fetch user from the database etc.

        final User user = new User();
        user.setId(userId);
        user.setFirstName("First");
        user.setLastName("Last");

        return user;
    }
}

Пример тестирования: curl --header "userId: 123" localhost:8080/user

Результат будет: Hey, User{id='123', firstName='First', lastName='Last'}

Кстати, я использовал следующие версии: spring-boot:2.0.3 and spring-web:5.0.7

Ответ 2

контроллер

   @RequestMapping(value = "/addAnswer", method = RequestMethod.POST)
   public String addAnswer(Answer answer,ModelMap model,HttpServletRequest request) {
      quizService.addAnswer(answer);
      model.addAttribute("answerList",quizService.getAllAnswers());
      return "answers";
 }      

 @ModelAttribute("answer")
 public Answer createAnswerModel() {
     return new Answer();
 }   

Просмотр

 <form:form method="POST"  commandName="answer"  action="${pageContext.request.contextPath}/admin/addAnswer"  accept-charset="UTF-8">
       <fieldset>
                <label for="answerText"></label><form:textarea  path="answerText"  cssStyle="width:100%" />
                <input type="submit" value="Submit"  class="btn-primary" />
        </fieldset>  
</form:form>

Ответ 3

Если я понимаю вас, вы хотите получить параметр и преобразовать его в сложный объект.

Вы должны определить пользовательский процесс DataBinder, реализующий PropertyEditorSupport и зарегистрировав его для типа.

Например, если вы хотите получить идентификатор формы пользователя bd, создайте класс:

public class UserEditor extends PropertyEditorSupport {

    private final UserDAO   userDao;

    public <T> CacheEditor(UserDAO userDao) {

        this.userDao = userDao;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {

        if (text != null && !text.isEmpty()) {
            Long code = Long.parseLong(text);
            setValue(userDao.getById( code));
        } else {
            setValue(null);
        }
    }
...
}

и редактор регистров:

@Controller
public class MyFormController {
    @Autowire
    private UserDAO userDao;

    @InitBinder
    public void initBinder(WebDataBinder binder) {          
        binder.registerCustomEditor(User.class, new UserEditor(userDao));
    }
....

Дополнительная информация: