我的项目与roo生成CRUD工作正常,但现在我需要更改一些实体的保存方式(例如我有一个“用户”属性,我希望动态设置为用户登录)
目前我只是将save()方法从方面移动到.java并根据需要进行修改。到目前为止它运行良好,但是roo控制台似乎不喜欢它,因为它在我改变方法返回类型或其他东西时重新创建方面。
我不需要对此示例的具体答案,而是我想知道这是否是修改/覆盖由roo提供的实体的开箱即用的创建/显示功能的最佳方法
修改:添加了示例
我的一个实体是“Servicio”,它有一些“ServiciosCollectionThymeleafController_Roo_Thymeleaf.aj”,带有“ServiciosCollectionThymeleafController.create”方法。我继续将所有.aj推入“ServiciosCollectionThymeleafController.java”
然后我在create方法中做了一些小改动并保存了它。它工作正常,但当我打开roo控制台时,安慰程序再次生成了推送的aj,只是使用我之前编辑的方法。
方面的原始创建方法:
/**
* TODO Auto-generated method documentation
*
* @param servicio
* @param result
* @param model
* @return ModelAndView
*/
@PostMapping(name = "create")
public ModelAndView ServiciosCollectionThymeleafController.create(@Valid @ModelAttribute Servicio servicio, BindingResult result, Model model) {
if (result.hasErrors()) {
populateForm(model);
return new ModelAndView("/servicios/create");
}
Servicio newServicio = getServicioService().save(servicio);
UriComponents showURI = getItemLink().to(ServiciosItemThymeleafLinkFactory.SHOW).with("servicio", newServicio.getId()).toUri();
return new ModelAndView("redirect:" + showURI.toUriString());
}
同样的方法推入了.java和我的修改:
/**
* TODO Auto-generated method documentation
*
* @param servicio
* @param result
* @param model
* @return ModelAndView
*/
@PostMapping(name = "create")
public ModelAndView create(@Valid @ModelAttribute Servicio servicio, BindingResult result, Model model, Principal principal, Pageable pageable) {
if (result.hasErrors()) {
populateForm(model);
return new ModelAndView("/servicios/create");
}
Prestador current = (Prestador) personaService.findByUsername(principal.getName(), pageable).getContent().get(0);
if (current == null) {
populateForm(model);
return new ModelAndView("/servicios/create");
}
servicio.setPrestador(current);
Servicio newServicio = getServicioService().save(servicio);
return new ModelAndView("redirect:/ver-servicio/" + newServicio.getId());
}
感谢。
答案 0 :(得分:3)
Roo通过查找方法签名(方法名称和参数类型)来检查Java文件中是否已包含方法,因为这是java支持重载方法的方式。
在您的情况下,一旦您更改了 create 方法参数,它就不再是相同的方法签名,这就是Roo再次生成它的原因。
通常,这不是问题,因为您必须更改该方法的客户端以使用新方法。例如,如果您向 Service 添加新方法,您还将更改 Controller 的实现以使用该新方法,而Roo生成的方法将不会影响你。
在控制器方法的情况下,问题与映射有关。在您的情况下,您最终会得到两个方法,一个由您添加,另一个由Roo生成,具有相同的请求映射。要解决这个问题,你只需添加Roo生成的方法而不需要映射注释。
在您的情况下,代码将是以下代码:
public ModelAndView create(@Valid @ModelAttribute Servicio servicio, BindingResult result, Model model) {
throw new UnsupportedOperationException();
}
@PostMapping(name = "create")
public ModelAndView create(@Valid @ModelAttribute Servicio servicio, BindingResult result, Model model, Principal principal, Pageable pageable) {
if (result.hasErrors()) {
populateForm(model);
return new ModelAndView("/servicios/create");
}
Prestador current = (Prestador) personaService.findByUsername(principal.getName(), pageable).getContent().get(0);
if (current == null) {
populateForm(model);
return new ModelAndView("/servicios/create");
}
servicio.setPrestador(current);
Servicio newServicio = getServicioService().save(servicio);
return new ModelAndView("redirect:/ver-servicio/" + newServicio.getId());
}
由于您拥有带默认签名的 create 方法,因此Roo不会重新生成它。此外,它没有 PostMapping 注释,因此Spring MVC将忽略它,它将使用新签名调用 create 方法。
附加说明:
此外,您还必须更改生成方法的链接的方式。 Roo生成的所有Thymeleaf控制器都有一个伴随类(以 LinkFactory 结尾),用于生成指向该控制器方法的链接,避免在Thymeleaf页面中使用硬编码的URI以及Controller重定向。那些 LinkFactory 类是使用Spring's MvcUriComponentsBuilder.fromMethodCall utility生成的,{{3}}使用伪方法调用来生成指向该Controller方法的链接。
由于您有新的方法签名,您必须更改 ServiciosCollectionThymeleafController toUri 方法的默认实现。将 toUri 方法插入Java文件,并将实现更改为类似的内容。
public UriComponents toUri(String methodName, Object[] parameters, Map<String, Object> pathVariables) {
...
if (methodName.equals(CREATE)) {
return SpringletsMvcUriComponentsBuilder.fromMethodCall(SpringletsMvcUriComponentsBuilder.on(getControllerClass()).create(null, null, null, null, null)).buildAndExpand(pathVariables);
}
...
}
注意我已经为 create 方法调用添加了两个额外的空参数,使用新方法签名。通过此更改,从Thymeleaf页面生成的所有URI都将指向新方法。