Skip to main content
 首页 » 编程设计

spring-mvc之Spring MVC CRUD Controller 最佳实践

2025年02月15日22落叶

我正在尝试为 Spring MVC 简单 CRUD Controller 找到最佳实践方法。网络上和本论坛上都有很多 CRUD Controller 的示例,但大多数都存在以下两个问题之一:

  • 保存/或更新或删除后,它们会显示保存和更新发生的消息,但它们点击的 URL 上仍然有“/update/{id}”或“/delete/{id}”。这是“错误的”,因为显示的内容通常是对象列表。

  • 或者
  • Controller 重定向到“showAll” View ,但是没有消息表明发生了操作,这对用户不友好。

  • 有没有人有一个没有这两个问题的 crud Controller 的例子?

    谢谢,

    亨利
    @Controller 
    @RequestMapping(value="/role") 
    public class RoleController { 
        private static final Logger log = Logger.getLogger(RoleController.class); 
     
        @Autowired 
        private RoleValidator validator = null; 
        @Autowired 
        private RoleService service = null; 
     
     
        public void setService(RoleService  service) { 
            this.service = service; 
        } 
     
        public void setValidator(RoleValidator validator) { 
            this.validator = validator; 
        } 
     
     
        @RequestMapping(method=RequestMethod.GET) 
        public String showForm(ModelMap model){ 
            List<Role> domainObjectList = service.getRoles(); 
            model.addAttribute("domainObjectList", domainObjectList); 
            return "role"; 
        } 
     
        @RequestMapping(value="/add", method=RequestMethod.GET) 
        public String preAdd(ModelMap model){ 
            Role domainObject = new Role(); 
            model.addAttribute("domainObject", domainObject); 
            addConstrainedFields(model); 
            return "roleEdit"; 
        } 
     
        @RequestMapping(value="/add", method=RequestMethod.POST) 
        public ModelAndView add(@ModelAttribute(value="domainObject") Role domainObject, BindingResult result) { 
            validator.validate(domainObject, result); 
            ModelAndView mv = new ModelAndView("role"); 
            if(result.hasErrors()){ 
                mv = new ModelAndView("roleEdit"); 
                mv.addObject("domainObject", domainObject); 
                return mv; 
            } 
            service.insertRole( domainObject ); 
            mv.addObject("domainObjectList", service.getRoles()); 
            mv.addObject("messageKey","label.form.item.added"); 
            //PROBLEM: the URL will remain "/add", but the content will be one of showing all roles + message that role was added.  
            return mv; 
        } 
     
        @RequestMapping(value="/update/{id}") 
        public String preUpdate(@PathVariable Integer id, ModelMap model) { 
            Role domainObject = service.getRole( id ); 
            model.addAttribute("domainObject", domainObject); 
            return "roleEdit"; 
        } 
     
     
        @RequestMapping(value="/update", method=RequestMethod.POST) 
        public String update(@ModelAttribute(value="domainObject") Role domainObject, ModelMap model, BindingResult result){ 
            validator.validate(domainObject, result); 
            ModelAndView mv = new ModelAndView("role"); 
            if(result.hasErrors()){         
                model.addAttribute("domainObject", domainObject); 
                return "roleEdit"; 
            } 
            service.insertRole(domainObject); 
            model.addAttribute("messageKey","label.form.item.added"); 
            model.addAttribute("domainObjectList", service.getRoles()); 
            //PROBLEM: the message that the object was updated will be lost, but the URL will be /role and we will show all roles. 
            return "redirect:/role"; 
        } 
     
        @RequestMapping(value="/delete/{id}") 
        public String delete(@PathVariable Integer id, ModelMap model) { 
            Role domainObject = service.getRole( id ); 
            if (domainObject == null) { 
                model.addAttribute("messageKey","label.form.item.notfound"); 
                return showForm(model); 
            } 
            service.deleteRole(domainObject); 
            model.addAttribute("messageKey","label.form.item.deleted"); 
            return showForm(model); 
        } 
     
        @RequestMapping(value="/delete", method=RequestMethod.POST) 
        public ModelAndView delete(@ModelAttribute(value="domainObject") Role domainObject, BindingResult result){ 
            validator.validate(domainObject, result); 
            ModelAndView mv = new ModelAndView("role"); 
            if(!result.hasErrors()){ 
                service.deleteRole(domainObject); 
                mv.addObject("messageKey","label.form.item.deleted"); 
                domainObject = new Role(); 
                mv.addObject("domainObject", domainObject); 
            } 
            mv.addObject("domainObjectList", service.getRoles()); 
            return mv; 
        } 
     
    } 
    

    请您参考如下方法:

  • 您应该使用 RESTful URL 设计,使用 get 读取,post 来创建,put 到更新,delete 到删除。使用 HiddenHttpMethodFilter对于不 PUT 或 DELETE 的用户代理。
  • 使用 Post-Redirect-Get避免重新发布的模式。
  • 使用 Flash Attributes在后续页面上显示成功/失败消息。