项目地址:
https://github.com/FateSolo/JSH-Test
目录:
通过上章示例可知,JAX-RS标准应属于三层架构中的表现层,与之对应的是Struts2、SpringMVC这些表现层框架。
因此,Jersey同样可以与Spring整合,享受Spring带来的全方位的便利,本章将示范整合Jersey + Spring + Spring-Data-JPA (Hibernate实现)。
1. 整合Spring
1) 打开web.xml,添加如下配置:1
2
3
4
5
6
7
8
9<!-- Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring/spring-common.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2) 添加Spring依赖:1
/**
* Jersey
*/
compile 'org.glassfish.jersey.ext:jersey-spring3:2.25.1'
/**
* Spring
*/
compile 'org.springframework:spring-web:4.3.7.RELEASE'
其中jersey-spring3是Jersey整合Spring所必需的依赖,其本身依赖jersey-container-servlet-core,因此可替换掉jersey-container-servlet-core。
3) 在resources/config/spring目录下创建Spring配置文件spring-common.xml:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<description>Spring 配置</description>
<!-- 扫描包内所有注解 -->
<context:component-scan base-package="com.fatesolo.jsh"/>
</beans>
2. 整合Spring-Data-JPA
1) 添加MySQL、Druid、Hibernate、Spring-Data-JPA依赖:1
/**
* Druid
*/
compile 'com.alibaba:druid:1.0.28'
/**
* Mysql
*/
compile 'mysql:mysql-connector-java:6.0.5'
/**
* Hibernate
*/
compile 'org.hibernate:hibernate-core:5.2.7.Final'
/**
* Spring
*/
compile 'org.springframework:spring-orm:4.3.7.RELEASE'
compile 'org.springframework:spring-web:4.3.7.RELEASE'
compile 'org.springframework.data:spring-data-jpa:1.11.1.RELEASE'
其中spring-orm在配置JPA时要用到。
2) 在resources/config/db目录下创建db.properties,配置相关信息:1
jdbc.url=jdbc:mysql://localhost:3306/jsh_test?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
druid.initialSize=5
druid.minIdle=5
druid.maxActive=50
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
3) 在spring-common.xml中配置数据源、JPA、Spring-Data-JPA:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64<!-- 引入 db.properties 配置文件 -->
<context:property-placeholder location="classpath:config/db/db.properties"/>
<!-- Druid 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${druid.initialSize}"/>
<property name="minIdle" value="${druid.minIdle}"/>
<property name="maxActive" value="${druid.maxActive}"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<property name="poolPreparedStatements" value="false"/>
</bean>
<!-- JPA -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.fatesolo.jsh.entity"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</bean>
<!-- 配置 JPA 事务 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Spring Data JPA -->
<jpa:repositories base-package="com.fatesolo.jsh.repository"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"/>
3. 编写基础代码
1) 改造实体Book,在类名上增加相关注解1
2
3
4@Entity
@Table(name = "book")
@XmlRootElement
public class Book {
在字段上增加相关注解1
2
3
4
5
6
7
8
9@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String author;
2) 建立repository子包,并创建BookRepository类:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.fatesolo.jsh.repository;
import com.fatesolo.jsh.entity.Book;
import org.springframework.data.repository.RepositoryDefinition;
import java.util.List;
@RepositoryDefinition(domainClass = Book.class, idClass = Integer.class)
public interface BookRepository {
Book findById(int id);
List<Book> findAll();
void save(Book book);
}
3) 建立service子包,并创建BookService类:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package com.fatesolo.jsh.service;
import com.fatesolo.jsh.repository.BookRepository;
import com.fatesolo.jsh.entity.Book;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class BookService {
@Resource
private BookRepository repository;
public Book getBookById(int id) {
return repository.findById(id);
}
public List<Book> getBooks() {
return repository.findAll();
}
public boolean addBook(Book book) {
repository.save(book);
return book.getId() != 0;
}
}
4) 改造资源BookResource,增加@Controller注解(事实上也可以使用@Component,在不使用SpringMVC的情况下,增加@Controller仅仅是为了将该类声明为由Spring容器管理的一个bean,以支持注入Service层),并访问service层方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40package com.fatesolo.jsh.resource;
import com.fatesolo.jsh.entity.Book;
import com.fatesolo.jsh.entity.Result;
import com.fatesolo.jsh.service.BookService;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;
@Controller
@Path("/book")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public class BookResource {
@Resource
private BookService service;
@GET
@Path("/{id}")
public Book getBookById(@PathParam("id") int id) {
return service.getBookById(id);
}
@GET
@Path("/")
public List<Book> getBooks() {
return service.getBooks();
}
@POST
@Path("/")
public Result addBook(Book book) {
return service.addBook(book) ? Result.success() : Result.failure();
}
}
4. 项目运行:
1) 使用Tomcat 8运行项目,使用curl工具添加一条数据:1
curl -H "Content-Type:application/xml" -d "<book><name>Book</name><author>Fate</author></book>" http://localhost:8080/rest/book
得到如下返回:1
2
3<result>
<code>SUCCESS</code>
</result>
2) 访问http://localhost:8080/rest/book/1 ,得到如下结果:1
2
3
4
5<book>
<author>Fate</author>
<id>1</id>
<name>Book</name>
</book>
3) 访问http://localhost:8080/rest/book ,得到如下结果:1
2
3
4
5
6
7<books>
<book>
<author>Fate</author>
<id>1</id>
<name>Book</name>
</book>
</books>
至此,Jersey + Spring + Spring-Data-JPA整合完成。
作者 [@FateSolo]
2017 年 03月 22日