Java 在spring中定制表单bean创建过程

Java 在spring中定制表单bean创建过程,java,spring,spring-mvc,spring-form,spring-mvc-initbinders,Java,Spring,Spring Mvc,Spring Form,Spring Mvc Initbinders,我有以下bean: public class TerminalAdmin { @Id @Column(name = "admin_id", nullable = false, unique = true) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id") @SequenceGenerator(name = "user_id", sequenceName = "us

我有以下bean:

public class TerminalAdmin {

    @Id
    @Column(name = "admin_id", nullable = false, unique = true)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id")
    @SequenceGenerator(name = "user_id", sequenceName = "user_id")
    private Long adminId;

    @Column(name = "email", nullable = false)
    private String email;

    @Column(name = "phone")
    @Size(max = 255)
    private String phone;

    @Size(max = 255)
    @Column(name = "name")
    private String name;

    @Column(name = "registration_date")
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar createDate;

    @Column(name = "password", nullable = false)
    @Size(min=1, max = 255, message = "введите пароль длиной от 1 до 255 символов")
    private String password;

    @ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinTable(name = "admin_role", joinColumns = { 
            @JoinColumn(name = "admin_id", nullable = false) }, 
            inverseJoinColumns = { @JoinColumn(name = "role_id", 
                    nullable = false) })
    private Set<AdminRole> adminRoles;

    @Column(name = "blocked")
    private boolean blocked;
    ...
}
内部控制器:

@RequestMapping(value = "/admin/addNewAdmin")
public String adminUsers(@Valid TerminalAdmin terminalAdmin,
            BindingResult bindingResult, ModelMap model, Principal principal, HttpSession session) {
我从客户端发送以下请求:

terminalAdmin得出的方法如下所示

  • 为什么spring会将值写入
    role
    字段
  • 如何强制弹簧将
    250
    /
    251
    写入id字段
  • 附笔。 我试着写作

    InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(AdminRole.class, new PropertyEditorSupport() {
            public void setAsText(String name) {
                ....
            }
        });
    }
    

    但是
    setAsText
    方法不会调用。

    将模型对象填充到表单中不是一个好的做法,因为如果init绑定器配置不正确,Spring可以将字段绑定到对象,即使它们没有填充到视图中

    最简单的方法是创建DTO对象,例如,您可以创建填充到视图中的AdminTerminalTo或AdminTerminalForm

    表单可以包含与AdminTerminal相同的字段,不包括ID字段或任何其他敏感字段。您不能从视图中插入新ID,因为它可能导致DB完整性错误

    成功验证后,只需持久化模型对象,并用DTO/Form对象填充它

    此外,您的JSR-303注释似乎没有以正确的方式使用

    @Size注释不适合作为检查字符串长度的验证。您必须使用@Length。您可以使用@Size检查数组的长度@大小也适用于字符串,但@Length更精确

  • 您不能只发送一个整数,然后尝试绑定到您的集合(正如您现在看到的,spring会执行一些奇怪的绑定)。相反,您已经在控制器中完成了addNewAdmin方法,它已经通知您添加了一个管理员用户
  • 在此方法中,您必须在服务器端分配管理员角色。首先,您可以使用DTO,它将包含用户名、密码和其他字段。您可以使用正确的JSR-303注释对它们进行注释。使用bindingResult检查是否存在任何验证错误。若表单验证良好,只需将DTO/表单对象转换为模型对象。然后可以添加管理员角色并持久化模型对象 如果这些提示还不够,我可以编写一些示例代码

    编辑:

    公共类终端管理器{
    私有字符串用户名;
    @长度(最大值=255)
    公共字符串getUsername(){
    返回用户名;
    }
    public void setUsername(字符串用户名){
    this.username=用户名;
    }
    公共终端管理员convertToTerminalAdmin(){
    TerminalAdmin TerminalAdmin=新的TerminalAdmin();
    terminalAdmin.setUsername(this.username);
    返回终端管理员;
    }
    }
    @实体
    @桌子
    公共类终端管理员{
    @身份证
    @列(name=“admin\u id”,null=false,unique=true)
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“用户id”)
    @SequenceGenerator(name=“user\u id”,sequenceName=“user\u id”)
    私有长管理员ID;
    @列(name=“email”,nullable=false)
    私人字符串电子邮件;
    @列(name=“phone”)
    @尺寸(最大值=255)
    私人电话;
    @尺寸(最大值=255)
    @列(name=“name”)
    私有字符串名称;
    @列(name=“注册日期”)
    @时态(TemporalType.TIMESTAMP)
    私人日历创建日期;
    @列(name=“password”,null=false)
    @尺寸(最小值为1,最大值为255,信息为“(最小值为255”)
    私有字符串密码;
    @ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinTable(name=“admin_role”,joinColumns={
    @JoinColumn(name=“admin\u id”,nullable=false)},
    inverseJoinColumns={@JoinColumn(name=“role\u id”,
    nullable=false)})
    私人设置管理员角色;
    @列(name=“blocked”)
    私有布尔阻塞;
    ...
    }
    @请求映射(value=“/admin/addNewAdmin”)
    公共字符串adminUsers(@Valid TerminalAdminDTO TerminalAdminDTO,
    BindingResult BindingResult,ModelMap模型,主体,HttpSession会话){
    if(result.hasErrors()){
    返回“errorPage”;
    }否则{
    createAdminUser(terminalAdminDTO);
    返回“successPage”;
    }
    }
    @服务
    @交易的
    公共类UserServiceImpl实现UserService{
    私有最终内部管理角色ID=0;
    @自动连线
    实体管理器实体管理器;
    public void createAdminUser(TerminalAdminTo TerminalAdminTo){
    TerminalAdmin TerminalAdmin=TerminalAdminTo.convertToTerminalAdmin();
    AdminRole AdminRole=entityManager.find(AdminRole.class,ADMIN\u ROLE\u ID);
    terminalAdmin.getAdminRoles().add(adminRole);
    entityManager.create(terminalAdmin);
    }
    }
    

    我将其作为一个示例来编写,这不是现成的代码

    请提供示例“您不能从视图中插入新ID,因为它可能导致数据库完整性错误”-这就是我们有限制的原因。但更重要的是:OP的案例中不会插入ID
    @Length
    不是标准注释。如果不使用Hibernate验证器,您甚至无法使用它。“你不能只发送一个整数,然后尝试绑定到你的集合”-是的,你可以,如果你知道怎么做的话。“您必须在服务器端分配管理员角色”-绑定发生在服务器端,不是吗?如果不使用Hibernate验证程序,您甚至无法使用它。“您不能只发送一个整数,然后尝试绑定到您的集合”-是的,您可以,如果您知道如何按照此建议执行-如果您知道如何执行,一切都可以完成,这样发送整数可能会导致严重的安全泄漏,您可以通过这种方式添加任何角色,而无需进行适当的验证“您必须在服务器端分配管理员角色”-绑定发生在服务器端,不是吗?是吗?它绑定了所有东西,而不是关于约束的管理员角色。为什么你还要尝试约束新对象id呢?如果你不按名称引用我,我不会得到通知,也不会
    InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(AdminRole.class, new PropertyEditorSupport() {
            public void setAsText(String name) {
                ....
            }
        });
    }
    
    public class TerminalAdminDTO {
    
        private String username;
    
        @Length(max = 255)
        public String getUsername(){
            return username;
        }
    
        public void setUsername(String username){
            this.username = username;
        }
    
        public TerminalAdmin convertToTerminalAdmin(){
            TerminalAdmin terminalAdmin = new TerminalAdmin();
            terminalAdmin.setUsername(this.username);
            return terminAdmin;
        }
    
    }
    
    
    @Entity
    @Table
    public class TerminalAdmin {
    
        @Id
        @Column(name = "admin_id", nullable = false, unique = true)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id")
        @SequenceGenerator(name = "user_id", sequenceName = "user_id")
        private Long adminId;
    
        @Column(name = "email", nullable = false)
        private String email;
    
        @Column(name = "phone")
        @Size(max = 255)
        private String phone;
    
        @Size(max = 255)
        @Column(name = "name")
        private String name;
    
        @Column(name = "registration_date")
        @Temporal(TemporalType.TIMESTAMP)
        private Calendar createDate;
    
        @Column(name = "password", nullable = false)
        @Size(min=1, max = 255, message = "введите пароль длиной от 1 до 255 символов")
        private String password;
    
        @ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
        @JoinTable(name = "admin_role", joinColumns = { 
                @JoinColumn(name = "admin_id", nullable = false) }, 
                inverseJoinColumns = { @JoinColumn(name = "role_id", 
                        nullable = false) })
        private Set<AdminRole> adminRoles;
    
        @Column(name = "blocked")
        private boolean blocked;
        ...
    }
    
    
    @RequestMapping(value = "/admin/addNewAdmin")
    public String adminUsers(@Valid TerminalAdminDTO terminalAdminDTO,
                BindingResult bindingResult, ModelMap model, Principal principal, HttpSession session) {
                        if(result.hasErrors()){
                            return "errorPage";
                        }else{
                            userService.createAdminUser(terminalAdminDTO);
                            return "successPage";
                        }
                }
    
    
    @Service
    @Transactional
    public class UserServiceImpl implements UserService {
    
        private final int ADMIN_ROLE_ID = 0;
    
        @Autowired
        EntityManager entityManager;
    
        public void createAdminUser(TerminalAdminDTO terminalAdminDTO){
            TerminalAdmin terminalAdmin = terminalAdminDTO.convertToTerminalAdmin();
            AdminRole adminRole = entityManager.find(AdminRole.class,ADMIN_ROLE_ID);
            terminalAdmin.getAdminRoles().add(adminRole);
            entityManager.create(terminalAdmin);
        }
    
    }