也是搞了很久,才搞定这个整合,之前在网上搜索的例子都比较简单,自己也是花了很久才整合到一起去,努力就会有收获,共勉。
本文包含jersey+spring+mybatis,包括json转换,bean的注入,事物处理。
本文例子业务逻辑是用户注册和按照用户ID查询。
环境:
eclipse4.4,jersey2.x,spring3.x
jdk7,(最好使用jdk7,因为jersey2.xjar包用jdk7编译的,本文使用的spring3.x,jdk8支持不够好,本人开始使用的jdk8,程序会启动报错)
完整的例子代码下载,需要1分了,求散分:http://download.csdn.net/detail/u013374450/9086861
首先用户实体类,很简单,只需要使用jersey注解即可,便于使实体进行json或xml转换,如
package com.xiao.bean;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 基础user实体类,只包括公共基础属性
* @author xyc
*
*/
@XmlRootElement
public class User implements Serializable{
private int id;
private String userName;
private String pwd;
private String phone;
private String email;
public int getId() {
return id;
}
@XmlAttribute(name = "id")
public void setId(int id) {
this.id = id;
}
public String getPhone() {
return phone;
}
@XmlAttribute(name = "phone")
public void setPhone(String phone) {
this.phone = phone;
}
public String getUserName() {
return userName;
}
@XmlAttribute(name = "userName")
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
@XmlAttribute(name = "email")
public void setEmail(String email) {
this.email = email;
}
public String getPwd() {
return pwd;
}
@XmlAttribute(name = "pwd")
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User [id=" + id + ", phone=" + phone + ", userName=" + userName
+ ", email=" + email + ", pwd=" + pwd + "]";
}
}
数据持久层,使用mybatis,所以dao类继承了SqlSessionDaoSupport,dao类实现类如下,和一般的mybatis集成spring写法一致,没什么区别
package com.xiao.dao.impl;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.stereotype.Repository;
import com.xiao.bean.User;
import com.xiao.dao.UserDao;
@Repository("userDao")
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{
@Override
public int insertUser(User user) throws Exception {
this.getSqlSession().insert("com.xiao.dao.UserDao.insertUser", user);
return 0;
}
@Override
public User selectById(int id) throws Exception {
User user = this.getSqlSession().selectOne("com.xiao.dao.UserDao.getById", id);
return user;
}
}
接下来是service层,本文采用的xml方式进行事物管理,所以没有太多的注解,spring已经不推荐使用@Autowired注解,推荐使用@resource注解.主要代码如下:
package com.xiao.service.impl;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xiao.base.Constants;
import com.xiao.bean.User;
import com.xiao.dao.UserDao;
import com.xiao.service.UserService;
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource(name="userDao")
private UserDao userDao;
@Override
public int insertUser(User user) throws Exception {
this.userDao.insertUser(user);
//方法发生异常的时候,数据会回滚
// System.out.println(9/0);
return Constants.RESULT_STATUS_SUCCESS;
}
@Override
public User getById(int id) throws Exception {
return this.userDao.selectById(id);
}
}
接下来就是jersey相关的resource层了,jersey或者rest风格的架构都是将服务器数据作为资源,所以资源就会有增post,删delete,查get,改put等状态,也是对应了http请求的方式。主要代码如下
package com.xiao.resource;
import javax.annotation.Resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.springframework.stereotype.Component;
import com.xiao.base.Constants;
import com.xiao.bean.User;
import com.xiao.service.UserService;
/**
* 资源类
* @author xyc
* 2015年9月7日19:44:56
*/
@Component
@Path("/user")
public class UserResource {
@Resource(name="userService")
private UserService userService;
/*
* 注册
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
public int insertUser(User user) throws Exception {
return userService.insertUser(user);
}
/*
* 查询
*/
@GET
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
public User getById(@PathParam("id") int id) throws Exception {
return userService.getById(id);
}
}
本文使用的是json方式,那么jersey原生是不能直接发送和接收json数据的,这时候需要注册一个json转换器,同时还要注册需要处理json所在的类,一般就是资源类,主要代码如下:
package com.xiao.server.rest;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.glassfish.jersey.server.ResourceConfig;
import com.xiao.resource.UserResource;
/**
* 该类是注册jackjson,使发送数据转换成json,接收的json转换成对象
* @author xyc
*
*/
public class RestApplication extends ResourceConfig{
public RestApplication(){
register(UserResource.class);
register(JacksonJsonProvider.class);
}
}
至此,主要的java代码就算完成了,下面是配置文件,首先是spring的配置
<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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 扫描包 -->
<context:component-scan base-package="com.xiao" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:com/xiao/config/mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/xiao/config/mappings/*.xml" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="dataSource" /></property>
<property name="rollbackOnCommitFailure" value="true" />
</bean>
<!-- 采用声明式编程方式来实现事物控制 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- propagation定义事物传播行为, isolation定义事物隔离级别, rollback-for需要触发回滚的异常定义 -->
<tx:method name="batch*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="insert*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="upload*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="Exception" />
<!-- 登陆方法 -->
<tx:method name="login*" propagation="REQUIRED" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 添加事物 -->
<aop:config>
<aop:pointcut id="appAop" expression="execution(* com.xiao.service..*.*(..))" />
<aop:advisor pointcut-ref="appAop" advice-ref="txAdvice"/>
</aop:config>
<bean id="userDao" class="com.xiao.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory">
<ref bean="sqlSessionFactory" />
</property>
</bean>
</beans>
关于userDao的注入是本文一个疑惑的地方,service的注入是通过扫描包自动注入的,而userDao却不能注入成功,所以采用了手动的方式。
最后是web.xml的配置,
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<module-name></module-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationConfig/applicationContext-datasource.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.xiao.server.rest.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
至此,所有代码完成。测试方法如下:
package com.xiao.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import com.xiao.bean.User;
/**
* 测试类
* @author xyc
*
*/
public class UserClient {
private static String serverUri = "http://localhost/spring-jersey/rest";
public static void main(String[] args) {
// register();
getById(14);
}
/**
* 添加,post请求,同修改,使用json提交数据
*/
private static void register(){
User user = new User();
user.setPhone("1890998765");
user.setEmail("235qeq@qq.com");
user.setPwd("zxcvb");
user.setUserName("asdfg");
Client client = ClientBuilder.newClient().register(JacksonJsonProvider.class);
WebTarget target = client.target(serverUri + "/user");
Response response = target.request().buildPost(Entity.entity(user, MediaType.APPLICATION_JSON)).invoke();
System.out.println(response.getStatus());
response.close();
}
/**
* 按照ID查询
* @param id
*/
private static void getById(int id){
// 注册json 支持
Client client = ClientBuilder.newClient().register(JacksonJsonProvider.class);
WebTarget target = client.target(serverUri + "/user/" + id);
Response response = target.request().get();
//返回json数据
User user = response.readEntity(User.class);
System.out.println(user);
response.close();
}
}