迁移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());
}