Java Spring引导使用@ModelAttribute注释封装表单数据 背景和背景

Java Spring引导使用@ModelAttribute注释封装表单数据 背景和背景,java,spring,spring-boot,spring-mvc,multipartform-data,Java,Spring,Spring Boot,Spring Mvc,Multipartform Data,我有一个Spring引导应用程序,它在嵌入式Tomcat容器中作为可执行JAR运行。该应用程序公开了各种传统的RESTful服务。除了传统的RESTful服务之外,我还需要创建一个更类似于传统servlet的端点 我将传统的RESTful服务定义为使用标准HTTP方法(GET、POST、PUT等)并接受JSON或XML请求体(使用适用方法时)并返回JSON或XML的端点。我定义了传统的方法,与类似servlet的端点不同,后者接受多部分/表单日期,并在调用方法后重定向客户端 此端点签名如下所示

我有一个Spring引导应用程序,它在嵌入式Tomcat容器中作为可执行JAR运行。该应用程序公开了各种传统的RESTful服务。除了传统的RESTful服务之外,我还需要创建一个更类似于传统servlet的端点

我将传统的RESTful服务定义为使用标准HTTP方法(GET、POST、PUT等)并接受JSON或XML请求体(使用适用方法时)并返回JSON或XML的端点。我定义了传统的方法,与类似servlet的端点不同,后者接受多部分/表单日期,并在调用方法后重定向客户端

此端点签名如下所示

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;
    }


}
@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方法
  • 提交后,将用户重定向到分配给
    referer
    标题的值的基本url
  • 发送到此端点的表单数据是从我不拥有或不控制的表单发送的(我在下面包含了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>
    
    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;
        }
    
    
    }
    
    @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 );
    }
    
    问题陈述 正如您所看到的,我的端点定义了一个
    @modeldattributeformsubmission
    ,我的submission对象用HTML表单中元素的名称来表示每个getter和setter。但是,print语句显示为null。几天前我发誓这是有效的,现在所有的值都是空的。请给我一些建议

    后脚本#1 为了进一步澄清,当我修改端点签名时,如下所示

    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;
        }
    
    
    }
    
    @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 );
    }
    
    并调用终结点,但第一个名称不会成功打印。我希望这能更好地说明我的问题是关于在对象中封装这些表单数据键/值对的

    后脚本#2 如果我:

  • 从FormSubmission参数中删除
    @ModelAttribute
    ,然后
  • 从FormSubmission内私有成员变量的getter和setter方法中删除
    @ModelAttribute
  • 这更好,但我仍然希望能够通过与Java命名约定一致的变量进行命名,因为我不控制表单,所以没有ModelAttribute就无法进行命名