2013-07-29 5 views
6

Я пытаюсь найти оптимальный подход для простого CRUD-контроллера Spring MVC. Есть много примеров контроллеров CRUD как в Интернете и на этом форуме, но большинство из них страдают от одной из двух проблем:Spring MVC CRUD controller best pactice

  1. После сохранения/или модификации или удаления они показывают сообщение, что сохранить и обновить , но URL-адрес, который они нажимают, по-прежнему имеет «/ update/{id}» или «/ delete/{id}». Это «неправильно», потому что показанный контент обычно представляет собой список объектов.

или

  1. Контроллер перенаправляет на «SHOWALL» вид, но тогда нет сообщения о том, что действие имело место, которое не является дружественным к пользователю.

Есть ли у кого-нибудь пример контроллера crud, который не имеет этих двух проблем?

Спасибо,

Генри

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

} 
+1

насчет вы используете 'ResquestMethod.DELETE' для операций удаления на'/{ID} 'URL и возвращает новое значение ModelMap вместо вызова'/удалить/{ID} 'URL ?? То же самое для обновления, что вы можете использовать 'RequestMethod.PUT' –

+0

Ну, в этих двух случаях вы либо закончите с/{id} в URL-адресе после выполнения метода (и вы можете добавить сообщение к выходу, в котором говорится, что произошло), но вы покажете список объектов, или если вы перенаправите запрос, URL будет правильным (нет/{id} (например,/5), но как насчет сообщения о том, что произошло? –

+0

Поймите. вы используете '@ ModelAttribute' с некоторым списком' Message' на контроллере и обновляете модель? При таком подходе вы сохраняете сообщения на модели. здесь и [пример] (http://krams915.blogspot.com.br/2010 /12/spring-3-mvc-using-modelattribute-in.html). –

ответ

10
  1. Вы должны использовать RESTful дизайн URL, и использовать прочтешь, чтобы получить возможность отправлять СОЗДАТЬ, PUT для обновления и удаления для удаления. Используйте HiddenHttpMethodFilter для пользовательских агентов, которые не PUT или DELETE.

  2. Используйте шаблон Post-Redirect-Get, чтобы избежать повторных POST.

  3. Используйте Flash Attributes, чтобы отображать сообщения о успешной работе/сбое на последующих страницах.

+0

Спасибо, это ответ, который я искал !! –

+0

+1 отличная практика. Кстати, первая ссылка мертва – abiieez