Spring+Jersey+Hibernate+MySQL+HTML实现用户信息增删改查案例(附Jersey单元测试)

         Spring与Jersey整合相对比较简单,但是如果与前端进行交互,实现前后端传值,那就会遇到各种问题。本文的目的,就是详细介绍Spring与Jersey整合如何与前端数据交互。

一、Jersey简介

Jersey是JAX-RS(JSR311)开源参考实现用于构建RESTful Web service,它包含三个部分:

  核心服务器(Core Server) 通过提供JSR 311中标准化的注释和API标准化,可以用直观的方式开发RESTful Web服务。

        核心客户端(Core Client) Jersey客户端API能够帮助开发者与RESTful服务轻松通信;

        集成(Integration) Jersey还提供可以轻松继承Spring、Guice、Apache Abdera的库。

二、Jersey与Spring整合注意点

1、引入maven依赖jersey-spring,其中包含了spring的相关依赖,如果和项目中所使用的spring版本相冲突,可以通过exclusions清除掉。

2、确保jersey资源类所在的包路径,能被spring扫描到,即spring配置中的

3、确保jersey资源类打上注解@Component,这样可以注入spring容器的对象实例。

4、在web.xml中配置Spring的com.sun.jersey.spi.spring.container.servlet.SpringServlet过滤器,而不是Sevlet class。

5、Jersey与前端交互配置,如何配置避免页面不显示(空白页)。

6、前后端交互,ajax HTTP请求302错误和code 117错误原因及处理方法。

三、添加pom.xml中依赖

            如下所示为示例项目部分核心JAR包依赖,完整的pom.xml可以从本文最后提供的源码下载中获得。其中jersey-spring的maven依赖,去除了spring相关依赖。Spring与dbcp包中xerces依赖冲突,剔除。具体配置如下:

		
		
			org.springframework
			spring-core
			4.1.5.RELEASE
		
		
			org.springframework
			spring-context
			4.1.5.RELEASE
		
		
			org.springframework
			spring-orm
			4.1.5.RELEASE
		
		
			org.springframework
			spring-aop
			4.1.5.RELEASE
		
		
			org.springframework
			spring-web
			4.1.5.RELEASE
		

		
		
			org.hibernate
			hibernate-core
			4.3.11.Final
		

		
		
			mysql
			mysql-connector-java
			5.1.20
		

                
		
			commons-dbcp
			commons-dbcp
			1.2
			
				
					xerces
					xerces
				
			
		

                
		
			com.sun.jersey
			jersey-json
			1.19
		
		
			com.sun.jersey
			jersey-client
			1.19
		

		
		
			com.sun.jersey.jersey-test-framework
			jersey-test-framework-core
			1.17.1
		
		
			com.sun.jersey.jersey-test-framework
			jersey-test-framework-grizzly2
			1.17.1
		

四、配置web.xml

           web.xml配置是核心部分,通常情况下Spring与Jersey整合可以使用SpringServlet或者ServletContainer即可,但是本文需要与前端交互,这两种方式均不能够正常的显示前端页面,必须以过滤器的方式配置SpringServlet,并设置WebPageContentRegex静态页面过滤才能正常访问,并发送HTTP请求。同时,需要指定Jersey资源包路径,使得请求映射能够正确访问相应的资源类中的方法。



  
  
    index.html
  
  
  
    org.springframework.web.context.ContextLoaderListener
  
  
  
  
    contextConfigLocation
    classpath:com/spring/jersy/hibernate/config/applicationContext.xml
  
  
     
  
    org.springframework.web.util.IntrospectorCleanupListener
  
  
  
    org.springframework.web.context.request.RequestContextListener
  
  
  
  
    jerseySpring
    com.sun.jersey.spi.spring.container.servlet.SpringServlet
    
      com.sun.jersey.config.feature.Redirect
      true
    
    
      com.sun.jersey.config.feature.FilterForwardOn404
      true
    
    
    
      com.sun.jersey.config.property.WebPageContentRegex
      /(images|css|jsp|js|html)/.*
    
    
    
      com.sun.jersey.api.json.POJOMappingFeature
      true
    
    
    
      com.sun.jersey.config.property.packages
      com.spring.jersy.hibernate.resource
    
  
  
    jerseySpring
    /*
  
  
  
  
  

 
  五、配置Spring配置文件applicationContext.xml  
  

           applicationContext.xml 文件主要配置数据库连接、事务操作、注解、AOP等信息,实现Spring接管Hibernate的目的,并提供HibernateTemplate实现数据库的DAO操作。具体如下:

 jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root

applicationContext.xml内容




	
	

	
	

	
	
	
	
	
		
		
		
		
	

	
	
		
		
			
				org.hibernate.dialect.MySQLDialect
				true
			
		
		
			
				com/spring/jersy/hibernate/model/User.hbm.xml
			
		
	

	
	
		
	

	
	
		
	

	
	
		
			
			
			
			
			
		
	

	
	
	
		
		
	
六、编写Jersey资源类

           Jersey rest实现与Spring MVC的实现有很多的相似之处,具体可参考本人另一篇博文( SpringMVC Resetful+Hibernate+MySQL实现增删改查操作)。Spring使用Componet注解Jersey资源类,以实现对该类的扫描注入。

          注意:Spring整合Jersey与前端交互,将数据返回给前端时,必须手动转换相应的数据格式,如JSON,否则前端会报302错误,且前后端设置的数据格式,在数据传递时,被传递的数据格式一定要相对应。

package com.spring.jersy.hibernate.resource;

import javax.annotation.Resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import net.sf.json.JSONObject;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.spring.jersy.hibernate.model.User;
import com.spring.jersy.hibernate.service.UserService;

/**
 * Spring 使用Component注解Jersey资源类
 * Path:相当于Spring MVC中的RequestMapping,用于HTTP URL请求
 * Scope:表示Spring的单例模式或者原型模式prototype
 */
@Component
@Path("/user")
@Scope("prototype")
public class UserResource {

	@Resource(name = "userService")
	private UserService userService;
	private String message;

	/**
	 * GET:表示Jersey rest查询请求
	 * Path:此处完整路径需接类上面的Path,如:user/exist/xx/1233,才会跳转到该方法处理
	 * Consumes:表示前端请求数据格式
	 * Produces:表示返回值数据格式
	 * PathParam:用于注解参数变量,与URL中对应的变量名对应,达到传递的作用
	 */
	@GET
	@Path("/exist/{username}/{password}")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	//查询
	public String isExist(@PathParam("username") String username,
			@PathParam("password") String password) {

		User user = new User();
		user.setUsername(username);
		user.setPassword(password);
		User result = userService.findUserByNameAndPassword(user);
		
		/**
		 * Spring+Jersey框架,不会主动帮助我们将传递的对象转换成JSON数据格式,
		 * 需使用JSON lib类中的JSONObject或者JSONArray转换才能够传递,否则前端
		 * 会报302错误。
		 */
		JSONObject jsonUser = JSONObject.fromObject(result);
		return jsonUser.toString();
	}

	@POST
	@Path("/addUser")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	//添加
	public String addUser(User user) {

		boolean flag = userService.addUser(user);
		if (flag) {
			message = "success";
		} else {
			message = "fail";
		}
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("message", message);
		return jsonObject.toString();
	}

	@DELETE
	@Path("/deleteUser/{id}")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	//删除
	public String deleteUser(@PathParam("id") Integer id) {

		boolean flag = userService.deleteUser(id);
		if (flag) {
			message = "success";
		} else {
			message = "fail";
		}
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("message", message);
		return jsonObject.toString();
	}

	@PUT
	@Path("/updateUser/{id}")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	//修改
	public String updateUser(@PathParam("id") Integer id, User user) {
		user.setId(id);
		boolean flag = userService.updateUser(user);
		if (flag) {
			message = "success";
		} else {
			message = "fail";
		}
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("message", message);
		return jsonObject.toString();
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}
}
七、编写业务逻辑处理类

此处的业务逻辑处理相对比较简单,此处使用Spring的@Service注解业务逻辑,使用@Resource注解使用Spring注解的userDao bean实例。

package com.spring.jersy.hibernate.service;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.spring.jersy.hibernate.dao.UserDao;
import com.spring.jersy.hibernate.model.User;

@Service(value="userService")
public class UserService {

	@Resource(name="userDao")
	private UserDao userDao;
	
	public User findUserByNameAndPassword (User user) {
		List listUsers = userDao.findByNameAndPassword(user);
		
		if(listUsers.size() > 0) {
			return listUsers.get(0);
		}
		return null;
	}
	
	public User findUserByName (String name) {
        List listUsers = userDao.findUserByName(name);
		if(listUsers.size() > 0) {
			return listUsers.get(0);
		}
		return null;
	}
	
	public boolean deleteUser(Integer id) {
		return userDao.deleteUser(id);
	}
	
	public boolean addUser(User user) {
		return userDao.addUser(user);
	}
	
	public boolean updateUser(User user){
		return userDao.updateUser(user);
	}
	public UserDao getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
}
八、编写Dao操作类

            Dao操作类中主要使用Spring提供的Hibernate Dao操作模型—HibernateTemplate,该类能够实现Hibernate中的各种CRUD操作,使得开发人员无需关注非业务逻辑的实现。@Resource(name="hibernateTemplate")表示使用Spring已经注入的hibernateTemplate,该类注入是在applicationContext.xml文件中配置的。

package com.spring.jersy.hibernate.dao;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Repository;
import com.spring.jersy.hibernate.model.User;

@Repository(value="userDao")
public class UserDao {

	@Resource(name="hibernateTemplate")
	private HibernateTemplate hibernateTemplate;
	
	//根据用户名和密码查询
	public List  findByNameAndPassword (User user) {
	   String queryString = "from User where username = :username and password = :password";
	   String paramNames[] = {"username" , "password"};
	   String paramValues[] = {user.getUsername(),user.getPassword()};
	   
	   @SuppressWarnings("unchecked")
	   List listUsers = (List) hibernateTemplate.findByNamedParam(queryString, paramNames, paramValues);
       return listUsers;		
	}
	
	//根据姓名查询
	@SuppressWarnings("unchecked")
	public  List findUserByName(String name) {
		List userList = new ArrayList();
		String queryString = "from User where username like:name";
		userList = (List) hibernateTemplate.findByNamedParam(queryString,"name",name);
        return userList;
	}
	
	//添加用户
	public boolean  addUser(User user) {
	    try {
	    	hibernateTemplate.save(user);   
		} catch (Exception e) {
           return false;			
		}
	    return true;
	}
	
	//删除用户
	public boolean deleteUser(Integer id) {
		try {
			User user = hibernateTemplate.get(User.class, id);
			hibernateTemplate.delete(user);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	//修改用户信息 
	public boolean updateUser(User user){
		try {
			User updateUser = hibernateTemplate.get(User.class, user.getId());
			updateUser.setUsername(user.getUsername());
			updateUser.setPassword(user.getPassword());
			updateUser.setAddress(user.getAddress());
			updateUser.setTel(user.getTel());
			
			hibernateTemplate.update(updateUser);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
}
九、html前端请求内容

           传统的Struts2、Spring MVC都默认为前端传值转换成以JSON方法传到后台,但是Spring+Jersey没有实现(本人在此处载了跟头),需要在前端使用JSON.stringify(data)转换后再传输,否则会报code 117代码错误。




MyHtml.html











访问REST GET服务

返回值:

访问REST POST服务

用户名:   密码:  

地址:   联系方式:  

返回值:

访问REST PUT服务

用户名:   密码:   

地址:   联系方式:   

返回值:

访问REST Delete服务

请输入:   返回值:

十、Demo页面展示

Spring+Jersey+Hibernate+MySQL+HTML实现用户信息增删改查案例(附Jersey单元测试)_第1张图片

附1:Jersey单元测试

Jersey单元测试必须添加jersey-test-framework-core测试依赖,所有单元测试必须继承JerseyTest,具体如下:

package com.spring.jersy.hibernate.test;

import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;

/**
 * 主要加载web.xml中的配置信息
 * @author Administrator
 *
 */
public abstract class BaseJerseyServiceTest extends JerseyTest {
	    @Override
	    protected WebAppDescriptor configure() {
	        return  new WebAppDescriptor.Builder("com.spring.jersy.jpa.hibernate.resource")
	        .contextParam( "contextConfigLocation", "classpath:com/spring/jersy/hibernate/config/applicationContext.xml")
	        //.servletClass(SpringServlet.class)
	        .filterClass(SpringServlet.class)
	        .initParam("com.sun.jersey.config.feature.Redirect", "true")
	        .initParam("com.sun.jersey.config.feature.FilterForwardOn404", "true")
	        .initParam("com.sun.jersey.config.property.WebPageContentRegex", "/(images|css|jsp|html|)/.*")
	        .initParam("com.sun.jersey.api.json.POJOMappingFeature", "true")
	        .initParam("com.sun.jersey.config.property.packages", "com.spring.jersy.jpa.hibernate.resource")
	        .contextListenerClass(ContextLoaderListener.class)
	        .requestListenerClass(RequestContextListener.class)
	        .build();
	    }
}
package com.spring.jersy.hibernate.test;

import javax.ws.rs.core.MediaType;
import org.junit.Before;
import org.junit.Test;
import com.spring.jersy.hibernate.model.User;
import com.sun.jersey.api.client.WebResource;

/**
 * 继承BaseJerseyServiceTest类,获得相应的web.xml配置信息
 * @author Administrator
 *
 */
public class UserResourceTest extends BaseJerseyServiceTest {

	private WebResource webResource;

	@Before
	public void setUp() throws Exception {
		webResource = resource();
	}

	@Test
	public void testIsExist() {
		String response = webResource.path("/user/exist/xx/1233").get(
				String.class);
		System.out.println(response);
	}

	@Test
	public void testAddUser() {

		User user = new User();
		user.setUsername("wwwx");
		user.setPassword("pwd");
		user.setAddress("江苏盐城");
		user.setTel("12333");
		String response = webResource.path("/user/addUser")
				.entity(user, "application/json").post(String.class, user);
		System.out.println(response.toString());
	}

	@Test
	public void testDeleteUser() {
		String response = webResource.path("/user/deleteUser/59").delete(
				String.class);
		System.out.println(response.toString());
	}

	@Test
	public void testUpdateUser() {
		User user = new User();
		user.setUsername("王三儿");
		user.setPassword("wangsaner");
		String response = webResource.path("/user/updateUser/64")
				.entity(user, MediaType.APPLICATION_JSON).put(String.class);
		System.out.println(response.toString());
	}
}

附2:前后端交互异常处理

     前端传值:code 117

Unexpected character ('u' (code 117)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
          解决办法:前端传值必须转换成JSON传递。因为Spring或者Jersey rest均不提供默认的注入。springMVC可以直接传递值。

          后端返回值:前端发送请求,后台处理后,执行状态无法返回,且报304错误。

GET /springjersyjpahibernate/jquery.min.js HTTP/1.1" 304 
         解决办法:前后端数据传递格式要一致,如:前端设置返回数据格式为JSON,后台则必须将数据转换成JSON形式进行传输,包括字符串也要转换。可以json-lib

        Jar包版本冲突:JSON lib依赖的以下几种Jar包版本冲突

Spring+Jersey+Hibernate+MySQL+HTML实现用户信息增删改查案例(附Jersey单元测试)_第2张图片

com.google.common.collect.Sets.newIdentityHashSet()Ljava/util/Set

附3:完整源码下载

Spring+Jersey+Hibernate+MySQL+HTML实现用户信息CRUD案例源码

           

//结束











你可能感兴趣的:(Spring)