SpringMVC之用注解控制器(一)
在传统的Spring MVC开发方法中,必须在Bean配置文件中为每个控制器类配置实例和请求映射和让每个控制器类去实现或者扩展特定于框架的接口或者基类,不够灵活。
如果Spring MVC可以自动侦测你的控制器类和请求映射,就能减少配置所需要的工作量。
Spring2.5支持一种基于注解的控制器开发方法。
Spring可以通过@Controller注解自动发现你的控制器类以及@RequestMapping注解中的请求映射,这样就为你免去了在Bean配置文件中配置它们的麻烦。此外,如果使用注解,控制器类和处理程序方法在访问上下文资源(例如请求参数、模型属性和会话属性)时也会更加灵活。
常用到的注解
处理程序方法的签名非常灵活。你可以为处理程序方法指定任意的名称,并定义以下任意一种类型作为它的方法参数。在这里,只提到了常见的参数类型。关于有效参数类型的完整列表,请参阅有关配置基于注解的控制器的Spring文档。
常见的参数类型
1.HttpServletRequest、HttpServletResponse或HttpSession。
2.添加了@RequestParam注解的任意类型的请求参数
3.添加了@ModelAttribute注解的任意类型的模型属性
4.任意类型的命令对象,供Spring绑定请求参数
5.Map或者ModelMap,供处理程序方法向模型添加属性
6.Errors或者BindingResult,让处理程序方法访问命令对象的绑定和验证结果
7.SessionStatus,让处理程序方法发出会话处理已经完成的通知
常见的返回值类型
处理程序方法的返回类型可以是ModelAndView、Model、Map、String、void
在创建基于注解的控制器之前,必须构建web应用程序上下文来处理注解。
首先,为了让Spring用@Controller注解自动侦测控制器,必须通过<context:component-scan>元素启用Spring的组件扫描特性。
其次Spring MVC还能够根据@RequestMapping将请求映射到控制器类和处理程序方法。
为了使其生效,必须在web应用程序上下文中注册DefaultAnnotationHandlerMapping实例和AnnotationMethodHandlerAdapter实例。
它们分别处理在类级别和方法级别上的@RequestMapping注解。
必要的Spring MVC配置
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 |
<?xml version= "1.0"
encoding= "UTF-8"
?> <beans xmlns= "http://www.springframework.org/schema/beans" xsi:schemaLocation=" http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd http: //www.springframework.org/schema/mvc/spring-mvc http: //www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http: //www.springframework.org/schema/context http: //www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 自动扫描注解的Controller --> <context:component-scan base- package = "com.wy.controller.annotation"
/> <!-- 处理在类级别上的 @RequestMapping 注解--> <bean class = "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"
/> <!-- 处理方法级别上的 @RequestMapping 注解--> <bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
/> <!-- 视图解析器策略 和 视图解析器 --> <!-- 对JSTL提供良好的支持 --> <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" > <!-- 默认的viewClass,可以不用配置 <property name= "viewClass"
value= "org.springframework.web.servlet.view.InternalResourceView"
/> --> <property name= "prefix"
value= "/WEB-INF/page/"
/> <property name= "suffix"
value= ".jsp"
/> </bean> </beans> |
DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter是默认在Web应用程序上下文中预先注册好的。然而,如果你还显式地注册了其他的处理程序映射或者处理程序适配器,它们就不会自动注册了。在这种情况下,你必须亲自注册它们。
基于注解的控制器类可以是个任意类,不实现特殊接口,也不扩展特殊的基类。你只要用@Controller注解对它进行标注即可。还可以在控制器中定义一个或者多个处理程序方法来处理单个或者多个动作。处理程序方法的签名很灵活,足以接受一系列参数。
@RequestMapping注解可以被应用到类级别或者方法级别上。
Controller层:代码中写了很详细的注释
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 |
package
com.wy.controller.annotation; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import
javax.servlet.http.HttpServletRequest; import
javax.servlet.http.HttpServletResponse; import
org.springframework.beans.propertyeditors.CustomDateEditor; import
org.springframework.stereotype.Controller; import
org.springframework.ui.Model; import
org.springframework.validation.BindingResult; import
org.springframework.validation.FieldError; import
org.springframework.web.bind.ServletRequestDataBinder; import
org.springframework.web.bind.annotation.InitBinder; import
org.springframework.web.bind.annotation.PathVariable; import
org.springframework.web.bind.annotation.RequestMapping; import
org.springframework.web.bind.annotation.RequestMethod; import
org.springframework.web.bind.annotation.RequestParam; import
org.springframework.web.bind.support.WebRequestDataBinder; import
org.springframework.web.servlet.ModelAndView; import
com.wy.pojo.User; /** * @author Administrator * @version 2011-12-3 */ @Controller @RequestMapping ( "userManagerContoller" ) //指定请求路径,相对路径可以不定义 public
class UserManagerContoller { /** * 欢迎 * @return */ /* 1.传统的获取请求的参数方式 */ @RequestMapping ( "/welcome" ) public
ModelAndView welcome(HttpServletRequest request){ ModelAndView mav = new
ModelAndView(); String name = request.getParameter( "name" ); Date today = new
Date(); String date = new
SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" ).format(today); mav.addObject( "today" , date); mav.addObject( "name" , name); mav.setViewName( "welcome" ); return
mav; } /* 2.restful风格获取请求的参数方式 Spring3.0的一个重要变化(将参数放到了请求路径中) * * 注意点: JVM将Java文件编译成Class文件有两种模式 Debug 和Release * 这两种编译方式的区别是: * Debug 包含额外的调试信息,可以完整的保留变量的名称 (Eclipse 使用的是Debug) * Release 把变量名称使用其他的一些符号代替,量名称就不可见啦 (在使用 javac命令) */ @RequestMapping ( "/welcome/{param}/{sex}" ) //前一个“param是防止Release编译下找不到参数名称,因此要指定;要和模板中定义的参数名称一致 //后面一个“param”可以和模板中定义的参数名称不一致,建议还是一致 public
ModelAndView welcome( @PathVariable ( "param" ) String param, @PathVariable ( "sex" ) String xingbie){ ModelAndView mav = new
ModelAndView(); mav.addObject( "name" , param); mav.addObject( "sex" , xingbie); Date today = new
Date(); String date = new
SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" ).format(today); mav.addObject( "today" , date); mav.setViewName( "welcome" ); return
mav; } /** * 3.不同请求方式(get,post),映射不同的方法 * * value 指定请求路径,method 指定请求方式 */ @RequestMapping (value= "/welcome" , method=RequestMethod.GET) public
ModelAndView requestMethodGet(){ ModelAndView mav = new
ModelAndView(); mav.setViewName( "welcome" ); return
mav; } @RequestMapping (value= "/hello" , method=RequestMethod.POST) public
ModelAndView requestMethodPost(){ ModelAndView mav = new
ModelAndView(); mav.setViewName( "hello" ); return
mav; } /** * 4. @RequestParam 使用方法和@PathVariable类似(要注意Debug和Release) * http://localhost:8080/SpringMVC/userManagerContoller/welcomeParam.do?username=wy&password=123&age=23 */ @RequestMapping (value= "/welcomeParam" , method=RequestMethod.GET) public
ModelAndView welcome( @RequestParam ( "username" ) String username, @RequestParam ( "password" ) String password, @RequestParam ( "age" ) int
age) { ModelAndView mav = new
ModelAndView(); User user = new
User(); user.setUsername(username); user.setPassword(password); user.setAge(age); mav.addObject( "user" , user); mav.setViewName( "hello" ); return
mav; } /** * 5.获取表单中的值 * BindingResult 绑定数据过程中产生的错误注入到BindingResult中。 */ @RequestMapping (value= "/welcome" , method=RequestMethod.POST) public
ModelAndView commonCommod(User user, BindingResult result){ ModelAndView mav = new
ModelAndView(); mav.addObject(user); if (result.hasErrors() && result.hasFieldErrors()){ String field = null ; Object fieldValue = null ; Map<String, Object> map = new
HashMap<String, Object>(); List<FieldError> fieldErrors = result.getFieldErrors(); for (FieldError fieldError : fieldErrors){ field = fieldError.getField(); fieldValue = fieldError.getRejectedValue(); map.put(field, fieldValue); } mav.addObject( "map" , map); mav.setViewName( "welcome" ); } else { mav.setViewName( "hello" ); } return
mav; } /** * 属性编辑器 类型转换 * 典型应用: 日期转换 */ @InitBinder public
void initBinder(WebRequestDataBinder binder){ binder.registerCustomEditor(Date. class , new
CustomDateEditor( new
SimpleDateFormat( "yyyy-MM-dd" ), false )); } public
void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws
Exception{ SimpleDateFormat dateFormat = new
SimpleDateFormat( "yyyy-MM-dd" ); dateFormat.setLenient( false ); binder.registerCustomEditor(Date. class , new
CustomDateEditor(dateFormat, true )); } /** * 6.常用的参数 * 使用Session有一个前提就是session必须是可用的 */ // public ModelAndView commonArguments(HttpServletRequest request, HttpServletResponse response, HttpSession session, // @CookieValue AnyType cookieName, @RequestHeader("user-Agent") AnyType name, // @PathVariable AnyType variableName, @RequestParam AnyType paramName){ // ModelAndView mav = new ModelAndView(); // // return mav; // } /** * 7.返回类型 * void 、String、AnyType(任意对象)、Model、ModelAndView * 说明:Model继承了Map,为SpringMVC定制的 */ // void @RequestMapping public
void commonReturnType(HttpServletResponse response){ try
{ PrintWriter out = response.getWriter(); out.println( "向页面中输出的值" ); } catch
(IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @RequestMapping public
void commonReturnType(PrintWriter out){ //其实也是从HttpServletResponse 通过getWriter()得到out out.println( "向页面中输出的值" ); } @RequestMapping ( "/commonReturnType" ) public
void commonReturnType(){ //默认生成隐含的viewName(规则测略:按照请求路径${appName/userManagerContoller/commonReturnType.do // ---> userManagerContoller/commonReturnType} // ---> /WEB-INF/page/userManagerContoller/commonReturnType.jsp // ) } // String /** * ModelAndView中的Model * ModelAndView中的View */ @RequestMapping public
String commonReturnType(Map<Object, Object> model){ //model model.put( "" , "" ); return
"viewName" ; } //AnyType(任意对象) /** * user放到model中,model(key, value) key默认是取Bean的名称将其首字母小写 即user,value即user * 默认生成隐含的viewName * 在页面上可以使用request.getAttribute("user")或者${user.key} ${user.value} * @return */ @RequestMapping public
User commonReturnTypeUser(){ // User user = null ; return
user; } /** * userList放到model中,model(key, value) key默认是框架生成userList,value即user * 默认生成隐含的viewName * 在页面上可以使用request.getAttribute("userList")或者${userList.key} ${userList.value} * @return */ @RequestMapping public
List<User> commonReturnTypeUserList(){ List<User> userList = null ; return
userList; } /** * * 默认生成隐含的viewName * @return */ @RequestMapping public
Model commonReturnTypeModel(){ Model model = null ; return
model; } /** * * @return */ @RequestMapping public
ModelAndView commonReturnTypeModelAndView(){ ModelAndView mav = new
ModelAndView(); mav.addObject( "" , "" ); mav.setViewName( "" ); return
mav; } } |
view层
welcome.jsp
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 |
<%@ page language= "java"
pageEncoding= "UTF-8" %> <% String path = request.getContextPath(); %> <!DOCTYPE html> <html> <head> <title>welcome.html</title> <meta http-equiv= "keywords"
content= "keyword1,keyword2,keyword3" > <meta http-equiv= "description"
content= "this is my page" > <meta http-equiv= "content-type"
content= "text/html; charset=UTF-8" > <!--<link rel= "stylesheet"
type= "text/css"
href= "./styles.css" >--> </head> <body> This is my annotation HTML page. <br/> 今天是: ${today}<br/> 参数是: ${name} ${sex}<br/> <hr/> <c:forEach var= "field"
items= "${map}" > <c: if
test= "${field != null}"
var= "param"
scope= "page" > 您输入的${field.key}不正确! ${field.value}<br/> </c: if > </c:forEach> <form action= "<%=path%>/userManagerContoller/welcome.do"
method= "post" > 用户名: <input type= "text"
id= "username"
name= "username"
value= "wy"
/><br/> 密码 : <input type= "text"
id= "password"
name= "password"
value= "wy"
/><br/> 年龄 : <input type= "text"
id= "age"
name= "age"
value= "23wy"
/><br/> <input type= "submit"
value= "提交"
/> </form> </body> </html> |
值得注意的点:
1、@PathVariable("paramName") @RequestParam("paramName") 建议指定参数名称
原因是VM将Java文件编译成Class文件有两种模式 Debug 和Release
这两种编译方式的区别是:
Debug 包含额外的调试信息,可以完整的保留变量的名称 (Eclipse 使用的是Debug)
Release 把变量名称使用其他的一些符号代替,量名称就不可见啦 (在使用 javac命令)
2、restful风格获取请求的参数方式
3、参数类型转换
注册属性编辑器
4、对于无任何输出的方法
1
2
3
4
5
6
7 |
@RequestMapping ( "/commonReturnType" ) public
void commonReturnType(){ //默认生成隐含的viewName(规则测略:按照请求路径${appName/userManagerContoller/commonReturnType.do // ---> userManagerContoller/commonReturnType} // ---> /WEB-INF/page/userManagerContoller/commonReturnType.jsp // ) } |
原文地址:http://blog.csdn.net/ning109314/article/details/7595403
如需转载请注明出处,尊重他人的劳动成果!