服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - spring mvc中注解@ModelAttribute的妙用分享

spring mvc中注解@ModelAttribute的妙用分享

2020-12-31 15:49雨中漫步,惟情而已 Java教程

这篇文章主要给大家介绍了关于spring mvc中注解@ModelAttribute妙用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Android具有一定的参考学习价值,需要的朋友们下面来一起看看吧。

前言

本文主要给大家介绍了关于spring mvc注解@ModelAttribute妙用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

在Spring mvc中,注解@ModelAttribute是一个非常常用的注解,其功能主要在两方面:

  1. 运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用;
  2. 运用在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中;

一般开发中,第一种用法居多,本次我将使用第二种用法以期节省controller层的一些代码:

目前使用spring mvc开发的controller层方法一般类似于:

?
1
2
3
4
@RequestMapping("/{encodeId}/detail")
public String detail(ModelMap model, @PathVariable String encodeId) {
.....
}

几乎在每一个@RequestMapping标注的方法的参数中都会有 ModelMap model的参数,既然这是一个大概率事件,为什么不可以像注入request那样,直接在类的开始使用@Resource进行自动注入呢?

另外一个,就是response,response也不能像request那样进行自动注入。

类似的可能还有很多,既然这些都是controller层常用的代码,如果能将其在一个basecontroller层自动注入,然后controller层继承这个basecontroller,那样就没有必要再@RequestMapping标注的方法中写上这些参数,使得参数个数减少,清晰。

我的思路正是使用@ModelAttribute注解,编写一个basecontroller类,预定义一些项目中controller层常用的对象,如下:

?
1
2
3
4
5
6
@Resource
protected HttpServletRequest request;
 
protected ModelMap model;
 
protected HttpServletResponse response;

request不用解释,可以直接使用@Resource直接注入,response和model的注入方式如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 设置response
 *
 * @param response
 */
 @ModelAttribute
 private final void initResponse(HttpServletResponse response) {
 this.response = response;
 }
 
 /**
 * 设置model
 *
 * @param model
 */
 @ModelAttribute
 private final void initModelMap(ModelMap model) {
 this.model = model;
 }

spring在执行@RequestMapping前会执行上述方法,spring会和平常一样,每次请求重新生成一个model和response,然后注入到方法的参数中,这样就变相在继承了这个basecontroller的controller中自动注入了response和model,在这个controller层中再也不必每次写ModelMap和response参数,整体代码整洁了不少。

我在项目中这样使用暂无问题,如果哪位高手知道这种做法会有弊端或者有更好的方法,求指正!

修正:

非常感谢eBusinessMan的提醒,确实有可能在spring mvc单例模式下会出现访问对象不一致的情况,为了防止该问题,而又能保持这种代码的简洁性以及确保使用spring mvc性能问题不太严重,我决定使用ThreadLocal来处理。

(验证结果:request采用spring的自动注入方式是线程安全的,response、model是不安全的,采用ThreadLocal可以解决该问题)

request对象不再使用注解自动注入(也可以继续使用注解方式注入),而使用同response和model初始化的方式,取消request、response、model三个类变量,具体如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
private static final ThreadLocal<HttpServletRequest> requestContainer = new ThreadLocal<HttpServletRequest>();
 
  private static final ThreadLocal<HttpServletResponse> responseContainer = new ThreadLocal<HttpServletResponse>();
 
  private static final ThreadLocal<ModelMap> modelContainer = new ThreadLocal<ModelMap>();
 
 /**
 * 初始化response
 *
 * @param response
 */
 @ModelAttribute
 private final void initResponse(HttpServletResponse response) {
 responseContainer.set(response);
 }
 
 /**
 * 获取当前线程的response对象
 *
 * @return
 */
 protected final HttpServletResponse getResponse() {
 return responseContainer.get();
 }
 
 /**
 * 初始化request
 *
 * @param request
 */
 @ModelAttribute
 private final void initRequest(HttpServletRequest request) {
 requestContainer.set(request);
 }
 
 /**
 * 获取当前线程的request对象
 *
 * @return
 */
 protected final HttpServletRequest getRequest() {
 return requestContainer.get();
 }
 
 /**
 * 设置model
 *
 * @param model
 */
 @ModelAttribute
 private final void initModelMap(ModelMap model) {
 modelContainer.set(model);
 }
 
 /**
 * 获取当前线程的modelMap对象
 *
 * @return
 */
 protected final ModelMap getModelMap() {
 return modelContainer.get();
 }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:http://www.cnblogs.com/liaochong/p/spring_modelattribute.html

延伸 · 阅读

精彩推荐