目录
SpringMvc教程 1
初识springMVC 1
背景 1
常见MVC框架比较 1
基于spring3.2的采用annotation方式搭建springMVC环境 1
springMVC的RequestMapping的基本设置 6
在controller中获取前台传递的参数 8
在controller中获取web元素 9
将controller中数据传递到jsp页面 10
设置跳转方式为重定向或者转发 14
视图解析器的配置和使用 14
controller中方法的返回值类型 15
springMVC的文件上传于下载 18
springMVC和jQuery的Ajax结合 22
SpringMvc教程
作者:DK
初识springMVC
背景
Spring框架提供了构建Web?应用程序的全功能MVC模块。使用Spring可插入的MVC架构,可以选择是使用内置的SpringWeb框架还是Struts这样的Web框架。通过策略接口,Spring框架是高度可配置的,而且包含多种视图技术,例如JavaServerPages(JSP)技术、Velocity、Tiles、iText和POI。SpringMVC框架并不知道使用的视图,所以不会强迫您只使用JSP技术。SpringMVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
运行性能上:
Jsp+servlet>struts1>springmvc>struts2+freemarker>>struts2,ognl,值栈。
开发效率上,基本正好相反。值得强调的是,springmvc开发效率和struts2不相上下。
Struts2的性能低的原因是因为OGNL和值栈造成的。所以,如果你的系统并发量高,可以使用freemaker进行显示,而不是采用OGNL和值栈。这样,在性能上会有相当大得提高。
基于spring3.2的采用annotation方式搭建springMVC环境
上官网下载对应的zip包当然该zip并非最新的。下载地址为:http://repo.spring.io/webapp/home.html?0
解压之后得到目录:打开libs会看到会多jar这里边包括了所有的jar和source和doc。当然我们只是需要使用jar就可以了。
3、创建空的web项目目录结构如下:其中user实体类为:
publicclassUser{
privateStringname;
privateIntegerage;
privateDatebirth;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicUser(Stringname,Integerage,Datebirth){
super();
this.name=name;
this.age=age;
this.birth=birth;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
publicDategetBirth(){
returnbirth;
}
publicvoidsetBirth(Datebirth){
this.birth=birth;
}
publicUser(){
super();
//TODOAuto-generatedconstructorstub
}
publicUser(Stringname){
super();
this.name=name;
}
@Override
publicStringtoString(){
//TODOAuto-generatedmethodstub
return"["+name+"]";
}
}
4、在项目中添加如下jar文件:spring-webmvc-3.2.0.RELEASE.jar
spring-core-3.2.0.RELEASE.jarspring-context-3.2.0.RELEASE.jarspring-beans-3.2.0.RELEASE.jarspring-web-3.2.0.RELEASE.jarcommons-logging.jarspring-expression-3.2.0.RELEASE.jar
其中commons-logging.jar请单独下载。
5、在web.xml中添加过滤器的配置。
example
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring-servlet.xml
1
example
.do
这个org.springframework.web.servlet.DispatcherServle即为springMVC的核心控制器。
其中init-param中配置的是spring的配置文件的文件路径。
6、在WEB-INF下添加spring的配置文件spring-servlet.xml文件内容如下:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-3.0.xsd">
其中schemaLocation和xmlns建议直接拷贝。7、创建UserController如下:@Controller
@RequestMapping("/user.do")
publicclassUserController{
@RequestMapping(params="method=add")
publicStringaddUser(Modelmodel){
model.addAttribute("message","添加了一个用户");
System.out.println("UserController.addUser()");
return"/WEB-INF/jsp/addsuc.jsp";
}
}其中@RequestMapping("/user.do")的配置是指:该controller的请求url为:user.do
@RequestMapping(params="method=add")的注解是指:凡是请求的url为:user.do而带了参数method=add的请求会由方法addUser来处理。
addUser的形参model为后续讲解内容。
return"/WEB-INF/jsp/addsuc.jsp";是告诉spring完成处理之后直接进入该视图。
8、添加对应的页面,测试请求user.do?method=add
springMVC的RequestMapping的基本设置
在类的上面注解RequestMapping("/ex.do")意思为所有的ex.do请求全部进入该类处理。"/user.do").所有的user.do请求都会进入该Controller。
2、在自定义的controller中会调用有@RequestMapping注解字样的方法来处理请求。@Controller
@RequestMapping("/user.do")
publicclassUserController{
@RequestMapping
publicStringaddUser(Modelmodel){
model.addAttribute("message","添加了一个用户");
System.out.println("UserController.addUser()");
return"/WEB-INF/jsp/addsuc.jsp";
}
}3、当然可以编写多个处理请求的方法,而这些方法的调用都是通过@RequestMapping的属性类控制调用的。@RequestMapping属性:
value:指定请求的实际地址,指定的地址可以是URITemplate模式(最终请求的url为类的注解的url+方法注解的url)
value的uri值为以下三类:
A)可以指定为普通的具体值;
@Controller
@RequestMapping("/user")
publicclassUserController{
@RequestMapping(value="/some.do")
publicModelAndViewhandleRequest(HttpServletRequestarg0,
HttpServletResponsearg1)throwsException{
System.out.println("handleRequest");
returnnewModelAndView("/WEB-INF/jsp/addsuc.jsp");
}
}
该注解的是说:请求的url为”user/some.do”就会进入该方法(handleRequest)处理。
url:user/some.do
B)可以指定为含有某变量的一类值(URITemplatePatternswithPathVariables);
@RequestMapping(value="/{userId}/delete.do",method=RequestMethod.GET)
publicStringdelete(@PathVariableStringuserId){
System.out.println("delete:"+userId);
return"/WEB-INF/jsp/addsuc.jsp";
}
这个注解:url中带了参数的数据userIdurl:user/1123/delete.do
使用@PathVariable指定形参接收url中的数据
C)可以指定为含正则表达式的一类值(URITemplatePatternswithRegularExpressions);
@RequestMapping(value="/{userBirth:\\d{4}-\\d{2}-\\d{2}}/update.do")
publicStringupdate(@PathVariableStringuserBirth){
System.out.println("userBirth:"+userBirth);
return"/WEB-INF/jsp/addsuc.jsp";
}
请求的url类似:user/1990-11-11/update.do
使用@PathVariable指定形参接收url中的数据
method:指定请求的method类型,GET、POST、PUT、DELETE等;(也就是说只有制定类型的请求才会进入该方法处理)
consumes:指定处理请求的提交内容类型(Content-Type),例如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
4、当类没有@RequestMapping注解时,则直接参考方法的注解匹配对于的url。
@Controller
publicclassUserController{
@Controller
@RequestMapping("/user.do")
publicvoidmanagerUser(){}
}
在这里url为user.do则直接使用managerUser处理请求。
在controller中获取前台传递的参数
将页面数据传递到controller
用户名:
年龄:
生日:
C
/
1、直接使用形参获取前台传递的参数数据
要注意的是形参的名字必须和页面参数的名字
@parammodel
@paramname
@paramage
@parambirth
@return
/
@RequestMapping(method=RequestMethod.POST)
publicStringaddUser(Modelmodel,Stringname,Integerage,Datebirth){
model.addAttribute("message","添加了一个用户");
System.out.println("name:"+name+"\tage:"+age+"\tbirht:"+birth);
System.out.println("UserController.addUser()");
return"/WEB-INF/jsp/addsuc.jsp";
}
/
2、使用对象接受前台传递的参数,
要注意的是前台传递的参数的名称必须和对象的属性名称一直,如果不一致则可以使用@ModelAttribute("u")Stringuname指定
/
@RequestMapping(method=RequestMethod.POST)
publicStringaddUser(Modelmodel,Useruser){
model.addAttribute("message","添加了一个用户");
System.out.println("name:"+user.getName()+"\tage:"+user.getAge()+"\tbirht:"+user.getBirth());
System.out.println("UserController.addUser()");
return"/WEB-INF/jsp/addsuc.jsp";
}
在controller中获取web元素
当某个方法需要使用web对象时(request,response,session,application)
可以使用如下方式:
除过application其他的对象都可以直接设为方法的形参即可。spring会自动将对应的对象传递给对应的形参。
而application对象可以使用session对象获取。
当然也可以在方法中使用response对象重定向到其他的url这时方法最后return的url则可以视作无效。
同样的也可以使用request对象转发到其他的url。
@RequestMapping(value="/web.do")
publicStringgetWebElement(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionsession)throwsIOException,ServletException{
System.out.println("使用request获取的前台参数:"+request.getParameter("pname"));
request.setAttribute("message","这个是request中的数据");
session.setAttribute("message","这个是session中的数据");
session.getServletContext().setAttribute("message","这个是application中的数据");
//response.sendRedirect("http://www.baidu.com");
//returnnull;
//request.getRequestDispatcher("/WEB-INF/jsp/showData.jsp").forward(request,response);
return"/WEB-INF/jsp/showData.jsp";
}
将controller中数据传递到jsp页面
1、可以在controller中获取request对象,然后将数据设置为request对象的属性,然后使用转发的方式进入jsp即可。
2、将方法的返回值该为ModelAndView在返回时,将数据存储在ModelAndView对象中如:
newModelAndView("/WEB-INF/jsp/showData.jsp","message",message)
其中第一个参数为url,第二个参数为要传递的数据的key,第三个参数为数据对象。
在这里要注意的是数据是默认被存放在request中的。
//使用modelAndView对象将数据传递到前台。
@RequestMapping(value="/mad/showData_1.do")
publicModelAndViewshowData_1(){
Stringmessage="这个是要传递的数据";
//其中第一个参数为url,第二个参数为要传递的数据的key,第三个参数为数据对象。
//在这里要注意的是数据是默认被存放在request中的。
returnnewModelAndView("/WEB-INF/jsp/showData.jsp","message",message);
}
前台页面获取方式:
request:${requestScope.message}
2.1、可以在类的前面添加注解@SessionAttributes({"message","user"})
这个注解可以设置对应的model中参数也会在session中存储一份。该注解中的参数为一个集合,可以写多个,如上面的例子,其中message和user都是存储的数据的key.
@SessionAttributes({"message","user"})//modelAndView中的对应的数据也会在session中存储一份
session:${sessionScope.message}
3、数据modelAndView返回一个集合
该处理方式和上面的处理方式一直,因为modelAndView接受的数据类型是Object的,集合也是一样的处理方式
//使用modelAndView对象将数据传递到前台。
//传递多个参数(不同类型的)
@RequestMapping(value="/mad/showData_2.do")
publicModelAndViewshowData_2(){
System.out.println("showData_2");
Stringmessage="这个是要传递的数据";
Useruser=newUser("张三",12,newDate());
Listus=newArrayList();
us.add(newUser("张三",12,newDate()));
us.add(newUser("张四",13,newDate()));
us.add(newUser("张五",14,newDate()));
ModelAndViewmad=newModelAndView("/WEB-INF/jsp/showData.jsp");
//将数据存入modelMap
mad.addObject("message",message);
mad.addObject(user);//默认为类名的首字母小写
mad.addObject("users",us);
returnmad;
}
request:${requestScope.message}
${u.name}-${u.age}-${u.birth}
4、使用modelAndView传递多个参数。
可以通过ModelAndView的mad.addObject("message",message);方法设置参数。
该方法中第一个参数为数据的key,第二个参数为数据对象。
也可以使用mad.addObject(user);方法
该方法中数据的参数为数据对象,数据的key为该对象的类的类名(其中首字母小写)。
5、使用ModelMap传递多个数据到jsp中。
在方法的参数列表中添加形参ModelMapmap,spring会自动创建ModelMap对象。
然后调用map的put(key,value)或者addAttribute(key,value)将数据放入map中,spring会自动将数据存入request。
//使用modelMap对象将数据传递到前台。
//传递多个参数(不同类型的)
@RequestMapping(value="/mad/showData_3.do")
publicStringshowData_3(ModelMapmap){
System.out.println("showData_3");
Stringmessage="这个是要传递的数据";
Useruser=newUser("张三",12,newDate());
Listus=newArrayList();
us.add(newUser("张三",12,newDate()));
us.add(newUser("张四",13,newDate()));
us.add(newUser("张五",14,newDate()));
//将数据存入modelMap
map.put("message",message);
map.addAttribute("user",user);
map.put("users",us);
return"/WEB-INF/jsp/showData.jsp";
}
页面调用:
request:${requestScope.message}
session:${sessionScope.message}
application:${applicationScope.message}
ModelMap中的数据
${requestScope.message}
${requestScope.user.name}
列表
${u.name}-${u.age}-${u.birth}
设置跳转方式为重定向或者转发
1、spring默认的跳转方式即为转发,当然转发也可以写作:return"forward:/WEB-INF/jsp/showData.jsp";
2、重定向必须写作:return"redirect:http://www.baidu.com";
视图解析器的配置和使用
1、在spring-servlet.xml中配置视图解析器
配置该解析器之后,那么controller中的返回的视图url就可以改写了。
return"showData";实际跳转的url为:/WEB-INF/jsp/showData.jsp
controller中方法的返回值类型
springMvc中controller中方法的返回值除了可以返回String和ModelAndView两种类型外还有其他类型。
在这里上面用过的两种类型不再赘述。
其他类型还包括:void、ModelMap、Map、Object、map、List、Set。一般建议使用String。
1、void返回值类型为void则只是纯粹的执行了方法中的程序,然后响应的url依然为请求的url
例如案例中请求为index.do则响应的url为index在视图解析器解析之后得到的最终的url为/WEB-INF/jsp/index.jsp
//返回值为vood
@RequestMapping(value="/index.do",params="type=void")
publicvoidresultVoid(HttpServletRequestrequest){
request.setAttribute("void","resultVoid");
}
2、ModelMap返回值为modelMap时,响应的url和void一致。
只是存储在MpdelMap中的数据可以在jsp页面中取出。
//返回值为ModelMap
@RequestMapping(value="index.do",params="type=modelMap")
publicModelMapresultModelMap(ModelMapmap){
map.put("msg","这里是modleMap中的数据");
returnmap;
}
3、Map和modelMap几乎完全一直。
//返回值为Map
@RequestMapping(value="index.do",params="type=map")
publicMapresultMap(){
Mapmap=newHashMap();
map.put("msg","这里是Map中的数据");
returnmap;
}
4、List返回list是响应的url和void一致。
只是spring会将list对象存储在request中,而该对象的存储的key为:当list中存储为String类型数据时key为:stringList,当存储为User对象时key为:userList。其他的类型的可以类比。//返回值为List
@RequestMapping(value="index.do",params="type=list_string")
publicListresultList_String(){
Listls=newArrayList();
ls.add("list1");ls.add("list2");ls.add("list3");
returnls;
}//返回值为List
@RequestMapping(value="index.do",params="type=list_user")
publicListresultList_User(){
Listls=newArrayList();
ls.add(newUser("张三"));
ls.add(newUser("张四"));
returnls;
}
5、Set返回Set类型的数据时和List除了没有顺序之外,其他都一直。//返回值为Set
@RequestMapping(value="index.do",params="type=set_user")
publicSetresultSet_User(){
Setls=newHashSet();
ls.add(newUser("张三"));
ls.add(newUser("张四"));
returnls;
}
6、Object返回object时,响应的url和以上一直,spirng也会将返回的对象存储在request中,该对象在request中的key为该对象类型的类名(首字母小写)
//返回值为User
@RequestMapping(value="index.do",params="type=user")
publicUserresultUser(){
returnnewUser("张四");
}
返回值类型
Void
无返回值类型
${requestScope.void}
ModelMap
返回ModelMap
${requestScope.msg}
Map
返回map
${requestScope.msg}
List
返回List<String>
${requestScope.stringList}
List
返回List<User>
${requestScope.userList}
Set
返回Set<User>
${requestScope.userSet}
User(Object)
返回User(Object)
${requestScope.user}
springMVC的文件上传于下载
1、springmvc文件的上传也是借助于两个工具所以需要添加两个jar
apache-commons-fileupload.jar
apache-commons-io.jar
2、在spring-servlet.xml中添加文件上传的处理bean的配置。 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
其中属性
的配置配置的是临时文件目录,spring会将文件先传到临时文件,然后我们再调用对应的API将临时文件写到目标文件。
3、编写上传文件的controller
3.1上传一个文件
直接在处理的方法中设置形参@RequestParam("file")CommonsMultipartFilefile
注意这里的参数必须使用@RequestParam指定。
然后调用方法file.getFileItem().write(targetFile);将临时文件写出到目标文件。
/
上传一个文件
@paramname
@paramfile
@paramsession
@return
/
@RequestMapping(value="/upload.do",method=RequestMethod.POST)
publicStringfileUpLoad(Stringname,@RequestParam("file")CommonsMultipartFilefile,HttpSessionsession){
if(!file.isEmpty()){
Stringpath=session.getServletContext().getRealPath("/upload/");
StringfileName=file.getOriginalFilename();
StringfileType=fileName.substring(fileName.lastIndexOf("."));
FiletargetFile=newFile(path,newDate().getTime()+fileType);
try{
file.getFileItem().write(targetFile);
}catch(Exceptione){
e.printStackTrace();
}
}
return"showData";
}
3.2上传多个文件
上传多个文件时,其实和上传一个文件一样,只是将形参改为@RequestParam("file")CommonsMultipartFile[]file
然后我们只需在方法中循环处理这些文件即可。
示例:
/
上传多个文件
@paramname
@paramfiles
@paramsession
@return
/
@RequestMapping(value="/mupload.do",method=RequestMethod.POST)
publicStringmuFileUpLoad(Stringname,@RequestParam("file")CommonsMultipartFile[]files,HttpSessionsession){
if(files!=null&&files.length>0){
Stringpath=session.getServletContext().getRealPath("/upload/");
for(CommonsMultipartFilefile:files){
StringfileName=file.getOriginalFilename();
StringfileType=fileName.substring(fileName.lastIndexOf("."));
FiletargetFile=newFile(path,newDate().getTime()+fileType);
try{
file.getFileItem().write(targetFile);
}catch(Exceptione){
e.printStackTrace();
}
}
}
return"showData";
}
4、文件下载
文件下载其实和spring没关系,还是使用最普通的方式实现下载即可,在这里不赘述。
示例:
/
文件下载
@paramsession
@paramresponse
@paramfileName
@paramisOnline
@throwsException
/
@RequestMapping(value="/downLoad.do",method=RequestMethod.GET)
publicvoiddownLoad(HttpSessionsession,HttpServletResponseresponse,StringfileName,booleanisOnline)throwsException{
Stringpath=session.getServletContext().getRealPath("/upload/")+"\\"+fileName;
Filefile=newFile(path);
System.out.println(path);
if(!file.exists()){
response.sendError(404,"您要下载的文件没找到");
return;
}
BufferedInputStreambufIn=newBufferedInputStream(newFileInputStream(file));
byte[]buff=newbyte[1024];
intlen=-1;
response.reset();
if(isOnline){
URLu=newURL("file:///"+path);
response.setContentType(u.openConnection().getContentType());
response.setHeader("Content-Disposition","inline;filename="+fileName);
}else{
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
}
OutputStreamout=response.getOutputStream();
while((len=bufIn.read(buff))!=-1){
out.write(buff,0,len);
out.flush();
}
bufIn.close();
out.close();
}
springMVC和jQuery的Ajax结合
1、使用@RequestBody接收前台传递的json集合数据。
首先:从spring3.1开始只要配置了就不用再配置其他转换器了。
然后添加json的几个jar:jackson-annotations-2.4.0.jar,jackson-core-2.4.1.jar,jackson-databind-2.4.1.jar
这些jar建议从官网上下载最新的(http://wiki.fasterxml.com/JacksonDownload)
在这里要注意的是,如果jackson的jar如果和spring的版本不匹配,可能会出现响应状态码415.如果出现415响应状态吗,不能解决可以联系此文档的主人qq:2780004063或者发送邮件。
@RequestBody将HTTP请求正文转换为适合的HttpMessageConverter对象。
1.1
在前台js中创建JSON字符串。如[{name:''11'',age:12},{name:''222'',age:15}],
然后使用JSON.stringify将该json对象转换为json字符串,因为@RequstBody只接受json字符串。
$("#saveUser").click(function(){
varusers=[{
name:''张三'',
age:18,
birth:''2014-11-11''
},{
name:''王五'',
age:18,
birth:''2014-11-11''
},{
name:''李四'',
age:18,
birth:''2014-11-11''
}];
$.ajax({
type:''POST'',
data:JSON.stringify(users),
contentType:''application/json'',
dataType:''json'',
url:''user/saveJsonUser.do'',
success:function(data){
alert("OK");
},
error:function(e){
alert("error");
}
});
});
1.2
使用Ajax提交数据需要注意的是:contentType:''application/json'',dataType:''json'',
这两个属性必须这样设置。
1.3
Controller中的处理方法的形参需要添加注解@RequestBody而且形参必须是数组或者list。
如:@RequestBodyUser[]users
示例:
/
使用@RequestBody接受前台传递的一组json数据
@paramusers
@return
/
@RequestMapping(value="/saveJsonUser.do",method=RequestMethod.POST)
publicStringsaveJsonUser(@RequestBodyUser[]users){
for(Useruser2:users){
System.out.println(user2);
}
System.out.println(users);
return"saveUser";
}
2、使用@Response返回指定形式的返回值。
在返回值类型钱添加@Response注解之后,spring不会再对返回的url进行解析,而是直接将返回的对象转化成对应的字符串形式放入respons的流中输出到客户端。
2.1如果返回的为字符串,则直接将该字符串输出到客户端。
/
使用@ResponseBody返回普通字符串。
@paramname
@return
/
@RequestMapping(value="/checkName.do")
public@ResponseBodyStringcheckName(Stringname){
name="userNameis:"+name;
returnname;
}
2.2如果是其他形式的对象,则spring会自动将这些对象转换为对应的json形式的字符串,然后将字符串输出到客户端。
/
使用@ResponseBody返回一个对象集合。
@paramname
@return
/
@RequestMapping(value="/getUsers.do")
public@ResponseBodyListgetUsers(){
Listus=newArrayList();
us.add(newUser("张三",12,newDate()));
us.add(newUser("张四",13,newDate()));
us.add(newUser("张五",14,newDate()));
returnus;
}
/
使用@ResponseBody返回一个对象。
@paramname
@return
/
@RequestMapping(value="/getUser.do")
public@ResponseBodyUsergetUser(){
returnnewUser("老黑",45,newDate());
}
还有springMVC和hibern的整合尚未整理,待续。
|
|