迁移Spring MVC RESTful到Spring4
Spring4主要在Web服务方面有下面两个方面提升:
1. 控制器使用@ResponseBody和 @RestController
2.异步调用。
项目迁移前后的源码:
下图是Spring 3.2的数据模型图:

Spring3.2 配置:
<import resource="db-context.xml"/>
<!-- Detects annotations like @Component, @Service, @Controller, @Repository, @Configuration -->
<context:component-scan base-package="xpadro.spring.web.controller,xpadro.spring.web.service"/>
<!-- Detects MVC annotations like @RequestMapping -->
<mvc:annotation-driven/>
db-context.xml
<!-- Registers a mongo instance -->
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
<property name="host" value="localhost" />
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongo" ref="mongo" />
<constructor-arg name="databaseName" value="rest-db" />
</bean>
服务代码实现:
@Service
public class SeriesServiceImpl implements SeriesService {
@Autowired
private MongoOperations mongoOps;
@Override
public Series[] getAllSeries() {
List<Series> seriesList = mongoOps.findAll(Series.class);
return seriesList.toArray(new Series[0]);
}
@Override
public Series getSeries(long id) {
return mongoOps.findById(id, Series.class);
}
@Override
public void insertSeries(Series series) {
mongoOps.insert(series);
}
@Override
public void deleteSeries(long id) {
Query query = new Query();
Criteria criteria = new Criteria("_id").is(id);
query.addCriteria(criteria);
mongoOps.remove(query, Series.class);
}
}
控制器实现:
| 01 | @Controller |
| 02 | @RequestMapping(value="/series") |
| 03 | public class SeriesController { |
| 04 |
| 05 | private SeriesService seriesService; |
| 06 |
| 07 | @Autowired |
| 08 | public SeriesController(SeriesService seriesService) { |
| 09 | this.seriesService = seriesService; |
| 10 | } |
| 11 |
| 12 | @RequestMapping(method=RequestMethod.GET) |
| 13 | @ResponseBody |
| 14 | public Series[] getAllSeries() { |
| 15 | return seriesService.getAllSeries(); |
| 16 | } |
| 17 |
| 18 | @RequestMapping(value="/{seriesId}", method=RequestMethod.GET) |
| 19 | public ResponseEntity<Series> getSeries(@PathVariable("seriesId") long id) { |
| 20 | Series series = seriesService.getSeries(id); |
| 21 |
| 22 | if (series == null) { |
| 23 | return new ResponseEntity<Series>(HttpStatus.NOT_FOUND); |
| 24 | } |
| 25 |
| 26 | return new ResponseEntity<Series>(series, HttpStatus.OK); |
| 27 | } |
| 28 |
| 29 | @RequestMapping(method=RequestMethod.POST) |
| 30 | @ResponseStatus(HttpStatus.CREATED) |
| 31 | public void insertSeries(@RequestBody Series series, HttpServletRequest request, HttpServletResponse response) { |
| 32 | seriesService.insertSeries(series); |
| 33 | response.setHeader("Location", request.getRequestURL().append("/").append(series.getId()).toString()); |
| 34 | } |
| 35 |
| 36 | @RequestMapping(value="/{seriesId}", method=RequestMethod.DELETE) |
| 37 | @ResponseStatus(HttpStatus.NO_CONTENT) |
| 38 | public void deleteSeries(@PathVariable("seriesId") long id) { |
| 39 | seriesService.deleteSeries(id); |
| 40 | } |
| 41 | } |
迁移到Spring 4
1. 改变Maven的依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
servlet 3.0改为serv;et 3.1
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
2.改变Spring名称空间:
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
3.jackson升级
原来是1.4版本:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.4.2</version>
</dependency>
现在是2.3:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.0</version>
</dependency>
代码改动:
//converters.add(new MappingJacksonHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
如果REST有JSON or XML格式,原来@ResponseBody是标注在方法上,从4.0以后可以标注在类上:
@Controller
@ResponseBody
public class SeriesController {
另外使用使用@RestController更加简化 ,只需一个 @RestController即可:
@RestController
public class SeriesController {
Spring 4.0 包含了通过AsyncRestTemplate异步调用。您可以调用以后继续做其他的计算工作,以后再查看响应。
@Test
public void getAllSeriesAsync() throws InterruptedException, ExecutionException {
logger.info("Calling async /series");
Future<ResponseEntity<Series[]>> futureEntity = asyncRestTemplate.getForEntity(BASE_URI, Series[].class);
logger.info("Doing other async stuff...");
logger.info("Blocking to receive response...");
ResponseEntity<Series[]> entity = futureEntity.get();
logger.info("Response received");
Series[] series = entity.getBody();
assertNotNull(series);
assertEquals(2, series.length);
assertEquals(1L, series[0].getId());
assertEquals("The walking dead", series[0].getName());
assertEquals("USA", series[0].getCountry());
assertEquals("Thriller", series[0].getGenre());
assertEquals(2L, series[1].getId());
assertEquals("Homeland", series[1].getName());
assertEquals("USA", series[1].getCountry());
assertEquals("Drama", series[1].getGenre());
}