REST (4) RESTEasy implements REST

RESTEasy is an open source project from JBoss that provides various frameworks to help you build RESTful Web Services and RESTful Java applications. It is a complete implementation of the JAX-RS specification and certified by JCP. As a JBOSS project, it certainly integrates well with the JBOSS application server. However, it will also run in any servlet container running JDK5 or above. RESTEasy also provides a RESTEasy JAX-RS client invocation framework. Can be easily integrated with EJB, Seam, Guice, Spring and Spring MVC. Supports automatic GZIP decompression on client and server.

For other RESTEasy introductions, see the official website: http://resteasy.jboss.org/ . This section briefly introduces the integration and client access of RESTEasy2+spring4.

1. For the basic environment
of spring web, see the web project testRest created in the previous chapter.

2. The REST address
is similar to the previous section, design the RESTEasy module /resteasy/*.

3. The RESTEasy library
adds RESTEasy dependencies to the project pom.xml:
<properties>
	<!-- resteasy high version requires jdk1.8, use low version-->
	<resteasy.version> 3.0.0.Final </resteasy.version>
</properties>
<dependencies>	
	...
	<! - resteasy begin ->
	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId> resteasy-jaxrs </artifactId>
		<version>${resteasy.version}</version>
	</dependency>
	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId> resteasy-client </artifactId>
		<version>${resteasy.version}</version>
	</dependency>
	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId> resteasy-spring </artifactId>
		<version>${resteasy.version}</version>
	</dependency>
	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId> resteasy-jackson-provider </artifactId>
		<version>${resteasy.version}</version>
	</dependency>
	<! - resteasy end ->
	...

Version uses 3.0.0.Final because newer versions require jdk1.8 to run.

4. Servlet
configures RESTEasy access entry.
<! - resteasy ->
<context-param>
	<param-name>resteasy.resources</param-name>
	<param-value>
		com.sunbin.test.resteasy.TeachersResource, com.sunbin.test.resteasy.TeacherResource
	</param-value>
</context-param>
<context-param>
	<param-name>resteasy.servlet.mapping.prefix</param-name>
	<param-value>/resteasy</param-value>
</context-param>
<listener>
	<listener-class> org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap </listener-class>
</listener>
<servlet>
	<servlet-name>resteasy</servlet-name>
	<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>resteasy</servlet-name>
	<url-pattern>/resteasy/*</url-pattern>
</servlet-mapping>

resteasy Servlet will intercept all accesses under /resteasy/*.
After RESTEasy is integrated with web and spring, there is no need to implement components such as Application and Component, and no configuration file is required for path configuration, only @Path annotation is required.

5. Implement the api to
create a new com.sunbin.test.resteasy package, and add the TeachersResource class to implement the interface of the /teachers path:
package com.sunbin.test.resteasy;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.springframework.beans.factory.annotation.Autowired;

import com.sunbin.test.teacher.pojo.Teacher;
import com.sunbin.test.teacher.service.TeacherService;

@Path("/teachers")
@Produces(MediaType.APPLICATION_JSON)
public class TeachersResource {

	@Autowired
	private TeacherService teacherService;

	@GET
	public Map get() {
		System.out.println("Resteasy TeachersResource.get");
		Map map = new HashMap();
		map.put("teachers", teacherService.list());
		return map;
	}

	@POST
	public Map post(@FormParam("age") int age, @FormParam("name") String name) {
		Map map = new HashMap();
		try {
			Teacher teacher = new Teacher();
			teacher.setName(name);
			teacher.setAge(age);
			System.out.println ("Resteasy TeachersResource.post:" + teacher);
			teacherService.save(teacher);
			map.put("status", "y");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace ();
		}
		return map;
	}

}

Path annotation @Path, return type annotation @Produces, access method @GET, parameter read @FormParam are the same as Jersey's JAX-RS.

After redeploying the project, visit http://localhost:8080/testRest/resteasy/teachers and find an error:
java.lang.NullPointerException
com.sunbin.test.resteasy.TeachersResource.get(TeachersResource.java:29)
After checking, it is found that The teacherService in the teacherService.list() statement is null, and the @Autowired annotation does not take effect.
Trying to use the xml configuration method to achieve teacherService injection, or using the jsr specification's own @Inject and @Resource annotations will not work.

Why is this happening? The analysis is because of the problem of dependency injection between RESTEasy and spring's beanfactory.
The RESTEasy official website manual recommends the following two solutions:
1. Obtain the ApplicationContext object through the WebApplicationContextUtils tool class
2. Customize the tool
class See my previous article for details: spring4 learning (3) Obtaining beans in non-Spring classes

for easy injection, The second method is adopted here: define the Context tool class SpringContextHolder and configure it to spring. After that, the Resource class needs to be transformed:
package com.sunbin.test.resteasy;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.sunbin.common.spring.SpringContextHolder;
import com.sunbin.test.teacher.pojo.Teacher;
import com.sunbin.test.teacher.service.TeacherService;

@Path("/teachers")
@Produces(MediaType.APPLICATION_JSON)
public class TeachersResource {

	private TeacherService teacherService;

	public TeachersResource() {
		super();
		// Cannot be injected automatically, you need to manually assign getBean assignments
		teacherService = (TeacherService) SpringContextHolder
				.getBean("teacherService");
		// TODO Auto-generated constructor stub
	}

	@GET
	public Map get() {
		System.out.println("Resteasy TeachersResource.get");
		Map map = new HashMap();
		map.put("teachers", teacherService.list());
		return map;
	}

	@POST
	public Map post(@FormParam("age") int age, @FormParam("name") String name) {
		Map map = new HashMap();
		try {
			Teacher teacher = new Teacher();
			teacher.setName(name);
			teacher.setAge(age);
			System.out.println ("Resteasy TeachersResource.post:" + teacher);
			teacherService.save(teacher);
			map.put("status", "y");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace ();
		}
		return map;
	}

}

In the constructor of the TeachersResource class, manually obtain the Bean through the SpringContextHolder, and then assign it to the resource.

Similarly, add the TeacherResource class to implement the interface of the /teacher/{id} path:
package com.sunbin.test.resteasy;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
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 com.sunbin.common.spring.SpringContextHolder;
import com.sunbin.test.teacher.pojo.Teacher;
import com.sunbin.test.teacher.service.TeacherService;

@Path("teacher/{id}")
@Produces(MediaType.APPLICATION_JSON)
public class TeacherResource {

	private TeacherService teacherService;

	public TeacherResource() {
		super();
		teacherService = (TeacherService) SpringContextHolder
				.getBean("teacherService");
		// TODO Auto-generated constructor stub
	}

	@GET
	public Map get(@PathParam("id") int id) {
		System.out.println("Resteasy TeacherResource.get:" + id);
		Teacher teacher = new Teacher();
		teacher.setId(id);
		Map map = new HashMap();
		map.put("teacher", teacherService.get(teacher));
		return map;
	}

	@PUT
	public Map put(@PathParam("id") int id, @FormParam("age") int age,
			@FormParam("name") String name) {
		Map map = new HashMap();
		try {
			Teacher teacher = new Teacher();
			teacher.setId(id);
			teacher.setName(name);
			teacher.setAge(age);
			System.out.println("Resteasy TeacherResource.put:" + id + ":"
					+ teacher);
			teacherService.update(teacher);
			map.put("status", "y");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace ();
		}
		return map;
	}

	@DELETE
	public Map delete(@PathParam("id") int id) {
		Map map = new HashMap();
		try {
			System.out.println("Resteasy TeacherResource.delete:" + id);
			Teacher teacher = new Teacher();
			teacher.setId(id);
			teacherService.remove(teacher);
			map.put("status", "y");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace ();
		}
		return map;
	}

}


6.js test
Use the test page src\main\webapp\rest\index.jsp in the previous section to test:
...
	<script type="text/javascript">
		// test framework
		//var restType = "jersey";
		//var restType = "restlet";
		var restType = "resteasy";
		//var restType = "restCxf";
		//var restType = "restMvc";
...

After redeploying, use a browser to visit http://localhost:8080/testRest/rest , the test content is the same as the Restlet test.

7. RESTEasy Client test
RESTEasy provides the Client library for testing the REST interface.
Create a new TestResteasy class with the following code:
package com.sunbin.test.resteasy;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;

import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;

public class TestResteasy {

	public static final String URL_BASE = "http://localhost:8080/testRest/resteasy/";

	public static void main(String[] args) {
		ResteasyClient client = new ResteasyClientBuilder (). Build ();
		String module = "teacher";
		String url = "";
		String result = "";
		Entity<Form> entity = null;
		Form form = null;
		ResteasyWebTarget baseTarget = client.target (URL_BASE);
		ResteasyWebTarget target = null;

		url = URL_BASE + module + "s";
		System.out.println("get\t" + url);
		target = baseTarget.path(module + "s");
		result = target.request().get(String.class);
		System.out.println(result);

		url = URL_BASE + module + "s";
		System.out.println("post\t " + url);
		target = baseTarget.path(module + "s");
		form = new Form().param("age", "1").param("name", "a");
		entity = Entity.form(form);
		result = target.request().post(entity, String.class);
		System.out.println(result);

		url = URL_BASE + module + "s";
		System.out.println("get\t" + url);
		target = baseTarget.path(module + "s");
		result = target.request().get(String.class);
		System.out.println(result);

		url = URL_BASE + module + "/1";
		System.out.println("get\t " + url);
		target = baseTarget.path(module + "/1");
		result = target.request().get(String.class);
		System.out.println(result);

		url = URL_BASE + module + "/1";
		System.out.println("put\t " + url);
		target = baseTarget.path(module + "/1");
		form = new Form().param("age", "11").param("name", "aa");
		entity = Entity.form(form);
		result = target.request().put(entity, String.class);
		System.out.println(result);

		url = URL_BASE + module + "s";
		System.out.println("get\t" + url);
		target = baseTarget.path(module + "s");
		result = target.request().get(String.class);
		System.out.println(result);

		url = URL_BASE + module + "/1";
		System.out.println("delete\t " + url);
		target = baseTarget.path(module + "/1");
		result = target.request().delete(String.class);
		System.out.println(result);

		url = URL_BASE + module + "s";
		System.out.println("get\t" + url);
		target = baseTarget.path(module + "s");
		result = target.request().get(String.class);
		System.out.println(result);
	}
}

The test results are similar to Restlet.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326618935&siteId=291194637