[英]Spring-MVC @ModelAttribute and @Autowired
我正在尝试使用方法上的@ModelAttribute Annontation初始化对象。 当调用URL“ / p / PPP / scope”时,会发生奇怪的事情。 调用@ModelAttribute方法时,似乎未实例化ProjectService,但是调用show()方法时,ProjectService在那里。 有谁知道这有什么问题吗?
以下是日志语句:
12:32:19 [DEBUG] ScopeController - getProject() - loading project for 'PPP'
12:32:19 [DEBUG] ScopeController - getProject() - projectService initialized? null
12:32:21 [DEBUG] ScopeController - show() - projectService initialized? ...project.ProjectService@20f2442e
以及来源:
@Controller
@RequestMapping("/p/{abbr}/scope")
@SessionAttributes("project")
public class ScopeController {
public static final String SHOW_PROJECT_PAGE = "/projects/scope/show";
private static final Logger log = LoggerFactory.getLogger(ScopeController.class);
@Autowired
private ProjectService projectService;
@ModelAttribute("project")
private Project getProject(@PathVariable(value = "abbr") String abbr) {
log.debug("getProject() - loading project for '{}'", abbr);
log.debug("getProject() - projectService initialized? {}", projectService);
// should call this method:
// return projectService.find(abbr);
return new Project();
}
@RequestMapping(method = RequestMethod.GET)
@Transactional
public String show() throws BindException {
log.debug("show() - projectService initialized? {}", projectService);
return SHOW_PROJECT_PAGE;
}
}
具有ModelAttibute批注的所有方法必须是公共的。
因此,当方法getProject为公共方法时,它将可以正常工作:
@ModelAttribute("project")
public Project getProject( ...
也许尝试一些事情。
因此,它看起来像:
@Controller
@RequestMapping("/p/{abbr}/scope")
@SessionAttributes("project")
public class ScopeController {
public static final String SHOW_PROJECT_PAGE = "/projects/scope/show";
private static final Logger log = LoggerFactory.getLogger(ScopeController.class);
@Autowired
private ProjectService projectService;
@RequestMapping(value = "/<yourUri for getProject>", method = RequestMethod.GET)
public @ResponseBody Project get(@PathVariable(value = "abbr") String abbr) {
return getProject(abbr);
}
private Project getProject(String abbr) {
log.debug("getProject() - loading project for '{}'", abbr);
log.debug("getProject() - projectService initialized? {}", projectService);
// should call this method:
// return projectService.find(abbr);
return new Project();
}
@RequestMapping(method = RequestMethod.GET)
@Transactional
public String show() throws BindException {
log.debug("show() - projectService initialized? {}", projectService);
return SHOW_PROJECT_PAGE;
}
}
//In your Project class
@ModelAttribute("project")
public class Project {
//your class stuff
}
一方面,我将@Transactional
批注放在存储库/数据访问层中,因为这是基于Spring MVC批注的分层应用程序的规范。 另外,您的@PathVariable
批注用于检索在控制器的基本URI之后在URI中传递的值。 因此,在不拦截URI模式的私有帮助器方法中使用此注释几乎没有任何意义。
因此,在玩耍之后,我找到了解决方案。 问题是@ModelAttribute中的名称。 删除“项目”后,该方法将按预期方式工作。 由于对“ getProject()”方法的困惑,我做了一些重构以使该方法的意图更加清楚。 这是带有附加注释的完整课程:
@Controller
@RequestMapping("/p/{abbr}/scope")
public class ScopeController {
private static final String SHOW_PROJECT_PAGE = "/projects/scope/show";
private static final Logger log = LoggerFactory.getLogger(ScopeController.class);
@Autowired
private ProjectService projectService;
// method is called before show() and update()
@ModelAttribute
private void initProject(@PathVariable(value = "abbr") String abbr, Model model) {
log.debug("loading project for '{}'", abbr);
// load the project JPA entity from the database, will be merged with the
// updated form values in the POST request. By doing this, I can asure
// that the primary key (the ID) and the related objects are present as
// needed for the em.saveOrUpdate() in the projectService.save() method.
model.addAttribute("project", projectService.find(abbr));
}
@RequestMapping(method = RequestMethod.GET)
public String show() throws BindException {
// shows the project scope form with the project
// added in 'initProject()'
return SHOW_PROJECT_PAGE;
}
@RequestMapping(method = RequestMethod.POST)
public String update(
// the project with the updated form values and the JPA ID and JPA
// relations as loaded in the initProject()
@Valid @ModelAttribute Project project, BindingResult result,
RedirectAttributes redirectAttrs)
throws MethodArgumentNotValidException {
redirectAttrs.addFlashAttribute(project);
try {
if (!result.hasErrors()) {
projectService.save(project);
}
}
catch (Exception e) {
log.error(e.toString());
throw new MethodArgumentNotValidException(null, result);
}
log.debug("project '{}' updated", project.getAbbreviation());
return SHOW_PROJECT_PAGE;
}
}
谢谢大家的回答。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.