viruela.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>jersey-web-learn</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 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.23.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<!--支持HttpServletRequest、ServletContext、HttpServletResponse-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!--json-->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.ext/jersey-mvc-freemarker -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-freemarker</artifactId>
<version>2.23.2</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<build>
<plugins>
<!-- tomcat maven 插件 -->
<!-- <plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>-->
</plugins>
</build>
</project>
y web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>jerseyServlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.itheima.config.ApiResourceConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jerseyServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
ApiResourceConfig.java
package com.itheima.config;
import com.itheima.controller.MyTest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
import javax.ws.rs.ApplicationPath;
public class ApiResourceConfig extends ResourceConfig {
public ApiResourceConfig() {
// 配置 FreeMarker 模板引擎
property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/views");
register(FreemarkerMvcFeature.class);
// 注册 Jersey 资源类
register(MyTest.class);
}
}
1. Primeros pasos
controlador
package com.itheima.controller;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/person")
public class PersonResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String get(){
return "GET Person resource";
}
}
Clase de configuración
package com.itheima.config;
import com.itheima.controller.PersonResource;
import org.glassfish.jersey.server.ResourceConfig;
//配置类,配置这个项目有什么资源
public class ApiResourceConfig extends ResourceConfig {
public ApiResourceConfig() {
register(PersonResource.class);
}
}
Configuración del controlador frontal web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>jerseyServlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.itheima.config.ApiResourceConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jerseyServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
2. Notas
1、@Ruta
@Path("/person")
public class PersonResource {
@GET
@Path("{id}")
@Produces(MediaType.TEXT_PLAIN)
public String get(@PathParam("id") Long id){
return "GET Person resource"+id;
}
}
No solo admite parámetros de ruta, sino también expresiones.
@Path("/person")
public class PersonResource {
@GET
@Path("/{username: [a-zA-Z]{5,8}}")//支持正则表达式:大小写字母并且5到8个字符之间
@Produces(MediaType.TEXT_PLAIN)
public String getUser(@PathParam("username") String username){
return "GET Person resource"+username;
}
}
2. Comentarios sobre el método de solicitud.
3、@Produce
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
@GET
@Path("/text")
@Produces({
"text/plain","text/html"})
public String getTextOrHtml(){
return "hello";
}
}
Establecer Aceptar en texto/sin formato o texto/html
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
@GET
@Path("/text")
//服务端指定,text/plain 品质因数为0.9
@Produces({
"text/plain; qs=0.9","text/html"})
public String getTextOrHtml(){
return "hello";
}
}
Acceso, el encabezado de solicitud Aceptar no está especificado y el encabezado de respuesta es texto/html
4、@Consume
5、@PathParam
Se utiliza para obtener los parámetros en la ruta de solicitud de URL (ya se usa antes)
6、@QueryParam
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
// 请求路径中带?name=xxx&age=18
@GET
@Produces("text/plain")
public String get(@QueryParam("name") String name,@QueryParam("age") Integer age){
return name+age;
}
}
6.1@Valor predeterminado
Si no se pasa ningún valor, aún se puede hacer coincidir. Si no se agrega @DefaultValue, la clase de empaquetado devuelve nulo. Después de agregar @DefaultValue, se devuelve el contenido especificado.
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
// 请求路径中带?name=xxx&age=18
@GET
@Produces("text/plain")
public String get(@DefaultValue("yyds")@QueryParam("name") String name,@DefaultValue("yyds")@QueryParam("age") Integer age){
return name+age;
}
}
6.2
public class PersonResource {
// 请求路径中带?ids=1&ids=2
// @QueryParam就是活的路径中?后面的内容,比如localhost:8080/person?ids=1&ids=2
// 需要一个集合来接收多个数据,@QueryParam("ids")中的ids与路径中的ids是一致的
@DELETE
public void get(@QueryParam("ids") List<Long> ids){
System.out.println(ids);
}
}
Cartero:
7、@MatrixParam
Los parámetros de ruta comienzan con; punto y coma
Ruta de solicitud localhost:8080/person;id=1010;name=Zhang San, Li Si
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
// 矩阵参数 @MatrixParam
@GET
public String get(@MatrixParam("id") Integer id,@MatrixParam("name") List<String> names){
System.out.println(id);
System.out.println(names);
return "ok";
}
}
cartero:
8、@FormParam
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)//传过来的是表单类型的数据
public String get(@FormParam("name") String name,@FormParam("age") Integer age){
return name+age;
}
}
9、@HeadParam、@CookieParam
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
// 获取请求头和cookie中的值
@GET
public String get(@HeaderParam("User-Agent") String head,
@HeaderParam("Cookie") String cookie,
@CookieParam("name") String name){
System.out.println(head);
System.out.println(cookie);
System.out.println(name);
return head+";"+cookie+";"+name;
}
}
@CookieParam obtiene específicamente el valor en el encabezado de la solicitud
10、@BeanParam
Enviar una solicitud POST, los datos transportados son de tipo formulario
Es demasiado problemático definir @FormParam uno por uno, por lo que la anotación @BeanParam se usa para encapsular la clave en el formulario en una clase de dominio.
persona.java
package com.itheima.domain;
import lombok.Data;
import javax.ws.rs.FormParam;
@Data //包括了get、set方法和tostring
public class Person {
@FormParam("id")
private Long id;
@FormParam("name")
private String name;
@FormParam("age")
private Integer age;
}
Debido a que se pasan los parámetros del tipo de formulario, los atributos en la clase de entidad deben agregarse con @FormParam.
cartero:
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void save(@BeanParam Person person){
System.out.println(person);
}
}
Aviso
11、@Contexto
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
@Path("/person")
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
@Context
ServletContext servletContext;
@GET
public void HttpInfo(@Context HttpServletRequest request, @Context HttpServletResponse response){
System.out.println(this);
System.out.println(servletContext);
System.out.println(request);
System.out.println(response);
}
}
12. Anotaciones del ciclo de vida.
La anotación predeterminada @RequestScoped es diferente.
Más @Singleton
3. JSON
<!--json-->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23.2</version>
</dependency>
1. Devolver datos en formato json al front-end
Cartero:
@Path("/person")
@Singleton //性能会更好
//@Produces(MediaType.TEXT_PLAIN)
public class PersonResource {
// 返回json格式数据
@GET
@Produces(MediaType.APPLICATION_JSON)
public Person getJson(){
Person person = new Person();
person.setId(1001L);
person.setName("小时光");
person.setAge(12);
return person;
}
}
2. Recibir datos en formato json
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void getSJson2(Person person){
System.out.println(person);
}
Cartero:
3. Anotación de Jaskson
4. Usando SpringBoot
Estructura de directorios
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima</groupId>
<artifactId>jersey-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jersey-springboot</name>
<description>jersey-springboot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--添加web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--添加jersey-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Configuración de camiseta
package com.itheima.config;
import com.itheima.web.PersonResource;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(PersonResource.class);
}
}
código
web/PersonaRecurso
package com.itheima.web;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/person")
@Component
public class PersonResource {
@Path("hello")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getPerson(){
return "hello";
}
}
cartero
@Path("/person")
@Component
public class PersonResource {
@Path("{id}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getPerson(@PathParam("id") Integer id){
System.out.println(id);
return "hello";
}
}
5. Mejores prácticas para interfaces REST
pom.xml nuevo
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
1. Verifique los datos según la identificación
package com.itheima.web;
import com.itheima.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/person")
@Component
public class PersonResource {
@Autowired
private ApplicationContext ctx;
// 请求方式GET
// 路径 /person/id值
// 状态 200
// 响应数据类型 application/json
// 响应体中的数据就是person
//响应状态 Response类,提供方法设置状态,响应头,响应数据
//根据id去查询数据
@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getPerson(@PathParam("id") Integer id){
System.out.println(id);
//下面这段数据,实际情况下是从数据库中获取的
Person person = new Person();
person.setId(1001);
person.setName("xiaoshiguang");
person.setAge(22);
return Response.ok(person)// 不仅设置响应码为200,而且返回json格式的数据
.build();//建立Response对象
}
}
Clase de entidad persona.java
package com.itheima.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.ws.rs.FormParam;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Integer id;
private String name;
private Integer age;
}
Cartero:
2. Consulta de paginación
package com.itheima.web;
import com.itheima.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Path("/person")
@Component
public class PersonResource {
// 2、做分页查询
// 请求方式GER
// 路径 /person
// 状态 200
// 响应数据类型application/json
// 响应体中的数据是多条person数据
// 还需要返回一共有多少条数据,通过响应头来设置:X-Total-Count
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response page(){
List<Person> personList = new ArrayList<>();
Person p1 = new Person(1001,"p1",18);
Person p2 = new Person(1002,"p2",19);
Person p3 = new Person(1003,"p3",20);
personList = Arrays.asList(p1, p2, p3);
return Response.ok(personList) //SpringBoot下自动转换为json格式的数据
.header("X-Total-Count",personList.size())
.build(); // 创建对象
}
}
Nota: @AllArgsConstructor genera automáticamente constructores parametrizados y @NoArgsConstructos constructores sin parámetros
3. Guardar datos###
package com.itheima.web;
import com.itheima.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Path("/person")
@Component
public class PersonResource {
// 按restful风格
// 3、保存数据
// 发POST请求
// 请求路径 /person/save
// 请求参数是json类型,在请求体中
// 状态 201
// 响应数据类型 application/json
// 响应体中的数据包含被创建的person数据
// 响应头 location:http://localhost:8080/person/id值
@Path("/save")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response save(Person person,@Context UriInfo uriInfo){
// 把person对象存到数据库中
// 避免写死代码
URI uri = uriInfo.getAbsolutePathBuilder()
.path(person.getId() + "")
.build();
System.out.println(uri);
return Response.created(uri) //设置状态码201,并设置响应头location
.entity(person)
.build();
}
}
agregando datos
Resultados de devolución:
4. Modificar datos
package com.itheima.web;
import com.itheima.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Path("/person")
@Component
public class PersonResource {
// 按restful风格
// 4、修改数据
// 请求类型为POST
// 请求路径为/person/update
// 请求参数为json类型
// 状态码 204
// 没有响应数据
@Path("/update")
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response update(Person person){
// 把person对象修改到数据库中
System.out.println(person);
return Response.noContent() //设置响应码为204,并且没有响应数据
.build();
}
}
5. Eliminar datos
package com.itheima.web;
import com.itheima.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Path("/person")
@Component
public class PersonResource {
// 按restful风格
// 5、删除数据
// 请求类型为DELETE
// 请求路径为/person/id值
// 状态码为204 没有响应数据
@Path("delete/{id}")
@DELETE
public Response delete(@PathParam("id") Integer id){
// 从数据库中删除该id对应的字段
System.out.println("删除id为:"+id);
return Response.noContent().build();
}
}