JAX-RS2入门
解读REST
(Representation State Transfer)表属性状态转移,六个特点:客户端-服务器的、无状态的、可缓存的、统一接口的、分层系统和按需编码。优势:跨平台、跨语言。
REST风格将对象视为一种资源(resource)。
REST资源可寻址:
HTTP协议定义通用动词方法(GET、POST、DELETE、PUT);
URI协议唯一标识资源公布的接口。
标准:HTTP+URL+XML(XML借指数据格式),标准是基本实现格式,但是不是唯一实现形式。满足基本实现格式的不一定就是REST服务。
RESTful Web Service(REST式Web服务)
REST服务是一种面向资源你的架构(ROA)应用,特点是方法信息存在于HTTP协议中,作用域存在于URI中。(区别RPC风格:RPC将请求方式放在信封中全部采用POST方法传送,没有体现HTTP协议的优势),所以REST风格更轻量和快速。
JAX-RS2的目标
要掌握一门技术,先要掌握其背后标准的定义。(我不想掌握jesery~)
1)基于POJO;
2)以HTTP为中心;
3)格式独立性;
4)容器独立性;
5)内置于javaEE;
为什么是JERSEY?
JERSEY框架从2019年起在github上不再更新?https://github.com/jersey 但是JERSEY是JAVA领域中最纯正的REST服务开发框架。来自GlassFish项目的子项目。
JERSEY的模块
容器提供三种HTTP容器:Grizzly2、JDK-HTTP、SIMPLE-HTTP,Grizzly2同时提供Servlet容器。
快速实现Java REST服务
创建服务可以使用Jersey提供的Maven模型创建,使用IDEA创建快速启动的Jersey项目步骤如下:
GroupId:org.glassfish.jersey.archetypes
ArtifactId:jersey-quickstart-grizzly2
Version:2.22.1
创建完成后会生成如下的工程目录结构:
我们启动main方法,Jersey会启动web容器,我们根据uri访问便可完成简单的Jersey体验。
主类:
package my.restful;
import java.io.IOException;
import java.net.URI;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
/**
* Main class.
*/
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8080/myapp/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
*
* @return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in my.restful package
final ResourceConfig rc = new ResourceConfig().packages("my.restful");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.shutdown();
}
}
资源类:
package my.restful;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
@Path("myresource")
public class MyResource {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* @return String that will be returned as a text/plain response.
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
}
请求uri:http://localhost:8080/myapp/myresource
结果:
扩展——webapp
webapp在jetty容器上提供rest服务:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.restful</groupId>
<artifactId>my-first-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-first-webapp</name>
<build>
<finalName>my-first-webapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.5.v20151012</version>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<!-- uncomment this to get JSON support
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
-->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-servlet -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.22.1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
index.jsp
<html>
<body>
<h2>Jersey RESTful Web Application!</h2>
<p><a href="webapi/myresource">Jersey resource</a>
<p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
for more information on Jersey!
</body>
</html>
myResource.java
package my.restful;
import java.util.concurrent.ConcurrentHashMap;
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.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
@Path("myresource")
public class MyResource {
private static ConcurrentHashMap<String, MyDomain> map = new ConcurrentHashMap<>();
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* @return String that will be returned as a text/plain response.
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
@GET
@Path("{key}")
@Produces(MediaType.APPLICATION_XML)
public MyDomain getMy(@PathParam("key") final String key) {
final MyDomain myDomain = map.get(key);
if (myDomain == null) {
return new MyDomain();
}
return myDomain;
}
@POST
@Consumes(MediaType.APPLICATION_XML)//POST传输application/xml
public void addMy(final MyDomain myDomain) {
map.put(myDomain.getName(), myDomain);
}
}
MyDomain.java
package my.restful;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement//对象转xml
public class MyDomain {
private String name;
private String value;
public MyDomain() {
}
public MyDomain(String name, String value) {
this.name = name;
this.value = value;
}
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
测试:
无参访问:
带请求实体POST:
GET方法访问eric: