1. 编写目的
本文档用于描Spring+Jersey框架的搭建Rest服务的过程及其注意事项。主要介绍环境配置、Spring框架配置、Jersey与Spring的集成配置,以及前端Ajax的调用Demo。
2. 环境配置
2.1. 开发工具配置
下表所列开发工具都安装到D:\DEVTOOLS下,其他工具自定安装位置。
类别 | 工具 |
集成编程环境 | STS2.5(Eclipse+Spring Tools) |
JavaScript | Spket1.68(插件) |
SVN插件 | SubEclipse(插件) |
Flex开发环境 | FlashBuilder_4_Plugin |
JDK | JDK 6.0 |
J2EE 应用服务器 | Tomcat6 |
WebLogic10 | |
数据库 | Oracle10.2 |
数据库工具 | PL/SQL Developer |
2.2. 环境变量
JAVA_HOME= D:\ DEVTOOLS\JDK
CATALINA_HOME= D:\DEVTOOLS\Tomcat
2.3. 系统环境
操作系统:WindowsXP
内存:2G以上
硬盘:80G以上
CPU:2.7GHz以上
2.4. 配置字符集
-
右键点击工程,选择属性。
-
在属性框的info中配置该工程的文本文件编码位UTF-8。
-
也可以给整个工作区设置整体字符集,在工作空间上设置UTF-8,如下图:
2.5. 配置JDK
1)选择“窗口 | 首选项…”菜单,进入配置界面。
2)在java-〉编译器下,配置编译器jdk 6.0
3)在java-〉JRE下配置JDK6.0
2.6. Tomcat配置
-
选择“窗口 | 首选项…”菜单,进入配置界面。
-
在Eclipse下选择Server,配置Tomcat路径以及JDK等。
3)启用Tomcat6
3. 框架搭建过程
3.1. 创建Java Web工程
启动STS程序,选择新建Dynamic Web Project项目,作为框架的Web工程项目,如下图:
并将所依赖的Jar包放入工程的WebRoot\WEB-INF\lib目录下面,主要是Spring相关Jar包、Jersey相关Jar包,其他依赖包自行加入。
Spring所依赖的Jar包:
Jersey所依赖的Jar包:
3.2. 配置Java Web项目的Web.xml
配置JAVA Web工程中WebRoot/WEB-INF/web.xml
<!--Spring配置文件的路径,可使用通配符,多个路径用逗号分隔-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/applicationContext*.xml</param-value>
</context-param>
<!--CharacterEncoding filter(字符集拦截转换)-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Spring的ApplicationContext 载入-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!—定义Jersey的拦截器-->
<servlet>
<servlet-name>JerseyServlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JerseyServlet</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
配置Jersey的拦截器,并指定容器为Spring,拦截所有经过rs的服务。
3.3. 创建Spring配置文件applicationContext.xml
在Web.xml中配置的Spring配置文件,需要在src或者src/resource目录中建立applicationContext.xml,如果在src/resource目录下面建立,需要把resource目录作为源代码路径,目的是使applicationContext.xml可以输出到WebRoot\WEB-INF\CLASSES目录下面;
applicationContext.xml配置文件的内容如下:
<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns=http://www.springframework.org/schema/beansxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p=http://www.springframework.org/schema/pxmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-lazy-init="true"default-autowire="byName">
<description>Spring公共配置文件</description>
<!-- property-placeholder是一个属性遍历器,定位一个属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 使用annotation自动注册bean,并检查@Required,@Autowired的属性已被注入 -->
<context:component-scan base-package="com.geoweb"/>
<!-- 数据源配置,使用应用内的DBCP数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<!-- ConnectionInfo -->
<property name="driverClassName"value="${jdbc.driver}" />
<property name="url"value="${jdbc.url}" />
<property name="username"value="${jdbc.username}" />
<property name="password"value="${jdbc.password}" />
<!-- ConnectionPooling Info
<propertyname="initialSize" value="${dbcp.initialSize}" />
<propertyname="maxActive" value="${dbcp.maxActive}" />
<propertyname="maxIdle" value="${dbcp.maxIdle}" />
<propertyname="defaultAutoCommit" value="false" />-->
</bean>
<!-- 事务配置-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
</beans>
3.4. Jersey的介绍和配置
Representational state transfer(REST)在2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一。但是,在 Java™ 社区中,直到 2008 年JSR 311(JAX-RS) 规范定稿后才将其标准化。第一个版本的参考实现甚至更晚。Jersey—JSR 311 的参考实现,描述其必要的API和注释。我将展示如何通过在Apache Tomcat中集成Jersey从 servlet风格的服务转型到RESTful服务。
REST 中最重要的概念是资源(resources),使用全球 ID(通常使用 URI)标识。客户端应用程序使用 HTTP 方法(GET/ POST/ PUT/ DELETE)操作资源或资源集。RESTful Web服务是使用HTTP和REST原理实现的Web服务。通常,RESTful Web服务应该定义以下方面:
Web 服务的基/根URI,比如http://host/<appcontext>/resources。
支持 MIME 类型的响应数据,包括:JSON/XML/ATOM等等。
服务支持的操作集合(例如:POST、GET、PUT 或 DELETE)。
方法/ 资源 | 资源集合, URI 如:http://host/<appctx>/rs | 成员资源,URI 如:http://host/<appctx>/rs/1 |
GET | 列出资源集合的所有成员。 | 检索标识为1的资源的表示形式。 |
PUT | 使用一个集合更新(替换)另一个集合。 | 更新标记为1的数字资源。 |
POST | 在集合中创建数字资源,其 ID 是自动分配的。 | 在下面创建一个子资源。 |
DELETE | 删除整个资源集合。 | 删除标记为1的数字资源。 |
Jersey的配置全部基于注解,实体类与XML、JSON之间的转换,rest服务的发布,相关参数的配置等都可以基于注解完成,下面简要介绍使用到的注解:
-
注释(Annotation):在 javax.ws.rs.* 中定义,是 JAX-RS (JSR 311) 规范的一部分。
-
@Path:定义资源基URI。由上下文根和主机名组成,资源标识符类似于http://localhost:8080/Jersey/rest/contacts。
-
@GET:这意味着以下方法可以响应 HTTP GET 方法。
-
@Produces:以纯文本方式定义响应内容 MIME 类型。
-
@Context: 使用该注释注入上下文对象,比如 Request、Response、UriInfo、ServletContext 等。
-
@Path("{contact}"):这是 @Path 注释,与根路径 “/contacts” 结合形成子资源的 URI。
-
@PathParam("contact"):该注释将参数注入方法参数的路径,就是id。其他可用的注释有@FormParam、@QueryParam 等。
-
@Consumes:声明该方法使用 HTML FORM。
-
@FormParam:注入该方法的 HTML 属性确定的表单输入。
-
@Response.created(uri).build():构建新的 URI 用于新创建的联系人(/contacts/{id}) 并设置响应代码(201/created)。您可以使用 http://localhost:8080/Jersey/rest/contacts/<id> 访问新联系人。
HTTP 方法映射到资源的 CRUD(创建、读取、更新和删除) 操作。尽管您可以做一些小修改,比如让 PUT 方法变成创建或更新,但基本的模式如下:
-
HTTP GET:获取/列出/检索单个资源或资源集合。
-
HTTP POST:新建资源。
-
HTTP PUT:更新现有资源或资源集合。
-
HTTP DELETE:删除资源或资源集合。
4. 框架应用
4.1. 创建Java服务器端应用
首先在Web工程中新建一个实体类,JAX-RS 支持使用 JAXB (Java API for XML Binding) 将 JavaBean 绑定到 XML 或 JSON,反之亦然。JavaBean必须使用@XmlRootElement,没有明确 @XmlElement 注释的字段将包含一个名称与之相同的 XML 元素,注释实体类,如下:
@XmlRootElement
public class Role {
private String name;
private List<Authority> authorityList = Lists.newArrayList();
public Role() {
}
public Role(Long id, String name) {
this.id = id;
this.name = name;
}
@Column(nullable = false, unique = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setAuthorityList(List<Authority> authorityList) {
this.authorityList = authorityList;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
使用注解发布Rest服务,如下:
@Component
@Path("/users")
public class UserResourceService {
private static Logger logger = LoggerFactory.getLogger(UserResourceService.class);
@Context
private UriInfo uriInfo;
@Autowired
private AccountManager accountManager;
/**
* 获取所有用户.
*/
@GET
@Produces({ MediaType.APPLICATION_JSON })
public List<User>getAllUser() {
try {
List<User>entityList = accountManager.getAllLoadedUser();
return entityList;
} catch (RuntimeException e) {
logger.error(e.getMessage(),e);
throw newWebApplicationException();
}
}
/**
* 获取用户.
* @throws IOException
*/
@GET
@Path("{id}")
@Produces({ MediaType.APPLICATION_JSON })
public User getUser(@PathParam("id") Long id) {
try {
User entity =accountManager.getUser(id);
return entity;
} catch(ObjectNotFoundException e) {
Stringmessage = "用户不存在(id:" + id + ")";
logger.error(message, e);
throw buildException(Status.NOT_FOUND, message);
} catch (RuntimeException e) {
logger.error(e.getMessage(),e);
throw newWebApplicationException();
}
}
}
可以使用http://localhost:8088/geoweb/rs/users/1 获取ID为1的用户,可以使用Ajax调用,可以使用Flex等Ria客户端调用,也在cs中程序中进行调用。
4.2. Ajax调用Rest服务User
对于所有JAVA工程发布的Rest服务,使用Ajax都可以进行调用,此处使用jQuery提供的$.getJSON()方法来调用发布的Rest服务,例如:
$.getJSON('http://localhost/geoweb/rs/users/1','',function(json){
alert(json);
});
服务调用成功后,会输出服务返回的用户对象的JSON文件。