前言
Spring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等。但他们的基础都是Spring的ioc和aop。ioc提供了依赖注入的容器,aop解决了面向横切面的编程;然后在此二者的基础上实现了其他延伸产品的高级功能。
Spring MVC是基于 Servlet 的一个 MVC 框架,主要解决 WEB 开发的问题。
后来因为 Spring 的配置非常复杂,各种XML、 JavaConfig处理起来比较繁琐。于是为了方便开发者使用,从而又推出了Spring BOOT,简化了Spring的配置流程。
说得更简便一些:Spring 最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个MVC框架(一些用Spring解耦的组件),用来开发web应用,最终形成了SpringMVC。然后有发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring BOOT。
什么是Spring?它解决了什么问题?
Spring,一般指代的是Spring Framework,它是一个开源的应用程序框架,提供了一个简易的开发方式,通过这种开发方式,将避免那些可能致使代码变得繁杂混乱的大量的业务/工具对象,说的更通俗一点就是由框架来帮你管理这些对象,包括它的创建,销毁等,比如基于Spring的项目里经常能看到的Bean
,它代表的就是由Spring管辖的对象。
而在被管理对象与业务逻辑之间,Spring通过IOC(控制反转)架起使用的桥梁,IOC也可以看做Spring最核心最重要的思想,通过IOC能带来什么好处呢?首先来看一个实际开发中的典型应用场景,假设我们有一个基于MVC分层结构的应用,通过controller层对外提供接口,而通过service层提供具体的实现,在service层中有一个WelcomeService
服务接口,一般情况下都是通过WelcomeService service = new WelcomeServiceImpl();
创建实例并进行调用:
public class WelcomeController {
private WelcomeService service = new WelcomeServiceImpl();
@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}
调用后发现一切正常,此时,功能提交,需要进行测试,而由于实际应用环境与测试环境有所区别,需要替换WelcomeServiceImpl
为一个MockWelcomeServiceImpl
,以方便测试,怎么办?没有其他办法,只有改代码:
public class WelcomeController {
private WelcomeService service = new MockWelcomeServiceImpl();
...
}
测试OK后再将代码改回去,这种方式太过于繁琐,且对代码的侵入性很强;
下面看通过Spring的IOC如何实现,首先将WelcomeService
交由Spring管理:
然后在业务代码处通过Spring IOC拿到具体对象:
public class WelcomeController {
@Autowired
private WelcomeService service;
@RequestMapping("/welcome")
public String welcome() {
return service.retrieveWelcomeMessage();
}
}
测试的时候,只需要更改配置文件,将WelcomeService对应的实现改为MockWelcomeServiceImpl即可:
这种方式对业务代码没有任何侵入,它有效的实现松耦合,大家都知道紧耦合的代码是业务发展的噩梦;同时,Spring IOC提供的远不止这些,如通过单例减少创建无用的对象,通过延迟加载优化初始化成本等
当然,Spring 的核心功能远不知这些,如:
- Spring AOP
- Spring JDBC
- Spring MVC
- Spring ORM
- Spring JMS
- Spring Test
其实不通过Spring框架依然可以实现这些功能特定,但是Spring 提供了更优雅的抽象接口以方便对这些功能的组装,同时又给予每个具体实现以灵活的配置;另外,基于Spring,你可以方便的与其他框架进行集成,如hibernate
,ibatis
等,Spring官方的原则是绝不重复造轮子,有好的解决方案只需要通过Spring进行集成即可。纵览Spring的结构,你会发现Spring Framework 本身并未提供太多具体的功能,它主要专注于让你的项目代码组织更加优雅,使其具有极好的灵活性和扩展性,同时又能通过Spring集成业界优秀的解决方案,想了解Spring的核心实现机制可参考tiny spring 项目
为什么使用Spring ?
- 方便解耦,简化开发
通过Spring提供的IoC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。
- AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,如性能监测、事务管理、日志记录等。
-
声明式事务的支持
-
方便集成各种优秀框架
-
降低Java EE API的使用难度
如对JDBC,JavaMail,远程调用等提供了简便封装
什么是IoC,为什使用IoC ?
IoC全称Iversion of Controller,控制反转。
这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
它能指导我们如何设计出松耦合、更优良的程序。
什么是AOP,为什么使用AOP ?
AOP全称:Aspect-Oriented Programming,面向切面编程。
AOP,面向切面编程,就是把可重用的功能提取出来,然后将这些通用功能在合适的时候织入到应用程序中,比如事务管理、权限控制、日志记录、性能统计等。
AOP并没有帮助我们解决任何新的问题,它只是提供了一种更好的办法,能够用更少的工作量来解决现有的一些问题,使得系统更加健壮,可维护性更好。
什么是Spring的事务管理?
事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。
开发中为了避免这种情况一般都会进行事务管理。
Spring的声明式事务通常是指在配置文件中对事务进行配置声明,其中包括了很多声明属性,它是通过Spring Proxy帮你做代理,自己不用额外的写代码,只要在Spring配置文件中声明即可;通常用在数据库的操作里面;
编程式事务就是指通过硬编码的方式做事务处理,这种处理方式需要写代码,事务中的逻辑可以自己定制;可以是数据库的东东,也可以是其他的操作。
Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。
Spring框架支持以下五种bean的作用域:
singleton : 默认值,bean在每个Spring ioc 容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
什么是Spring的MVC框架?
Spring 配备构建Web 应用的全功能MVC框架。Spring可以很便捷地和其他MVC框架集成,如Struts,Spring 的MVC框架用控制反转把业务对象和控制逻辑清晰地隔离。它也允许以声明的方式把请求参数和业务对象绑定。
spring mvc是一个基于mvc的web框架。spring mvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。
如何启用注解:
如果使用 则上面内容可以省略
Spring MVC的请求流程:
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找Handler可以根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView。ModelAndView是springmvc框架的一个底层对象,包括 Model和view
第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染。视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果
web.xml的配置

注解的处理器映射器和适配器
spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。
使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
spring 与 mybatis整合过程
第一步:整合dao层
mybatis和spring整合,通过spring管理mapper接口。
使用mapper的扫描器自动扫描mapper接口在spring中进行注册。
第二步:整合service层
通过spring管理 service接口。
使用配置方式将service接口配置在spring配置文件中。
实现事务控制。
第三步:整合springmvc
由于springmvc是spring的模块,不需要整合。
主要配置有:
1). mybatis配置文件sqlMapConfig.xml配置别名自动扫描(实体类)
2). mapper扫描器(接口,数据库访问接口)
3). 数据库连接池配置
4). 声明式事务配置
5). 启用注解扫描:
6). 配置注解映射器和适配器:
7). 视图解析器:
8). 配置控制类: DispatcherServlet前端控制器
9). 配置spring配置文件加载类:ClassLoadListener
前端控制器从上边的文件中加载处理映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,使用默认加载的 DispatcherSerlvet.properties。
视图解析器配置前缀和后缀:

sqlMapConfig.xml,mybatis自己的配置文件。

配置数据源:

事务控制(applicationContext-transaction.xml),在applicationContext-transaction.xml中使用spring声明式事务控制方法。

加载spring配置

静态资源访问不被拦截:
@RequestMapping的作用
1). url映射
2). 窄化请求映射
3). 限制http请求方法
controller方法的返回值
**返回ModelAndView **
需要方法结束时,定义ModelAndView,将model和view分别进行设置。
返回string
如果controller方法返回string,
1). 表示返回逻辑视图名。真正视图(jsp路径)=前缀+逻辑视图名+后缀
2). redirect重定向:返回字符串格式为:”redirect:queryItem.action”
3). forward页面转发:返回字符串格式为:“forward:queryItem.action”
返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
1). 使用request转向页面,如下:request.getRequestDispatcher(“页面路径”).forward(request, response);
2). 也可以通过response页面重定向:response.sendRedirect(“url”)
3). 也可以通过response指定响应结果,例如响应json数据如下:
-
response.setCharacterEncoding(“utf-8”);
-
response.setContentType(“application/json;charset=utf-8”);
-
response.getWriter().write(“json串”);
参数绑定:
默认支持的类型
直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。
1). HttpServletRequest:通过request对象获取请求信息
2). HttpServletResponse:通过response处理响应信息
3). HttpSession:通过session对象得到session中存放的对象
4). Model/ModelMap:model是一个接口,modelMap是一个接口实现 。作用:将model数据填充到request域。
简单类型
-
通过@RequestParam对简单类型的参数进行绑定。
-
如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。
-
如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。
-
通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,会报错。
pojo绑定
页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。(usename,age;不需要user.username,user.age)
自定义参数绑定实现日期类型绑定
对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期数据串转成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。
Spring MVC 和 Struts2 对比
1.Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC 就容易实现restful url
2.由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。
3.由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
4.SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
5.springmvc面向方法开发的(更接近service接口的开发方式),struts2面向类开发。
6.springmvc可以单例开发,struts2只能是多例开发。
乱码处理
1). post乱码
在web.xml添加post乱码filter:CharacterEncodingFilter
2). 对于get请求中文参数出现乱码解决方法有两个:
a. 修改tomcat配置文件添加编码与工程编码一致,如下:
b. 对参数进行重新编码:
String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1″),”utf-8”)
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
集合类型绑定
1). 数组绑定:
controller方法参数使用:(Integer[] itemId)
页面统一使用:itemId 作为name
2). list绑定:
pojo属性名为:itemsList
页面:itemsList[index].属性名
3). map 绑定:
pojo属性名为:Map itemInfo = new HashMap();
页面:
spring 校验
1). 项目中,通常使用较多是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。
2). springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。
校验思路:页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
数据回显
1). @ModelAttribute还可以将方法的返回值传到页面:在方法上加注解@ModelAttribute
2). 使用最简单方法使用model,可以不用@ModelAttribute:model.addAttribute(“id”, id);
3). springmvc默认对pojo数据进行回显。pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)
4). public String testParam(PrintWriter out, @RequestParam(“username”) String username) { //out直接输出
异常处理
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。

上传图片
1). 在页面form中提交enctype=”multipart/form-data”的数据时,需要springmvc对multipart类型的数据进行解析。
2). 在springmvc.xml中配置multipart类型解析器。

3). 方法中使用:MultipartFile attach (单个文件上传) 或者 MultipartFile[] attachs (多个文件上传)
Json处理
1). 加载json转换的jar包:springmvc中使用jackson的包进行json转换(@requestBody和@responseBody使用下边的包进行json转)
2). 配置json转换器。在注解适配器RequestMappingHandlerAdapter中加入messageConverters。如果使用 则会自动加入。
3). ajax

4). Controller (ResponseBody、RequestBody)

注意ajax中contentType如果不设置为json类型,则传的参数为key/value类型。上面设置后,传的是json类型。
详见:http://www.cnblogs.com/Jtianlin/p/5224885.html
拦截器:
1). 定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。
a. preHandle :进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
b. postHandle:进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
c. afterCompletion:执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理
2). 拦截器配置:
a. 针对HandlerMapping配置(不推荐):springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。 (一般不推荐使用)
b. 类似全局的拦截器:springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中

如何启用注解:
如果使用 则上面内容可以省略 使用 mvc:annotation-driven代替注解映射器和注解适配器配置
什么是Spring Boot?它解决了什么问题?
初期的Spring通过代码加配置的形式为项目提供了良好的灵活性和扩展性,但随着Spring越来越庞大,其配置文件也越来越繁琐,太多复杂的xml文件也一直是Spring被人诟病的地方,特别是近些年其他简洁的WEB方案层出不穷,如基于Python或Node.Js,几行代码就能实现一个WEB服务器,对比起来,大家渐渐觉得Spring那一套太过繁琐,此时,Spring社区推出了Spring Boot,它的目的在于实现自动配置,降低项目搭建的复杂度,如需要搭建一个接口服务,通过Spring Boot,几行代码即可实现,请看代码示例:
//引入spring-boot-starter-web依赖
org.springframework.bootspring-boot-starter-web
//声明Spring Boot应用,直接写业务逻辑即可
@Controller
@SpringBootApplication
public class MockServerApplication {
@RequestMapping("/hi")
@ResponseBody
String home() {
return "how are you!";
}
public static void main(String[] args) {
SpringApplication.run(MockServerApplication.class, args);
}
}
你甚至都不用额外的WEB容器,直接生成jar包执行即可,因为spring-boot-starter-web
模块中包含有一个内置tomcat,可以直接提供容器使用;基于Spring Boot,不是说原来的配置没有了,而是Spring Boot有一套默认配置,我们可以把它看做比较通用的约定,而Spring Boot遵循的也是约定优于配置原则,同时,如果你需要使用到Spring以往提供的各种复杂但功能强大的配置功能,Spring Boot一样支持
在Spring Boot中,你会发现你引入的所有包都是
starter
形式,如:
- spring-boot-starter-web-services,针对SOAP Web Services
- spring-boot-starter-web,针对Web应用与网络接口
- spring-boot-starter-jdbc,针对JDBC
- spring-boot-starter-data-jpa,基于hibernate的持久层框架
- spring-boot-starter-cache,针对缓存支持
- 等等
Spring Boot对starter的解释如下:

这句话的译意为:

Spring REST如何使用?
准备工作
1、 下载jar包
spring各版本jar下载地址:http://ebr.springsource.com/repository/app/library/detail?name=org.springframework.spring
相关的依赖包也可以在这里找到:http://ebr.springsource.com/repository/app/library
2、 需要jar包如下

3、 当前工程的web.xml配置
dispatcherorg.springframework.web.servlet.DispatcherServletcontextConfigLocation/WEB-INF/dispatcher.xml1dispatcher*.doindex.jsp
4、 WEB-INF中的dispatcher.xml配置
5、 启动后,可以看到index.jsp 没有出现异常或错误。那么当前SpringMVC的配置就成功了。
二、REST控制器实现
REST控制器主要完成CRUD操作,也就是对于http中的post、get、put、delete。
还有其他的操作,如head、options、trace。
具体代码:
package com.hoo.controller;
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;
/**
* function:SpringMVC REST示例
* @author hoojo
* @createDate 2011-6-9 上午11:34:08
* @file RESTController.java
* @package com.hoo.controller
* @project SpringRestWS
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
@RequestMapping("/restful")
@Controller
public class RESTController {
@RequestMapping(value = "/show", method = RequestMethod.GET)
public ModelAndView show() {
System.out.println("show");
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("show method");
return model;
}
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public ModelAndView getUserById(@PathVariable String id) {
System.out.println("getUserById-" + id);
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("getUserById method -" + id);
return model;
}
@RequestMapping(value = "/add", method = RequestMethod.POST)
public ModelAndView addUser(String user) {
System.out.println("addUser-" + user);
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("addUser method -" + user);
return model;
}
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
public ModelAndView editUser(String user) {
System.out.println("editUser-" + user);
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("editUser method -" + user);
return model;
}
@RequestMapping(value = "/remove/{id}", method = RequestMethod.DELETE)
public ModelAndView removeUser(@PathVariable String id) {
System.out.println("removeUser-" + id);
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("removeUser method -" + id);
return model;
}
}
上面的方法对应的http操作:
/show -> get 查询
/get/id -> get 查询
/add -> post 添加
/edit -> put 修改
/remove/id -> delete 删除
在这个方法中,就可以看到RESTful风格的url资源标识
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public ModelAndView getUserById(@PathVariable String id) {
System.out.println("getUserById-" + id);
ModelAndView model = new ModelAndView("xStreamMarshallingView");
model.addObject("getUserById method -" + id);
return model;
}
value=”/get/{id}”就是url中包含get,并且带有id参数的get请求,就会执行这个方法。这个url在请求的时候,会通过Annotation的@PathVariable来将url中的id值设置到getUserById的参数中去。 ModelAndView返回的视图是xStreamMarshallingView是一个xml视图,执行当前请求后,会显示一篇xml文档。文档的内容是添加到model中的值。
三、利用RestTemplate调用REST资源
代码如下:
package com.hoo.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
/**
* function:RestTemplate调用REST资源
* @author hoojo
* @createDate 2011-6-9 上午11:56:16
* @file RESTClient.java
* @package com.hoo.client
* @project SpringRestWS
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
@Component
public class RESTClient {
@Autowired
private RestTemplate template;
private final static String url = "http://localhost:8080/SpringRestWS/restful/";
public String show() {
return template.getForObject(url + "show.do", String.class, new String[]{});
}
public String getUserById(String id) {
return template.getForObject(url + "get/{id}.do", String.class, id);
}
public String addUser(String user) {
return template.postForObject(url + "add.do?user={user}", null, String.class, user);
}
public String editUser(String user) {
template.put(url + "edit.do?user={user}", null, user);
return user;
}
public String removeUser(String id) {
template.delete(url + "/remove/{id}.do", id);
return id;
}
}
- RestTemplate的getForObject完成get请求、postForObject完成post请求、put对应的完成put请求、delete完成delete请求;还有execute可以执行任何请求的方法,需要你设置RequestMethod来指定当前请求类型。
- RestTemplate.getForObject(String url, Class responseType, String… urlVariables)
- 参数url是http请求的地址,参数Class是请求响应返回后的数据的类型,最后一个参数是请求中需要设置的参数。
- template.getForObject(url + “get/{id}.do”, String.class, id);
- 如上面的参数是{id},返回的是一个string类型,设置的参数是id。最后执行该方法会返回一个String类型的结果。
下面建立一个测试类,完成对RESTClient的测试。代码如下:
package com.hoo.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;
/**
* function:RESTClient TEST
* @author hoojo
* @createDate 2011-6-9 下午03:50:21
* @file RESTClientTest.java
* @package com.hoo.client
* @project SpringRestWS
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
@ContextConfiguration("classpath:applicationContext-*.xml")
public class RESTClientTest extends AbstractJUnit38SpringContextTests {
@Autowired
private RESTClient client;
public void testShow() {
System.out.println(client.show());
}
public void testGetUserById() {
System.out.println(client.getUserById("abc"));
}
public void testAddUser() {
System.out.println(client.addUser("jack"));
}
public void testEditUser() {
System.out.println(client.editUser("tom"));
}
public void testRemoveUser() {
System.out.println(client.removeUser("aabb"));
}
}
我们需要在src目录下添加applicationContext-beans.xml完成对restTemplate的配置。restTemplate需要配置MessageConvert将返回的xml文档进行转换,解析成JavaObject。
上面配置了xStreamMarshaller是和RESTController中的ModelAndView的view对应的。因为那边是用xStreamMarshaller进行编组的,所以RestTemplate这边也需要用它来解组。RestTemplate还指出其他的MarshallingHttpMessageConverter
推荐阅读更多精彩内容
-
阿里面试(Java岗):spring全家桶4面,Spring+boot+Cloud+MVC前言 相比于前几年来说,现在的面试难度提升了不少。你说说现在程序员这么多,你投递的公司可能与你一起投递的就有300…java高并发阅读 370评论 0赞 4
-
struts、hibernate、spring、 mybatis、 spring boot 关于1、谈谈你对Struts的理解。 答: 1.struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的…慕容小伟阅读 1,660评论 0赞 13
-
spring/spring-boot90. 为什么要使用 spring? 简介:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器…CgySHFF阅读 79评论 0赞 0
-
如何在Spring Boot应用中优雅的使用Date和LocalDateTimeJava8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作…杨绿寒轻阅读 2,800评论 0赞 14
-
Spring MVC的工作机制简单理解单独写这一篇我其实蛮忐忑的,毕竟我对于框架源码并不敢说完全“理解”,根本没到那种对原理吃透的程度,很大程度上只能算…加班狗老王阅读 84评论 0赞 0
{“dataManager”:”[]”,”props”:{“isServer”:true,”initialState”:{“global”:{“done”:false,”artFromType”:null,”fontType”:”black”,”$modal”:{“ContributeModal”:false,”RewardListModal”:false,”PayModal”:false,”CollectionModal”:false,”LikeListModal”:false,”ReportModal”:false,”QRCodeShareModal”:false,”BookCatalogModal”:false,”RewardModal”:false},”$ua”:{“value”:”Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36″,”isIE11″:false,”earlyIE”:null,”chrome”:”58.0″,”firefox”:null,”safari”:null,”isMac”:false},”$diamondRate”:{“displayable”:false,”rate”:0},”readMode”:”day”,”locale”:”zh-CN”,”seoList”:[{“comments_count”:0,”public_abbr”:”前言 相比于前几年来说,现在的面试难度提升了不少。你说说现在程序员这么多,你投递的公司可能与你一起投递的就有300…”,”share_image_url”:”https://upload-images.jianshu.io/upload_images/15593451-527663ecb1d53725.png”,”slug”:”4b9c50916fe2″,”user”:{“id”:15593451,”nickname”:”java高并发”,”slug”:”e2c8c5808732″,”avatar”:”https://cdn2.jianshu.io/assets/default_avatar/6-fd30f34c8641f6f32f5494df5d6b8f3c.jpg”},”likes_count”:4,”title”:”阿里面试(Java岗):spring全家桶4面,Spring+boot+Cloud+MVC”,”id”:53639311,”views_count”:370},{“comments_count”:0,”public_abbr”:”1、谈谈你对Struts的理解。 答: 1.struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的…”,”share_image_url”:””,”slug”:”a2ec21bf14f6″,”user”:{“id”:8286055,”nickname”:”慕容小伟”,”slug”:”e79074dcce23″,”avatar”:”https://upload.jianshu.io/users/upload_avatars/8286055/6b358ed2-8d45-4649-a41c-d5930355ac34.png”},”likes_count”:13,”title”:”struts、hibernate、spring、 mybatis、 spring boot 关于”,”id”:23494555,”views_count”:1660},{“comments_count”:0,”public_abbr”:”90. 为什么要使用 spring? 简介:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器…”,”share_image_url”:”https://upload-images.jianshu.io/upload_images/20515679-34319db74a3d664f.png”,”slug”:”7a8e4ff148d2″,”user”:{“id”:20515679,”nickname”:”CgySHFF”,”slug”:”e4851418a8c5″,”avatar”:”https://upload.jianshu.io/users/upload_avatars/20515679/da51acc1-bfce-4aa7-9b4d-11ab8339f9d6″},”likes_count”:0,”title”:”spring/spring-boot”,”id”:65813402,”views_count”:79},{“comments_count”:0,”public_abbr”:”Java8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作…”,”share_image_url”:””,”slug”:”ccab14aef228″,”user”:{“id”:12041297,”nickname”:”杨绿寒轻”,”slug”:”60aa1a125369″,”avatar”:”https://cdn2.jianshu.io/assets/default_avatar/2-9636b13945b9ccf345bc98d0d81074eb.jpg”},”likes_count”:14,”title”:”如何在Spring Boot应用中优雅的使用Date和LocalDateTime”,”id”:72691106,”views_count”:2800},{“comments_count”:0,”public_abbr”:”单独写这一篇我其实蛮忐忑的,毕竟我对于框架源码并不敢说完全“理解”,根本没到那种对原理吃透的程度,很大程度上只能算…”,”share_image_url”:”https://upload-images.jianshu.io/upload_images/23378019-a78ece9063d2b8a8.png”,”slug”:”5eae2707f98a”,”user”:{“id”:23378019,”nickname”:”加班狗老王”,”slug”:”f3fb9d927356″,”avatar”:”https://upload.jianshu.io/users/upload_avatars/23378019/c4b2d48b-24e8-4725-a495-e22360724fff”},”likes_count”:0,”title”:”Spring MVC的工作机制简单理解”,”id”:73465246,”views_count”:84}]},”note”:{“data”:{“is_author”:false,”last_updated_at”:1617011068,”public_title”:”Spring、Spring Boot、Spring MVC、Spring REST如何使用”,”purchased”:false,”liked_note”:false,”comments_count”:2,”free_content”:”u003ch2u003e前言u003c/h2u003enu003cpu003eSpring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等。但他们的基础都是Spring的ioc和aop。ioc提供了依赖注入的容器,aop解决了面向横切面的编程;然后在此二者的基础上实现了其他延伸产品的高级功能。u003c/pu003enu003cpu003eSpring MVC是基于 Servlet 的一个 MVC 框架,主要解决 WEB 开发的问题。u003c/pu003enu003cpu003e后来因为 Spring 的配置非常复杂,各种XML、 JavaConfig处理起来比较繁琐。于是为了方便开发者使用,从而又推出了Spring BOOT,简化了Spring的配置流程。u003c/pu003enu003cpu003e说得更简便一些:Spring 最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个MVC框架(一些用Spring解耦的组件),用来开发web应用,最终形成了SpringMVC。然后有发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring BOOT。u003c/pu003enu003ch2u003e什么是Spring?它解决了什么问题?u003c/h2u003enu003cpu003eSpring,一般指代的是Spring Framework,它是一个开源的应用程序框架,提供了一个简易的开发方式,通过这种开发方式,将避免那些可能致使代码变得繁杂混乱的大量的业务/工具对象,说的更通俗一点就是由框架来帮你管理这些对象,包括它的创建,销毁等,比如基于Spring的项目里经常能看到的u003ccodeu003eBeanu003c/codeu003e,它代表的就是由Spring管辖的对象。u003c/pu003enu003cpu003e而在被管理对象与业务逻辑之间,Spring通过IOC(控制反转)架起使用的桥梁,IOC也可以看做Spring最核心最重要的思想,通过IOC能带来什么好处呢?首先来看一个实际开发中的典型应用场景,假设我们有一个基于MVC分层结构的应用,通过controller层对外提供接口,而通过service层提供具体的实现,在service层中有一个u003ccodeu003eWelcomeServiceu003c/codeu003e服务接口,一般情况下都是通过u003ccodeu003eWelcomeService service = new WelcomeServiceImpl();u003c/codeu003e创建实例并进行调用:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epublic class WelcomeController {n private WelcomeService service = new WelcomeServiceImpl();nn @RequestMapping(“/welcome”)n public String welcome() {n return service.retrieveWelcomeMessage();n }n}nu003c/codeu003eu003c/preu003enu003cpu003e调用后发现一切正常,此时,功能提交,需要进行测试,而由于实际应用环境与测试环境有所区别,需要替换u003ccodeu003eWelcomeServiceImplu003c/codeu003e为一个u003ccodeu003eMockWelcomeServiceImplu003c/codeu003e,以方便测试,怎么办?没有其他办法,只有改代码:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epublic class WelcomeController {n private WelcomeService service = new MockWelcomeServiceImpl();nn …n}nu003c/codeu003eu003c/preu003enu003cpu003e测试OK后再将代码改回去,这种方式太过于繁琐,且对代码的侵入性很强;u003cbru003en下面看通过Spring的IOC如何实现,首先将u003ccodeu003eWelcomeServiceu003c/codeu003e交由Spring管理:u003c/pu003enu003cpreu003eu003ccode class=”c”u003eu0026lt;bean name=”WelcomeService” class=”XXX.XXX.XXX.service.impl.WelcomeServiceImpl”/u0026gt;nu003c/codeu003eu003c/preu003enu003cpu003e然后在业务代码处通过Spring IOC拿到具体对象:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epublic class WelcomeController {n @Autowiredn private WelcomeService service;nn @RequestMapping(“/welcome”)n public String welcome() {n return service.retrieveWelcomeMessage();n }n}nu003c/codeu003eu003c/preu003enu003cpu003e测试的时候,只需要更改配置文件,将WelcomeService对应的实现改为MockWelcomeServiceImpl即可:u003c/pu003enu003cpreu003eu003ccode class=”c”u003eu0026lt;bean name=”WelcomeService” class=”XXX.XXX.XXX.service.impl.MockWelcomeServiceImpl”/u0026gt;nu003c/codeu003eu003c/preu003enu003cpu003e这种方式对业务代码没有任何侵入,它有效的实现松耦合,大家都知道紧耦合的代码是业务发展的噩梦;同时,Spring IOC提供的远不止这些,如通过单例减少创建无用的对象,通过延迟加载优化初始化成本等u003c/pu003enu003cpu003e当然,Spring 的核心功能远不知这些,如:u003c/pu003enu003culu003enu003cliu003eSpring AOPu003c/liu003enu003cliu003eSpring JDBCu003c/liu003enu003cliu003eSpring MVCu003c/liu003enu003cliu003eSpring ORMu003c/liu003enu003cliu003eSpring JMSu003c/liu003enu003cliu003eSpring Testu003c/liu003enu003c/ulu003enu003cpu003e其实不通过Spring框架依然可以实现这些功能特定,但是Spring 提供了更优雅的抽象接口以方便对这些功能的组装,同时又给予每个具体实现以灵活的配置;另外,基于Spring,你可以方便的与其他框架进行集成,如u003ccodeu003ehibernateu003c/codeu003e,u003ccodeu003eibatisu003c/codeu003e等,Spring官方的原则是绝不重复造轮子,有好的解决方案只需要通过Spring进行集成即可。u003cstrongu003e纵览Spring的结构,你会发现Spring Framework 本身并未提供太多具体的功能,它主要专注于让你的项目代码组织更加优雅,使其具有极好的灵活性和扩展性,同时又能通过Spring集成业界优秀的解决方案u003c/strongu003e,想了解Spring的核心实现机制可参考u003ca href=”https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fcode4craft%2Ftiny-spring” target=”_blank”u003etiny spring 项目u003c/au003eu003c/pu003enu003ch2u003e为什么使用Spring ?u003c/h2u003enu003colu003enu003cliu003e方便解耦,简化开发u003c/liu003enu003c/olu003enu003cpu003e通过Spring提供的IoC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。u003c/pu003enu003col start=”2″u003enu003cliu003eAOP编程的支持u003c/liu003enu003c/olu003enu003cpu003e通过Spring提供的AOP功能,方便进行面向切面的编程,如性能监测、事务管理、日志记录等。u003c/pu003enu003col start=”3″u003enu003cliu003eu003cpu003e声明式事务的支持u003c/pu003eu003c/liu003enu003cliu003eu003cpu003e方便集成各种优秀框架u003c/pu003eu003c/liu003enu003cliu003eu003cpu003e降低Java EE API的使用难度u003c/pu003eu003c/liu003enu003c/olu003enu003cpu003e如对JDBC,JavaMail,远程调用等提供了简便封装u003c/pu003enu003ch2u003e什么是IoC,为什使用IoC ?u003c/h2u003enu003cpu003eIoC全称Iversion of Controller,控制反转。u003c/pu003enu003cpu003e这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。u003c/pu003enu003cpu003e它能指导我们如何设计出松耦合、更优良的程序。u003c/pu003enu003ch2u003e什么是AOP,为什么使用AOP ?u003c/h2u003enu003cpu003eAOP全称:Aspect-Oriented Programming,面向切面编程。u003c/pu003enu003cpu003eAOP,面向切面编程,就是把可重用的功能提取出来,然后将这些通用功能在合适的时候织入到应用程序中,比如事务管理、权限控制、日志记录、性能统计等。u003c/pu003enu003cpu003eAOP并没有帮助我们解决任何新的问题,它只是提供了一种更好的办法,能够用更少的工作量来解决现有的一些问题,使得系统更加健壮,可维护性更好。u003c/pu003enu003ch2u003e什么是Spring的事务管理?u003c/h2u003enu003cpu003e事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。u003c/pu003enu003cpu003e开发中为了避免这种情况一般都会进行事务管理。u003c/pu003enu003cpu003eSpring的声明式事务通常是指在配置文件中对事务进行配置声明,其中包括了很多声明属性,它是通过Spring Proxy帮你做代理,自己不用额外的写代码,只要在Spring配置文件中声明即可;通常用在数据库的操作里面;u003c/pu003enu003cpu003e编程式事务就是指通过硬编码的方式做事务处理,这种处理方式需要写代码,事务中的逻辑可以自己定制;可以是数据库的东东,也可以是其他的操作。u003c/pu003enu003cpu003eSpring中也有自己的事务管理机制,一般是使用TransactionMananger进行管理,可以通过Spring的注入来完成此功能。u003c/pu003enu003ch2u003eSpring框架支持以下五种bean的作用域:u003c/h2u003enu003cpu003esingleton : 默认值,bean在每个Spring ioc 容器中只有一个实例。u003c/pu003enu003cpu003eprototype:一个bean的定义可以有多个实例。u003c/pu003enu003cpu003erequest:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。u003c/pu003enu003cpu003esession:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。u003c/pu003enu003cpu003eglobal-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。u003c/pu003enu003ch2u003e什么是Spring的MVC框架?u003c/h2u003enu003cpu003eSpring 配备构建Web 应用的全功能MVC框架。Spring可以很便捷地和其他MVC框架集成,如Struts,Spring 的MVC框架用控制反转把业务对象和控制逻辑清晰地隔离。它也允许以声明的方式把请求参数和业务对象绑定。u003c/pu003enu003cpu003espring mvc是一个基于mvc的web框架。spring mvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。u003c/pu003enu003ch3u003e如何启用注解:u003c/h3u003enu003cblockquoteu003enu003cpu003eu0026lt;context:annotation-config/u0026gt;u003c/pu003enu003c/blockquoteu003enu003cpu003e如果使用u0026lt;context:component-scan base-package=”com.tgb.web.controller.annotation”u0026lt;/context:component-scanu0026gt; 则上面内容可以省略u003c/pu003enu003ch3u003eSpring MVC的请求流程:u003c/h3u003enu003cpu003e第一步:发起请求到前端控制器(DispatcherServlet)u003c/pu003enu003cpu003e第二步:前端控制器请求HandlerMapping查找Handler可以根据xml配置、注解进行查找u003c/pu003enu003cpu003e第三步:处理器映射器HandlerMapping向前端控制器返回Handleru003c/pu003enu003cpu003e第四步:前端控制器调用处理器适配器去执行Handleru003c/pu003enu003cpu003e第五步:处理器适配器去执行Handleru003c/pu003enu003cpu003e第六步:Handler执行完成给适配器返回ModelAndViewu003c/pu003enu003cpu003e第七步:处理器适配器向前端控制器返回ModelAndView。ModelAndView是springmvc框架的一个底层对象,包括 Model和viewu003c/pu003enu003cpu003e第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)u003c/pu003enu003cpu003e第九步:视图解析器向前端控制器返回Viewu003c/pu003enu003cpu003e第十步:前端控制器进行视图渲染。视图渲染将模型数据(在ModelAndView对象中)填充到request域u003c/pu003enu003cpu003e第十一步:前端控制器向用户响应结果u003c/pu003enu003ch3u003eweb.xml的配置u003c/h3u003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 479px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 56.220000000000006%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”852″ data-height=”479″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-09c679d6731f913f.png” data-original-width=”852″ data-original-height=”479″ data-original-format=”image/png” data-original-filesize=”54250″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch3u003e注解的处理器映射器和适配器u003c/h3u003enu003cpu003espring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。u003c/pu003enu003cpu003e在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。u003c/pu003enu003cpu003e使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置u003c/pu003enu003ch3u003espring 与 mybatis整合过程u003c/h3u003enu003cpu003e第一步:整合dao层u003c/pu003enu003cpu003emybatis和spring整合,通过spring管理mapper接口。u003c/pu003enu003cpu003e使用mapper的扫描器自动扫描mapper接口在spring中进行注册。u003c/pu003enu003cpu003e第二步:整合service层u003c/pu003enu003cpu003e通过spring管理 service接口。u003c/pu003enu003cpu003e使用配置方式将service接口配置在spring配置文件中。u003c/pu003enu003cpu003e实现事务控制。u003c/pu003enu003cpu003e第三步:整合springmvcu003c/pu003enu003cpu003e由于springmvc是spring的模块,不需要整合。u003c/pu003enu003cpu003e主要配置有:u003c/pu003enu003cpu003e1). mybatis配置文件sqlMapConfig.xml配置别名自动扫描(实体类)u003c/pu003enu003cpu003e2). mapper扫描器(接口,数据库访问接口)u003c/pu003enu003cpu003e3). 数据库连接池配置u003c/pu003enu003cpu003e4). 声明式事务配置u003c/pu003enu003cpu003e5). 启用注解扫描:u0026lt;context:component-scan base-package=”cn.itcast.ssm.controller”u0026gt;u0026lt;/context:component-scanu0026gt;u003c/pu003enu003cpu003e6). 配置注解映射器和适配器: u0026lt;mvc:annotation-drivenu0026gt;u0026lt;/mvc:annotation-drivenu0026gt;u003c/pu003enu003cpu003e7). 视图解析器:u0026lt;bean class=”org.springframework.web.servlet.view.InternalResourceViewResolver”u0026gt;u003c/pu003enu003cpu003e8). 配置控制类: DispatcherServlet前端控制器u003c/pu003enu003cpu003e9). 配置spring配置文件加载类:ClassLoadListeneru003c/pu003enu003cpu003eu003cstrongu003e前端控制器从上边的文件中加载处理映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,使用默认加载的 DispatcherSerlvet.properties。u003c/strongu003eu003c/pu003enu003ch3u003e视图解析器配置前缀和后缀:u003c/h3u003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 196px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 27.22%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”720″ data-height=”196″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-c8676b29663bb424.png” data-original-width=”720″ data-original-height=”196″ data-original-format=”image/png” data-original-filesize=”20216″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch3u003esqlMapConfig.xml,mybatis自己的配置文件。u003c/h3u003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 629px; max-height: 469px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 74.56%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”629″ data-height=”469″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-8d4c7c9f12059df4.png” data-original-width=”629″ data-original-height=”469″ data-original-format=”image/png” data-original-filesize=”43700″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch2u003e配置数据源:u003c/h2u003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 510px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 60.28%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”846″ data-height=”510″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-470b1acdcec877ee.png” data-original-width=”846″ data-original-height=”510″ data-original-format=”image/png” data-original-filesize=”73521″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003eu003cstrongu003e事务控制(applicationContext-transaction.xml),在applicationContext-transaction.xml中使用spring声明式事务控制方法。u003c/strongu003eu003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 520px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 54.169999999999995%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”960″ data-height=”520″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-4fd7e74748242de8.png” data-original-width=”960″ data-original-height=”520″ data-original-format=”image/png” data-original-filesize=”69785″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch3u003e加载spring配置u003c/h3u003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 180px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 21.3%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”845″ data-height=”180″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-bf22b9a3b17d53ae.png” data-original-width=”845″ data-original-height=”180″ data-original-format=”image/png” data-original-filesize=”18440″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch3u003e静态资源访问不被拦截:u003c/h3u003enu003cpreu003eu003ccode class=”c”u003e u0026lt;resources mapping=”/resources/**” location=”/resources/” /u0026gt;nn u0026lt;resources mapping=”/images/**” location=”/images/” /u0026gt;nn u0026lt;resources mapping=”/js/**” location=”/js/” /u0026gt;nu003c/codeu003eu003c/preu003enu003ch3u003e@RequestMapping的作用u003c/h3u003enu003cpu003e1). url映射u003c/pu003enu003cpu003e2). 窄化请求映射u003c/pu003enu003cpu003e3). 限制http请求方法u003c/pu003enu003ch3u003econtroller方法的返回值u003c/h3u003enu003cpu003e**返回ModelAndView **u003c/pu003enu003cpu003e需要方法结束时,定义ModelAndView,将model和view分别进行设置。u003c/pu003enu003cpu003eu003cstrongu003e返回stringu003c/strongu003eu003c/pu003enu003cpu003e如果controller方法返回string,u003c/pu003enu003cpu003e1). 表示返回逻辑视图名。真正视图(jsp路径)=前缀+逻辑视图名+后缀u003c/pu003enu003cpu003e2). redirect重定向:返回字符串格式为:”redirect:queryItem.action”u003c/pu003enu003cpu003e3). forward页面转发:返回字符串格式为:“forward:queryItem.action”u003c/pu003enu003cpu003eu003cstrongu003e返回voidu003c/strongu003eu003c/pu003enu003cpu003e在controller方法形参上可以定义request和response,使用request或response指定响应结果:u003c/pu003enu003cpu003e1). 使用request转向页面,如下:request.getRequestDispatcher(“页面路径”).forward(request, response);u003c/pu003enu003cpu003e2). 也可以通过response页面重定向:response.sendRedirect(“url”)u003c/pu003enu003cpu003e3). 也可以通过response指定响应结果,例如响应json数据如下:u003c/pu003enu003culu003enu003cliu003eu003cpu003eresponse.setCharacterEncoding(“utf-8”);u003c/pu003eu003c/liu003enu003cliu003eu003cpu003eresponse.setContentType(“application/json;charset=utf-8”);u003c/pu003eu003c/liu003enu003cliu003eu003cpu003eresponse.getWriter().write(“json串”);u003c/pu003eu003c/liu003enu003c/ulu003enu003ch3u003e参数绑定:u003c/h3u003enu003cpu003eu003cstrongu003e默认支持的类型u003c/strongu003eu003c/pu003enu003cpu003e直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。u003c/pu003enu003cpu003e1). HttpServletRequest:通过request对象获取请求信息u003c/pu003enu003cpu003e2). HttpServletResponse:通过response处理响应信息u003c/pu003enu003cpu003e3). HttpSession:通过session对象得到session中存放的对象u003c/pu003enu003cpu003e4). Model/ModelMap:model是一个接口,modelMap是一个接口实现 。作用:将model数据填充到request域。u003c/pu003enu003cpu003eu003cstrongu003e简单类型u003c/strongu003eu003c/pu003enu003culu003enu003cliu003eu003cpu003e通过@RequestParam对简单类型的参数进行绑定。u003c/pu003eu003c/liu003enu003cliu003eu003cpu003e如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。u003c/pu003eu003c/liu003enu003cliu003eu003cpu003e如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。u003c/pu003eu003c/liu003enu003cliu003eu003cpu003e通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,会报错。u003c/pu003eu003c/liu003enu003c/ulu003enu003ch3u003epojo绑定u003c/h3u003enu003cpu003e页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。(usename,age;不需要user.username,user.age)u003c/pu003enu003cpu003eu003cstrongu003e自定义参数绑定实现日期类型绑定u003c/strongu003eu003c/pu003enu003cpu003e对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期数据串转成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。u003c/pu003enu003ch2u003eSpring MVC 和 Struts2 对比u003c/h2u003enu003cpu003e1.Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC 就容易实现restful urlu003c/pu003enu003cpu003e2.由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。u003c/pu003enu003cpu003e3.由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。u003c/pu003enu003cpu003e4.SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。u003c/pu003enu003cpu003e5.springmvc面向方法开发的(更接近service接口的开发方式),struts2面向类开发。u003c/pu003enu003cpu003e6.springmvc可以单例开发,struts2只能是多例开发。u003c/pu003enu003ch2u003e乱码处理u003c/h2u003enu003cpu003e1). post乱码u003c/pu003enu003cpu003e在web.xml添加post乱码filter:CharacterEncodingFilteru003c/pu003enu003cpu003e2). 对于get请求中文参数出现乱码解决方法有两个:u003c/pu003enu003cpu003ea. 修改tomcat配置文件添加编码与工程编码一致,如下:u003c/pu003enu003cpu003eu0026lt;Connector URIEncoding=”utf-8″ connectionTimeout=”20000″ port=”8080″ protocol=”HTTP/1.1″ redirectPort=”8443″/u0026gt;u003c/pu003enu003cpu003eb. 对参数进行重新编码:u003c/pu003enu003cpu003eString userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1″),”utf-8”)u003c/pu003enu003cpu003eISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码u003c/pu003enu003ch2u003e集合类型绑定u003c/h2u003enu003cpu003e1). 数组绑定:u003c/pu003enu003cpu003econtroller方法参数使用:(Integer[] itemId)u003c/pu003enu003cpu003e页面统一使用:itemId 作为nameu003c/pu003enu003cpu003e2). list绑定:u003c/pu003enu003cpu003epojo属性名为:itemsListu003c/pu003enu003cpu003e页面:itemsList[index].属性名u003c/pu003enu003cpu003e3). map 绑定:u003c/pu003enu003cpu003epojo属性名为:Mapu0026lt;String, Objectu0026gt; itemInfo = new HashMapu0026lt;String, Objectu0026gt;();u003c/pu003enu003cpu003e页面: u0026lt;tdu0026gt;姓名:u0026lt;inputtype=”text”name=”itemInfo[‘name’]”/u0026gt;u003c/pu003enu003ch2u003espring 校验u003c/h2u003enu003cpu003e1). 项目中,通常使用较多是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。u003c/pu003enu003cpu003e2). springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。u003c/pu003enu003cpu003e校验思路:页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。u003c/pu003enu003ch2u003e数据回显u003c/h2u003enu003cpu003e1). @ModelAttribute还可以将方法的返回值传到页面:在方法上加注解@ModelAttributeu003c/pu003enu003cpu003e2). 使用最简单方法使用model,可以不用@ModelAttribute:model.addAttribute(“id”, id);u003c/pu003enu003cpu003e3). springmvc默认对pojo数据进行回显。pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)u003c/pu003enu003cpu003e4). public String testParam(PrintWriter out, @RequestParam(“username”) String username) { //out直接输出u003c/pu003enu003ch2u003e异常处理u003c/h2u003enu003cpu003espringmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。u003c/pu003enu003cpu003e系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。u003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 672px; max-height: 90px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 13.389999999999999%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”672″ data-height=”90″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-099275b2ec3bb8c0.png” data-original-width=”672″ data-original-height=”90″ data-original-format=”image/png” data-original-filesize=”8601″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch2u003e上传图片u003c/h2u003enu003cpu003e1). 在页面form中提交enctype=”multipart/form-data”的数据时,需要springmvc对multipart类型的数据进行解析。u003c/pu003enu003cpu003e2). 在springmvc.xml中配置multipart类型解析器。u003c/pu003enu003cbru003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 173px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 23.73%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”729″ data-height=”173″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-e7d1b9a6520c8d3e.png” data-original-width=”729″ data-original-height=”173″ data-original-format=”image/png” data-original-filesize=”17484″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003e3). 方法中使用:MultipartFile attach (单个文件上传) 或者 MultipartFile[] attachs (多个文件上传)u003c/pu003enu003ch2u003eJson处理u003c/h2u003enu003cpu003e1). 加载json转换的jar包:springmvc中使用jackson的包进行json转换(@requestBody和@responseBody使用下边的包进行json转)u003c/pu003enu003cpu003e2). 配置json转换器。在注解适配器RequestMappingHandlerAdapter中加入messageConverters。如果使用u0026lt;mvc:annotation-driven /u0026gt; 则会自动加入。u003c/pu003enu003cpu003e3). ajaxu003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 691px; max-height: 319px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 46.160000000000004%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”691″ data-height=”319″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-7f67d3805f70b4d5.png” data-original-width=”691″ data-original-height=”319″ data-original-format=”image/png” data-original-filesize=”21899″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003e4). Controller (ResponseBody、RequestBody)u003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 200px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 26.009999999999998%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”769″ data-height=”200″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-5c1204270db4e75e.png” data-original-width=”769″ data-original-height=”200″ data-original-format=”image/png” data-original-filesize=”22084″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003e注意ajax中contentType如果不设置为json类型,则传的参数为key/value类型。u003cstrongu003e上面设置后,传的是json类型。u003c/strongu003eu003c/pu003enu003cpu003e详见:u003ca href=”https://links.jianshu.com/go?to=http%3A%2F%2Fwww.cnblogs.com%2FJtianlin%2Fp%2F5224885.html” target=”_blank”u003ehttp://www.cnblogs.com/Jtianlin/p/5224885.htmlu003c/au003eu003c/pu003enu003ch2u003e拦截器:u003c/h2u003enu003cpu003e1). 定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。u003c/pu003enu003cpu003ea. preHandle :进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行u003c/pu003enu003cpu003eb. postHandle:进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图u003c/pu003enu003cpu003ec. afterCompletion:执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理u003c/pu003enu003cpu003e2). 拦截器配置:u003c/pu003enu003cpu003ea. 针对HandlerMapping配置(不推荐):springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。 (一般不推荐使用)u003c/pu003enu003cpu003eb. 类似全局的拦截器:springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中u003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 700px; max-height: 273px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 37.76%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”723″ data-height=”273″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-685a96258fb81cb4.png” data-original-width=”723″ data-original-height=”273″ data-original-format=”image/png” data-original-filesize=”26506″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch2u003e如何启用注解:u003c/h2u003enu003cpu003eu0026lt;context:annotation-config/u0026gt;u003c/pu003enu003cpu003e如果使用u0026lt;context:component-scan base-package=”com.tgb.web.controller.annotation”u0026gt; u0026lt;/context:component-scanu0026gt; 则上面内容可以省略 使用 mvc:annotation-driven代替注解映射器和注解适配器配置u003c/pu003enu003cpu003eu003c/pu003eu003chru003eu003cpu003eu003c/pu003enu003ch2u003e什么是Spring Boot?它解决了什么问题?u003c/h2u003enu003cpu003e初期的Spring通过代码加配置的形式为项目提供了良好的灵活性和扩展性,但随着Spring越来越庞大,其配置文件也越来越繁琐,太多复杂的xml文件也一直是Spring被人诟病的地方,特别是近些年其他简洁的WEB方案层出不穷,如基于Python或Node.Js,几行代码就能实现一个WEB服务器,对比起来,大家渐渐觉得Spring那一套太过繁琐,此时,Spring社区推出了Spring Boot,它的目的在于实现自动配置,降低项目搭建的复杂度,如需要搭建一个接口服务,通过Spring Boot,几行代码即可实现,请看代码示例:u003c/pu003enu003cpreu003eu003ccode class=”c”u003e//引入spring-boot-starter-web依赖nu0026lt;dependencyu0026gt;n u0026lt;groupIdu0026gt;org.springframework.bootu0026lt;/groupIdu0026gt;n u0026lt;artifactIdu0026gt;spring-boot-starter-webu0026lt;/artifactIdu0026gt;nu0026lt;/dependencyu0026gt;nu003c/codeu003eu003c/preu003enu003cpreu003eu003ccode class=”c”u003e//声明Spring Boot应用,直接写业务逻辑即可n@Controllern@SpringBootApplicationnpublic class MockServerApplication {n @RequestMapping(“/hi”)n @ResponseBodyn String home() {n return “how are you!”;n }nn public static void main(String[] args) {n SpringApplication.run(MockServerApplication.class, args);n }n}nu003c/codeu003eu003c/preu003enu003cpu003e你甚至都不用额外的WEB容器,直接生成jar包执行即可,因为u003ccodeu003espring-boot-starter-webu003c/codeu003e模块中包含有一个内置tomcat,可以直接提供容器使用;基于Spring Boot,不是说原来的配置没有了,而是Spring Boot有一套默认配置,我们可以把它看做比较通用的约定,而Spring Boot遵循的也是约定优于配置原则,同时,如果你需要使用到Spring以往提供的各种复杂但功能强大的配置功能,Spring Boot一样支持u003c/pu003enu003cpu003e在Spring Boot中,你会发现你引入的所有包都是u003c/pu003enu003cpu003estarteru003c/pu003enu003cpu003e形式,如:u003c/pu003enu003culu003enu003cliu003espring-boot-starter-web-services,针对SOAP Web Servicesu003c/liu003enu003cliu003espring-boot-starter-web,针对Web应用与网络接口u003c/liu003enu003cliu003espring-boot-starter-jdbc,针对JDBCu003c/liu003enu003cliu003espring-boot-starter-data-jpa,基于hibernate的持久层框架u003c/liu003enu003cliu003espring-boot-starter-cache,针对缓存支持u003c/liu003enu003cliu003e等等u003c/liu003enu003c/ulu003enu003cpu003eSpring Boot对starter的解释如下:u003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 625px; max-height: 154px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 24.64%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”625″ data-height=”154″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-a92bbcbc157d2f4f.png” data-original-width=”625″ data-original-height=”154″ data-original-format=”image/png” data-original-filesize=”22856″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003e这句话的译意为:u003c/pu003enu003cbru003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 632px; max-height: 100px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 15.82%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”632″ data-height=”100″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-2709195ec212273b.png” data-original-width=”632″ data-original-height=”100″ data-original-format=”image/png” data-original-filesize=”21460″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003ch2u003eSpring REST如何使用?u003c/h2u003enu003ch4u003e准备工作u003c/h4u003enu003cpu003e1、 下载jar包u003c/pu003enu003cpu003espring各版本jar下载地址:u003ca href=”https://links.jianshu.com/go?to=http%3A%2F%2Febr.springsource.com%2Frepository%2Fapp%2Flibrary%2Fdetail%3Fname%3Dorg.springframework.spring” target=”_blank”u003ehttp://ebr.springsource.com/repository/app/library/detail?name=org.springframework.springu003c/au003eu003c/pu003enu003cpu003e相关的依赖包也可以在这里找到:u003ca href=”https://links.jianshu.com/go?to=http%3A%2F%2Febr.springsource.com%2Frepository%2Fapp%2Flibrary” target=”_blank”u003ehttp://ebr.springsource.com/repository/app/libraryu003c/au003eu003c/pu003enu003cpu003e2、 需要jar包如下u003c/pu003enu003cdiv class=”image-package”u003enu003cdiv class=”image-container” style=”max-width: 244px; max-height: 168px;”u003enu003cdiv class=”image-container-fill” style=”padding-bottom: 68.85%;”u003eu003c/divu003enu003cdiv class=”image-view” data-width=”244″ data-height=”168″u003eu003cimg data-original-src=”//upload-images.jianshu.io/upload_images/26011540-7edd820fb71516a3.png” data-original-width=”244″ data-original-height=”168″ data-original-format=”image/png” data-original-filesize=”73496″u003eu003c/divu003enu003c/divu003enu003cdiv class=”image-caption”u003eimage.pngu003c/divu003enu003c/divu003enu003cpu003e3、 当前工程的web.xml配置u003c/pu003enu003cpreu003eu003ccode class=”c”u003eu0026lt;?xml version=”1.0″ encoding=”UTF-8″?u0026gt;nu0026lt;web-app version=”2.4″ n xmlns=”http://java.sun.com/xml/ns/j2ee” n xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” n xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee n http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”u0026gt;n n u0026lt;!– 配置Spring核心控制器 –u0026gt;n u0026lt;servletu0026gt;n u0026lt;servlet-nameu0026gt;dispatcheru0026lt;/servlet-nameu0026gt;n u0026lt;servlet-classu0026gt;org.springframework.web.servlet.DispatcherServletu0026lt;/servlet-classu0026gt;n u0026lt;init-paramu0026gt;n u0026lt;param-nameu0026gt;contextConfigLocationu0026lt;/param-nameu0026gt;n u0026lt;param-valueu0026gt;/WEB-INF/dispatcher.xmlu0026lt;/param-valueu0026gt;n u0026lt;/init-paramu0026gt;n u0026lt;load-on-startupu0026gt;1u0026lt;/load-on-startupu0026gt;n u0026lt;/servletu0026gt;n n u0026lt;servlet-mappingu0026gt;n u0026lt;servlet-nameu0026gt;dispatcheru0026lt;/servlet-nameu0026gt;n u0026lt;url-patternu0026gt;*.dou0026lt;/url-patternu0026gt;n u0026lt;/servlet-mappingu0026gt;n n u0026lt;welcome-file-listu0026gt;n u0026lt;welcome-fileu0026gt;index.jspu0026lt;/welcome-fileu0026gt;n u0026lt;/welcome-file-listu0026gt;nu0026lt;/web-appu0026gt;nu003c/codeu003eu003c/preu003enu003cpu003e4、 WEB-INF中的dispatcher.xml配置u003c/pu003enu003cpreu003eu003ccode class=”c”u003eu0026lt;?xml version=”1.0″ encoding=”UTF-8″?u0026gt;nu0026lt;beans xmlns=”http://www.springframework.org/schema/beans”n xmlns:mvc=”http://www.springframework.org/schema/mvc”n xmlns:context=”http://www.springframework.org/schema/context”n xmlns:util=”http://www.springframework.org/schema/util”n xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”n xsi:schemaLocation=”http://www.springframework.org/schema/beans n http://www.springframework.org/schema/beans/spring-beans-3.0.xsdn http://www.springframework.org/schema/mvcn http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsdn http://www.springframework.org/schema/context n http://www.springframework.org/schema/context/spring-context-3.0.xsdn http://www.springframework.org/schema/utiln http://www.springframework.org/schema/util/spring-util-3.0.xsd”u0026gt;n n u0026lt;context:component-scan base-package=”com.hoo.*”u0026gt;n u0026lt;!– 忽略这个类 –u0026gt;n u0026lt;context:exclude-filter type=”assignable” expression=”com.hoo.client.RESTClient”/u0026gt;n u0026lt;/context:component-scanu0026gt;n n u0026lt;!– annotation的方法映射适配器 –u0026gt;n u0026lt;bean id=”handlerAdapter” class=”org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter”/u0026gt;n n u0026lt;!– xml视图,XStreamMarshaller,可以转换任何形式的java对象 –u0026gt;n u0026lt;bean name=”xStreamMarshallingView” class=”org.springframework.web.servlet.view.xml.MarshallingView”u0026gt;n u0026lt;property name=”marshaller”u0026gt;n u0026lt;bean class=”org.springframework.oxm.xstream.XStreamMarshaller”u0026gt; n u0026lt;!– 为了初始化XStreamMarshaller,这个类会把我们接口中得到结果以XML文档形式展现出来 –u0026gt;n u0026lt;property name=”autodetectAnnotations” value=”true”/u0026gt; n u0026lt;/beanu0026gt; n u0026lt;/propertyu0026gt;n u0026lt;/beanu0026gt;n n u0026lt;!– 视图解析器,根据视图的名称new ModelAndView(name),在配置文件查找对应的bean配置 –u0026gt;n u0026lt;bean class=”org.springframework.web.servlet.view.BeanNameViewResolver”u0026gt;n u0026lt;property name=”order” value=”3″/u0026gt;n u0026lt;/beanu0026gt;n n u0026lt;!– annotation默认的方法映射适配器 –u0026gt;n u0026lt;bean id=”handlerMapping” class=”org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping”u0026gt;n u0026lt;property name=”order” value=”1″ /u0026gt;n u0026lt;/beanu0026gt;n nu0026lt;/beansu0026gt;n5、 启动后,可以看到index.jsp 没有出现异常或错误。那么当前SpringMVC的配置就成功了。nu003c/codeu003eu003c/preu003enu003ch3u003e二、REST控制器实现u003c/h3u003enu003cpu003eREST控制器主要完成CRUD操作,也就是对于http中的post、get、put、delete。u003c/pu003enu003cpu003e还有其他的操作,如head、options、trace。u003c/pu003enu003cpu003e具体代码:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epackage com.hoo.controller;n nimport org.springframework.stereotype.Controller;nimport org.springframework.web.bind.annotation.PathVariable;nimport org.springframework.web.bind.annotation.RequestMapping;nimport org.springframework.web.bind.annotation.RequestMethod;nimport org.springframework.web.servlet.ModelAndView;n n/**n * u0026lt;bu0026gt;function:u0026lt;/bu0026gt;SpringMVC REST示例n * @author hoojon * @createDate 2011-6-9 上午11:34:08n * @file RESTController.javan * @package com.hoo.controllern * @project SpringRestWSn * @blog http://blog.csdn.net/IBM_hoojon * @email hoojo_@126.comn * @version 1.0n */n@RequestMapping(“/restful”)n@Controllernpublic class RESTController {n n @RequestMapping(value = “/show”, method = RequestMethod.GET)n public ModelAndView show() {n System.out.println(“show”);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“show method”);n return model; n }n n @RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)n public ModelAndView getUserById(@PathVariable String id) {n System.out.println(“getUserById-” + id);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“getUserById method -” + id);n return model; n }n n @RequestMapping(value = “/add”, method = RequestMethod.POST)n public ModelAndView addUser(String user) {n System.out.println(“addUser-” + user);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“addUser method -” + user);n return model; n }n n @RequestMapping(value = “/edit”, method = RequestMethod.PUT)n public ModelAndView editUser(String user) {n System.out.println(“editUser-” + user);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“editUser method -” + user);n return model;n }n n @RequestMapping(value = “/remove/{id}”, method = RequestMethod.DELETE)n public ModelAndView removeUser(@PathVariable String id) {n System.out.println(“removeUser-” + id);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“removeUser method -” + id);n return model;n }n}nu003c/codeu003eu003c/preu003enu003cpu003e上面的方法对应的http操作:u003c/pu003enu003cpreu003eu003ccode class=”c”u003e/show -u0026gt; get 查询n/get/id -u0026gt; get 查询n/add -u0026gt; post 添加n/edit -u0026gt; put 修改n/remove/id -u0026gt; delete 删除nu003c/codeu003eu003c/preu003enu003cpu003e在这个方法中,就可以看到RESTful风格的url资源标识u003c/pu003enu003cpreu003eu003ccode class=”c”u003e@RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)npublic ModelAndView getUserById(@PathVariable String id) {n System.out.println(“getUserById-” + id);n ModelAndView model = new ModelAndView(“xStreamMarshallingView”);n model.addObject(“getUserById method -” + id);n return model; n}nu003c/codeu003eu003c/preu003enu003cpu003evalue=”/get/{id}”就是url中包含get,并且带有id参数的get请求,就会执行这个方法。这个url在请求的时候,会通过Annotation的@PathVariable来将url中的id值设置到getUserById的参数中去。 ModelAndView返回的视图是xStreamMarshallingView是一个xml视图,执行当前请求后,会显示一篇xml文档。文档的内容是添加到model中的值。u003c/pu003enu003ch3u003e三、利用RestTemplate调用REST资源u003c/h3u003enu003cpu003e代码如下:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epackage com.hoo.client;n nimport org.springframework.beans.factory.annotation.Autowired;nimport org.springframework.stereotype.Component;nimport org.springframework.web.client.RestTemplate;n n/**n * u0026lt;bu0026gt;function:u0026lt;/bu0026gt;RestTemplate调用REST资源n * @author hoojon * @createDate 2011-6-9 上午11:56:16n * @file RESTClient.javan * @package com.hoo.clientn * @project SpringRestWSn * @blog http://blog.csdn.net/IBM_hoojon * @email hoojo_@126.comn * @version 1.0n */n@Componentnpublic class RESTClient {n n @Autowiredn private RestTemplate template;n n private final static String url = “http://localhost:8080/SpringRestWS/restful/”;n n public String show() {n return template.getForObject(url + “show.do”, String.class, new String[]{});n }n n public String getUserById(String id) {n return template.getForObject(url + “get/{id}.do”, String.class, id); n }n n public String addUser(String user) {n return template.postForObject(url + “add.do?user={user}”, null, String.class, user);n }n n public String editUser(String user) {n template.put(url + “edit.do?user={user}”, null, user);n return user;n }n n public String removeUser(String id) {n template.delete(url + “/remove/{id}.do”, id);n return id;n }n}nu003c/codeu003eu003c/preu003enu003culu003enu003cliu003eRestTemplate的getForObject完成get请求、postForObject完成post请求、put对应的完成put请求、delete完成delete请求;还有execute可以执行任何请求的方法,需要你设置RequestMethod来指定当前请求类型。u003c/liu003enu003cliu003eRestTemplate.getForObject(String url, Classu0026lt;Stringu0026gt; responseType, String… urlVariables)u003c/liu003enu003cliu003e参数url是http请求的地址,参数Class是请求响应返回后的数据的类型,最后一个参数是请求中需要设置的参数。u003c/liu003enu003cliu003etemplate.getForObject(url + “get/{id}.do”, String.class, id);u003c/liu003enu003cliu003e如上面的参数是{id},返回的是一个string类型,设置的参数是id。最后执行该方法会返回一个String类型的结果。u003c/liu003enu003c/ulu003enu003cpu003e下面建立一个测试类,完成对RESTClient的测试。代码如下:u003c/pu003enu003cpreu003eu003ccode class=”c”u003epackage com.hoo.client;n nimport org.springframework.beans.factory.annotation.Autowired;nimport org.springframework.test.context.ContextConfiguration;nimport org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;n n/**n * u0026lt;bu0026gt;function:u0026lt;/bu0026gt;RESTClient TESTn * @author hoojon * @createDate 2011-6-9 下午03:50:21n * @file RESTClientTest.javan * @package com.hoo.clientn * @project SpringRestWSn * @blog http://blog.csdn.net/IBM_hoojon * @email hoojo_@126.comn * @version 1.0n */n@ContextConfiguration(“classpath:applicationContext-*.xml”)npublic class RESTClientTest extends AbstractJUnit38SpringContextTests {n n @Autowiredn private RESTClient client;n n public void testShow() {n System.out.println(client.show());n }n n public void testGetUserById() {n System.out.println(client.getUserById(“abc”));n }n n public void testAddUser() {n System.out.println(client.addUser(“jack”));n }n n public void testEditUser() {n System.out.println(client.editUser(“tom”));n }n n public void testRemoveUser() {n System.out.println(client.removeUser(“aabb”));n }n}nu003c/codeu003eu003c/preu003enu003cpu003e我们需要在src目录下添加applicationContext-beans.xml完成对restTemplate的配置。restTemplate需要配置MessageConvert将返回的xml文档进行转换,解析成JavaObject。u003c/pu003enu003cpreu003eu003ccode class=”c”u003eu0026lt;?xml version=”1.0″ encoding=”UTF-8″?u0026gt;nu0026lt;beans xmlns=”http://www.springframework.org/schema/beans”n xmlns:context=”http://www.springframework.org/schema/context”n xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”n xsi:schemaLocation=”http://www.springframework.org/schema/beans n http://www.springframework.org/schema/beans/spring-beans-3.0.xsdn http://www.springframework.org/schema/contextn http://www.springframework.org/schema/context/spring-context-3.0.xsd”u0026gt;n n u0026lt;context:component-scan base-package=”com.hoo.*”/u0026gt;n n u0026lt;bean id=”restTemplate” class=”org.springframework.web.client.RestTemplate”u0026gt;n u0026lt;property name=”messageConverters”u0026gt;n u0026lt;listu0026gt;n u0026lt;bean class=”org.springframework.http.converter.xml.MarshallingHttpMessageConverter”u0026gt;n u0026lt;property name=”marshaller” ref=”xStreamMarshaller”/u0026gt;n u0026lt;property name=”unmarshaller” ref=”xStreamMarshaller”/u0026gt;n u0026lt;/beanu0026gt;n u0026lt;/listu0026gt;n u0026lt;/propertyu0026gt;n u0026lt;/beanu0026gt;n n u0026lt;bean id=”xStreamMarshaller” class=”org.springframework.oxm.xstream.XStreamMarshaller”u0026gt;n u0026lt;property name=”annotatedClasses”u0026gt;n u0026lt;arrayu0026gt; n u0026lt;/arrayu0026gt;n u0026lt;/propertyu0026gt;n u0026lt;/beanu0026gt;nu0026lt;/beansu0026gt;nu003c/codeu003eu003c/preu003enu003cpu003e上面配置了xStreamMarshaller是和RESTController中的ModelAndView的view对应的。因为那边是用xStreamMarshaller进行编组的,所以RestTemplate这边也需要用它来解组。RestTemplate还指出其他的MarshallingHttpMessageConverteru003c/pu003en”,”voted_down”:false,”rewardable”:true,”show_paid_comment_tips”:false,”share_image_url”:”https://upload-images.jianshu.io/upload_images/26011540-09c679d6731f913f.png”,”slug”:”dfaa6954287d”,”user”:{“liked_by_user”:false,”following_count”:9,”gender”:1,”avatar_widget”:null,”slug”:”f55db1589ea6″,”intro”:””,”likes_count”:18,”nickname”:”f55db1589ea6″,”badges”:[],”total_fp_amount”:”1497286085520975900″,”wordage”:59287,”avatar”:”https://upload.jianshu.io/users/upload_avatars/26011540/30d5ad0c-d43b-4660-bbb9-d44d3c1ca8d6.jpg”,”id”:26011540,”liked_user”:false},”likes_count”:6,”paid_type”:”free”,”show_ads”:true,”paid_content_accessible”:false,”hide_search_input”:true,”total_fp_amount”:”716000000000000000″,”trial_open”:false,”reprintable”:true,”bookmarked”:false,”wordage”:6283,”featured_comments_count”:0,”downvotes_count”:0,”wangxin_trial_open”:null,”guideShow”:{“audit_user_nickname_spliter”:0,”pc_note_bottom_btn”:1,”pc_like_author_guidance”:1,”ban_some_labels”:1,”h5_real_name_auth_link”:1,”audit_user_background_image_spliter”:0,”audit_note_spliter”:0,”new_user_no_ads”:1,”launch_tab”:0,”include_post”:0,”pc_login_guidance”:1,”audit_comment_spliter”:0,”pc_note_bottom_qrcode”:1,”audit_user_avatar_spliter”:0,”audit_collection_spliter”:0,”pc_top_lottery_guidance”:2,”subscription_guide_entry”:1,”creation_muti_function_on”:1,”explore_score_searcher”:0,”audit_user_spliter”:0,”h5_ab_test”:1,”reason_text”:1,”pc_note_popup”:2},”commentable”:true,”total_rewards_count”:0,”id”:85783421,”notebook”:{“name”:””},”activity_collection_slug”:null,”description”:”前言 Spring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等。但他们的基础都是Spring的ioc和aop。ioc提供了依赖注入的容器,aop…”,”first_shared_at”:1617011068,”views_count”:378,”notebook_id”:49694532},”baseList”:{“likeList”:[],”rewardList”:[]},”status”:”success”,”statusCode”:0},”user”:{“isLogin”:false,”userInfo”:{}},”comments”:{“list”:[],”featuredList”:[]}},”initialProps”:{“pageProps”:{“query”:{“slug”:”dfaa6954287d”}},”localeData”:{“common”:{“jianshu”:”简书”,”diamond”:”简书钻”,”totalAssets”:”总资产{num}”,”diamondValue”:” (约{num}元)”,”login”:”登录”,”logout”:”注销”,”register”:”注册”,”on”:”开”,”off”:”关”,”follow”:”关注”,”followBook”:”关注连载”,”following”:”已关注”,”cancelFollow”:”取消关注”,”publish”:”发布”,”wordage”:”字数”,”audio”:”音频”,”read”:”阅读”,”reward”:”赞赏”,”zan”:”赞”,”comment”:”评论”,”expand”:”展开”,”prevPage”:”上一页”,”nextPage”:”下一页”,”floor”:”楼”,”confirm”:”确定”,”delete”:”删除”,”report”:”举报”,”fontSong”:”宋体”,”fontBlack”:”黑体”,”chs”:”简体”,”cht”:”繁体”,”jianChat”:”简信”,”postRequest”:”投稿请求”,”likeAndZan”:”喜欢和赞”,”rewardAndPay”:”赞赏和付费”,”home”:”我的主页”,”markedNotes”:”收藏的文章”,”likedNotes”:”喜欢的文章”,”paidThings”:”已购内容”,”wallet”:”我的钱包”,”setting”:”设置”,”feedback”:”帮助与反馈”,”loading”:”加载中…”,”needLogin”:”请登录后进行操作”,”trialing”:”文章正在审核中…”,”reprintTip”:”禁止转载,如需转载请通过简信或评论联系作者。”},”error”:{“rewardSelf”:”无法打赏自己的文章哟~”},”message”:{“paidNoteTip”:”付费购买后才可以参与评论哦”,”CommentDisableTip”:”作者关闭了评论功能”,”contentCanNotEmptyTip”:”回复内容不能为空”,”addComment”:”评论发布成功”,”deleteComment”:”评论删除成功”,”likeComment”:”评论点赞成功”,”setReadMode”:”阅读模式设置成功”,”setFontType”:”字体设置成功”,”setLocale”:”显示语言设置成功”,”follow”:”关注成功”,”cancelFollow”:”取消关注成功”,”copySuccess”:”复制代码成功”},”header”:{“homePage”:”首页”,”download”:”下载APP”,”discover”:”发现”,”message”:”消息”,”reward”:”赞赏支持”,”editNote”:”编辑文章”,”writeNote”:”写文章”},”note”:{},”noteMeta”:{“lastModified”:”最后编辑于 “,”wordage”:”字数 {num}”,”viewsCount”:”阅读 {num}”},”divider”:{“selfText”:”以下内容为付费内容,定价 ¥{price}”,”paidText”:”已付费,可查看以下内容”,”notPaidText”:”还有 {percent} 的精彩内容”,”modify”:”点击修改”},”paidPanel”:{“buyNote”:”支付 ¥{price} 继续阅读”,”buyBook”:”立即拿下 ¥{price}”,”freeTitle”:”该作品为付费连载”,”freeText”:”购买即可永久获取连载内的所有内容,包括将来更新的内容”,”paidTitle”:”还没看够?拿下整部连载!”,”paidText”:”永久获得连载内的所有内容, 包括将来更新的内容”},”book”:{“last”:”已是最后”,”lookCatalog”:”查看连载目录”,”header”:”文章来自以下连载”},”action”:{“like”:”{num}人点赞”,”collection”:”收入专题”,”report”:”举报文章”},”comment”:{“allComments”:”全部评论”,”featuredComments”:”精彩评论”,”closed”:”评论已关闭”,”close”:”关闭评论”,”open”:”打开评论”,”desc”:”按时间倒序”,”asc”:”按时间正序”,”disableText1″:”用户已关闭评论,”,”disableText2″:”与Ta简信交流”,”placeholder”:”写下你的评论…”,”publish”:”发表”,”create”:” 添加新评论”,”reply”:” 回复”,”restComments”:”还有{num}条评论,”,”expandImage”:”展开剩余{num}张图”,”deleteText”:”确定要删除评论么?”},”collection”:{“title”:”被以下专题收入,发现更多相似内容”,”putToMyCollection”:”收入我的专题”},”seoList”:{“title”:”推荐阅读”,”more”:”更多精彩内容”},”sideList”:{“title”:”推荐阅读”},”wxShareModal”:{“desc”:”打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮”},”bookChapterModal”:{“try”:”试读”,”toggle”:”切换顺序”},”collectionModal”:{“title”:”收入到我管理的专题”,”search”:”搜索我管理的专题”,”newCollection”:”新建专题”,”create”:”创建”,”nothingFound”:”未找到相关专题”,”loadMore”:”展开查看更多”},”contributeModal”:{“search”:”搜索专题投稿”,”newCollection”:”新建专题”,”addNewOne”:”去新建一个”,”nothingFound”:”未找到相关专题”,”loadMore”:”展开查看更多”,”managed”:”我管理的专题”,”recommend”:”推荐专题”},”QRCodeShow”:{“payTitle”:”微信扫码支付”,”payText”:”支付金额”},”rewardModal”:{“title”:”给作者送糖”,”custom”:”自定义”,”placeholder”:”给Ta留言…”,”choose”:”选择支付方式”,”balance”:”简书余额”,”tooltip”:”网站该功能暂时下线,如需使用,请到简书App操作”,”confirm”:”确认支付”,”success”:”赞赏成功”},”payModal”:{“payBook”:”购买连载”,”payNote”:”购买文章”,”promotion”:”优惠券”,”promotionFetching”:”优惠券获取中…”,”noPromotion”:”无可用优惠券”,”promotionNum”:”{num}张可用”,”noUsePromotion”:”不使用优惠券”,”validPromotion”:”可用优惠券”,”invalidPromotion”:”不可用优惠券”,”total”:”支付总额”,”tip1″:”· 你将购买的商品为虚拟内容服务,购买后不支持退订、转让、退换,请斟酌确认。”,”tip2″:”· 购买后可在“已购内容”中查看和使用。”,”success”:”购买成功”},”reportModal”:{“ad”:”广告及垃圾信息”,”plagiarism”:”抄袭或未授权转载”,”placeholder”:”写下举报的详情情况(选填)”,”success”:”举报成功”},”guidModal”:{“modalAText”:”相似文章推荐”,”subText”:”下载简书APP,浏览更多相似文章”,”btnAText”:”先不下载,下次再说”,”followOkText”:”关注作者成功!”,”followTextTip”:”下载简书APP,作者更多精彩内容更新及时提醒!”,”followBtn”:”下次再说”,”downloadTipText”:”更多精彩内容,就在简书APP”,”footerDownLoadText”:”下载简书APP”,”modabTitle”:”免费送你2次抽奖机会”,”modalbTip”:”抽取10000收益加成卡,下载简书APP概率翻倍”,”modalbFooterTip”:”下载简书APP,天天参与抽大奖”,”modalReward”:”抽奖”,”scanQrtip”:”扫码下载简书APP”,”downloadAppText”:”下载简书APP,随时随地发现和创作内容”,”redText”:”阅读”,”likesText”:”赞”,”downLoadLeft”:”更多好文”,”leftscanText”:”把文字装进口袋”}},”currentLocale”:”zh-CN”,”asPath”:”/p/dfaa6954287d”}},”page”:”/p/[slug]”,”query”:{“slug”:”dfaa6954287d”},”buildId”:”lcwHSLQvYZGBn55hiTPfZ”,”assetPrefix”:”https://cdn2.jianshu.io/shakespeare”}