Spring Boot инкапсулирует данные формы с помощью аннотации @ModelAttribute - PullRequest
1 голос
/ 27 июня 2019

Фон и контекст

У меня есть приложение Spring Boot, которое запускается как исполняемый JAR во встроенном контейнере Tomcat. Приложение предоставляет множество традиционных RESTful-сервисов. В дополнение к традиционным сервисам RESTful мне также нужно создать конечную точку, которая больше похожа на традиционный сервлет.

Я определяю Традиционные службы RESTful как конечные точки, которые используют стандартные методы HTTP (GET, POST, PUT и т. Д.) И принимают тела запросов JSON или XML (когда используется соответствующий метод) и возвращают JSON или XML. Я определяю традиционный в отличие от сервлетоподобных конечных точек, которые принимают multipart / form-date и перенаправляют клиента после вызова метода.

Эта подпись конечной точки выглядит следующим образом

  1. Принимает составные данные / данные формы
  2. Метод POST
  3. Перенаправляет пользователей на базовый URL-адрес значения, назначенного заголовку referer после отправки

Данные формы, отправляемые в эту конечную точку, отправляются из формы, которой я не владею или не контролирую (я включил HTML-форму ниже). Поскольку форма имеет много пар ключ / значение со странным именем, я хочу инкапсулировать отправку в FormSubmission объекте.

код

Ниже приведена форма для отправки данных на мою конечную точку

<form novalidate="" accept-charset="UTF-8" action="https://baseurl.com/brochure" enctype="multipart/form-data" id="hsForm_4b5eec88-e83b-474f-9c51-6204df71e5a5" method="POST" class="hs-form stacked hs-form-private hs-form-4b5eec88-e83b-474f-9c51-6204df71e5a5_bc44b3dd-63e5-4a6f-85d2-4c2c4b436bf8" data-form-id="4b5eec88-e83b-474f-9c51-6204df71e5a5" data-portal-id="482700" target="target_iframe_4b5eec88-e83b-474f-9c51-6204df71e5a5" data-reactid=".hbspt-forms-0">
   <input id="firstname-4b5eec88-e83b-474f-9c51-6204df71e5a5" type="text" name="firstname"></div>
   <input id="lastname-4b5eec88-e83b-474f-9c51-6204df71e5a5" type="text" name="lastname"></div>
   <input id="address-4b5eec88-e83b-474f-9c51-6204df71e5a5" type="text" name="address"></div>
   <select id="state-4b5eec88-e83b-474f-9c51-6204df71e5a5" name="state" >
      <option value="" disabled="" selected="" >- Please Select -</option>
      <option value="AL" >Alabama</option>
      <option value="AK">Alaska</option>
   </select>
   <select id="country_custom-4b5eec88-e83b-474f-9c51-6204df71e5a5"  name="country_custom" ">
      <option value="United States">United States</option>
      <option value="Canada">Canada</option>
   </select>
   <input id="zip-4b5eec88-e83b-474f-9c51-6204df71e5a5" class="hs-input" type="text" name="zip"></div>
   <input id="email-4b5eec88-e83b-474f-9c51-6204df71e5a5" class="hs-input" type="email" name="email"></div>
   <select id="want_to_talk_with_an_area_builder_-4b5eec88-e83b-474f-9c51-6204df71e5a5" name="want_to_talk_with_an_area_builder_">
      <option value="Yes">Yes, now please.</option>
      <option value="No">No thank you</option>
   </select>
   <select id="blog_pool_life_2_subscription-4b5eec88-e83b-474f-9c51-6204df71e5a5" name="blog_pool_life_2_subscription"
      <option value="instant">Instant</option>
      <option value="daily">Daily</option>
   </select>
</form>

Приведенная выше форма отправляет multipart / form-data следующей конечной точке

@PostMapping("/brochure")
public RedirectView post( @ModelAttribute FormSubmission submission, RedirectAttributes attributes, @RequestHeader( value = "referer", required = true ) final String referer ) {

    String base = getBaseURL( referer );

    System.out.println( submission.getLastName() );

    return new RedirectView( base );
}

А класс FormSubmission выглядит следующим образом

public class FormSubmission {

    private String firstName;
    private String lastName;
    private String street;
    private String city;
    private String state;
    private String zip;
    private String email;
    private String country;
    private Boolean mail;
    private String speakWithBuilder;

    @ModelAttribute("city")
    public String getCity() {
        return city;
    }

    @ModelAttribute("city")
    public void setCity(String city) {
        this.city = city;
    }

    @ModelAttribute("state")
    public String getState() {
        return state;
    }

    @ModelAttribute("state")
    public void setState(String state) {
        this.state = state;
    }

    @ModelAttribute("zip")
    public String getZip() {
        return zip;
    }

    @ModelAttribute("zip")
    public void setZip(String zip) {
        this.zip = zip;
    }

    @ModelAttribute("country_custom")
    public String getEmail() {
        return email;
    }

    @ModelAttribute("country_custom")
    public void setEmail(String email) {
        this.email = email;
    }

    @ModelAttribute("country_custom")
    public String getCountry() {
        return country;
    }

    @ModelAttribute("country_custom")
    public void setCountry(String country) {
        this.country = country;
    }

    @ModelAttribute("blog_pool_life_2_subscription")
    public Boolean isMail() {
        return mail;
    }

    @ModelAttribute("blog_pool_life_2_subscription")
    public void setMail( String mail ) {
        this.mail = mail.toLowerCase().contains( "yes" );
    }

    @ModelAttribute("firstname")
    public String getFirstName() {
        return firstName;
    }

    @ModelAttribute("firstname")
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @ModelAttribute("lastname")
    public String getLastName() {
        return lastName;
    }

    @ModelAttribute("lastname")
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @ModelAttribute("address")
    public String getStreet() {
        return street;
    }

    @ModelAttribute("address")
    public void setStreet(String street) {
        this.street = street;
    }

    @ModelAttribute("want_to_talk_with_an_area_builder_")
    public String getSpeakWithBuilder() {
        return speakWithBuilder;
    }

    @ModelAttribute("want_to_talk_with_an_area_builder_")
    public void setSpeakWithBuilder(String speakWithBuilder) {
        this.speakWithBuilder = speakWithBuilder;
    }


}

Постановка проблемы

Как вы можете видеть, моя конечная точка определяет @ModelAttribute FormSubmission submission, и мой объект представления записывает каждому получателю и установщику имена элементов из формы HTML. Тем не менее, операторы печати показывают как ноль. Я поклялся, что это работало несколько дней назад, и теперь все значения равны нулю. Пожалуйста, совет.

Post Script # 1

Для дополнительного пояснения, когда я изменяю свою подпись конечной точки следующим образом

@PostMapping("/brochure")
public RedirectView post( @ModelAttribute("firstname") String firstName, RedirectAttributes attributes, @RequestHeader( value = "referer", required = true ) final String referer ) {

    System.out.println( firstName );
    String base = getBaseURL( referer );


    return new RedirectView( base );
}

И вызовите конечную точку, имя которой будет напечатано успешно. Надеюсь, это лучше иллюстрирует, что мой вопрос конкретно касается инкапсуляции этих пар ключ-значение данных формы в объекте.

Post Script # 2

Мне удалось успешно инкапсулировать данные, если я:

  1. Удалите @ModelAttribute из параметра FormSubmission и
  2. Удалите @ModelAttribute из методов получения и установки для закрытых переменных-членов внутри FormSubmission

Это лучше, но я все же хотел бы иметь возможность именовать переменными в соответствии с соглашением об именах Java, что я не могу сделать без ModelAttribute, так как я не управляю формой

...