Ceci est une suite de l'article suivant.
Exemple de configuration d'API RESTful minimum avec Jersey + Spring Framework https://qiita.com/kasa_le/items/59ebd6b5490945dd5580
Configuration multi-modules avec Maven (Jersey RESTful) https://qiita.com/kasa_le/items/db0d84e3e868ff14bc2b
Cette fois, c'est comme fusionner les projets créés dans les deux articles ci-dessus. Cependant, je vais vous expliquer en créant un projet à partir de zéro.
Implémentez l'API RESTful avec ** Jersey ** et ** Spring Framework ** (pas Boot).
--Jersey + Spring Framework fonctionne avec l'API RESTful (CRUD). --DI peut être fait avec une configuration multi-module.
Outils etc. | Version etc. |
---|---|
MacbookPro | macOS Mojave 10.14.5 |
IntelliJ IDEA | Ultimate 2019.3.3 |
Java | AdoptOpenJDK 11 |
apache maven | 3.6.3 |
Jersey | 2.30.1 |
JUnit | 5.6.0 |
Tomcat | apache-tomcat-8.5.51 |
Postman | 7.19.1 |
Spring Framework | 5.2.4-RELEASE |
Dans IntelliJ, créez un nouveau projet Maven
.
Fondamentalement, vous pouvez copier les paramètres de dépendance et de plug-in à partir du projet Configuration minimale de Jersey + Spring Framework.
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.example.jerseyspring</groupId>
<artifactId>jersey-spring-restful</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jersey and Spring Framework RESTfulAPI Sample</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<inherited>true</inherited>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>src/test/java/</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M4</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>
<!-- Jersey -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-server -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Jersey + Spring -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.ext/jersey-spring5 -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring5</artifactId>
<version>${jersey.version}</version>
</dependency>
<!--JAXB supprimé de JDK9-->
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
<!--tester-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.test-framework.providers/jersey-test-framework-provider-grizzly2 -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.30.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<spring.version>5.2.4.RELEASE</spring.version>
<jersey.version>2.30.1</jersey.version>
<junit.jupiter.version>5.6.0</junit.jupiter.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
src
Supprimez-le manuellement.
Dans le menu IntelliJ [Fichier] - [Nouveau] - [Module ...], ajoutez les deux suivants dans le projet Maven.
Le nom du sous-module est arbitraire. N'oubliez pas de définir ** Parent **. (Veuillez sélectionner le projet racine.)
Ensuite, le «
root/pom.xml
<groupId>my.example.jerseyspring</groupId>
<artifactId>jersey-spring-restful</artifactId>
<packaging>pom</packaging>
Chaque pom.xml
du sous-module devrait ressembler à ceci:
repository/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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jersey-spring-restful</artifactId>
<groupId>my.example.jerseyspring</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>repository</artifactId>
<packaging>jar</packaging>
</project>
serverapi/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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jersey-spring-restful</artifactId>
<groupId>my.example.jerseyspring</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>serverapi</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>my.example.jerseyspring</groupId>
<artifactId>repository</artifactId>
<version>${project.version}</version>
</dependency>
<!-- for spring test-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Le module serverapi est inclus dans la portée <test>
car le Spring Test est requis pour le test Junit.
Cependant, si vous en avez besoin dans d'autres sous-modules, vous pouvez le mettre à la racine pom.xml
.
Aucun n'a spécifié sa propre version. Je souhaite utiliser la version parente telle quelle.
C'est une politique de ne pas gérer la version pour chaque sous-module. Si nécessaire, spécifiez la version pour chacun avec la balise <version>
.
La structure actuelle des dossiers devrait ressembler à ceci.
$ tree
.
├── SpringJerseyRest.iml
├── pom.xml
├── repository
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
└── serverapi
├── pom.xml
└── src
├── main
│ ├── java
│ └── resources
└── test
└── java
Créez les classes suivantes dans le package my.example.jerseyspring.repository.models
.
Employee.java
package my.example.jerseyspring.repository.models;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Employee {
private int id;
private String firstName;
public Employee() {
}
public Employee(int id, String firstName) {
this.id = id;
this.firstName = firstName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
Créez la classe ʻEmployeeRepository dans le package
my.example.jerseyspring.repository`.
EmployeeRepository.java
package my.example.jerseyspring.repository;
import my.example.jerseyspring.repository.exceptions.DuplicateIdException;
import my.example.jerseyspring.repository.exceptions.EmployeeNameNotFoundException;
import my.example.jerseyspring.repository.exceptions.EmployeeNotFoundException;
import my.example.jerseyspring.repository.models.Employee;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Repository
public class EmployeeRepository {
private List<Employee> employeeList;
public EmployeeRepository() {
employeeList = new ArrayList<>();
employeeList.add(new Employee(3, "Cupcake"));
employeeList.add(new Employee(4, "Donuts"));
employeeList.add(new Employee(5, "Eclair"));
employeeList.add(new Employee(8, "Froyo"));
employeeList.add(new Employee(9, "Gingerbread"));
}
public List<Employee> selectAll() {
return employeeList;
}
public Employee select(int id) {
for (Employee employee : employeeList) {
if (employee.getId() == id) {
return employee;
}
}
throw new EmployeeNotFoundException();
}
public synchronized void insert(int id, String firstName) {
try {
select(id);
} catch (EmployeeNotFoundException e) {
//Sinon, vous pouvez ajouter
employeeList.add(new Employee(id, firstName));
return;
}
//Ne peut pas être ajouté si le même ID existe
throw new DuplicateIdException();
}
public synchronized void update(int id, String firstName) {
Employee employee = select(id);
employee.setFirstName(firstName);
}
public synchronized void delete(int id) {
Employee employee = select(id);
employeeList.remove(employee);
}
public List<Employee> search(String name) {
List<Employee> list = new ArrayList<>();
for (Employee employee : employeeList) {
if (employee.getFirstName().contains(name)) {
list.add(employee);
}
}
if (list.size() > 0) return list;
throw new EmployeeNameNotFoundException(name);
}
}
Dans le précédent exemple multi-module, j'ai mis l'implémentation singleton par moi-même, mais la DI de Spring Framework est fondamentalement singleton , Suppression de sa mise en œuvre.
ʻCréez chaque classe d'exception utilisée dans la classe EmployeeRepository. Le paquet est
repository.exceptions`.
Exemple) Classe ʻEmployeeNotFoundException`
EmployeeNotFoundException.java
package my.example.jerseyspring.repository.exceptions;
public class EmployeeNotFoundException extends RuntimeException {
public EmployeeNotFoundException() {
super("L'employé avec cet ID est introuvable.");
}
}
Créez d'autres classes de la même manière.
Aussi, j'apporterai le paquet transacation
utilisé dans le projet Configuration minimale de Jersey + Spring.
Le package repository.transaction
est très bien.
Créez une classe de test pour la classe d'exception.
A titre d'exemple, prenons le cas de ʻEmployeeNotFoundException`.
EmployeeNotFoundExceptionTest.java
package my.example.jerseyspring.repository.exceptions;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class EmployeeNotFoundExceptionTest {
@Test
void getMessage() {
EmployeeNotFoundException e = new EmployeeNotFoundException();
assertThat(e.getMessage()).isEqualTo("L'employé avec cet ID est introuvable.");
}
}
Depuis IntelliJ, exécutons le test Junit et vérifions qu'il réussit.
En fin de compte, vous devriez avoir une structure de dossiers comme celle-ci:
$ tree
.
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── my
│ │ └── example
│ │ └── jerseyspring
│ │ └── repository
│ │ ├── EmployeeRepository.java
│ │ ├── exceptions
│ │ │ ├── DuplicateIdException.java
│ │ │ ├── EmployeeNameNotFoundException.java
│ │ │ └── EmployeeNotFoundException.java
│ │ ├── models
│ │ │ └── Employee.java
│ │ └── transaction
│ │ ├── TransactionBo.java
│ │ └── impl
│ │ └── TransactionBoImpl.java
│ └── resources
└── test
└── java
└── my
└── example
└── jerseyspring
└── repository
└── exceptions
├── DuplicateIdExceptionTest.java
├── EmployeeNameNotFoundExceptionTest.java
└── EmployeeNotFoundExceptionTest.java
19 directories, 11 files
Créez la classe ʻEmployeeService dans le package
my.example.jerseyspring.rest`.
EmployeeService.java
package my.example.jerseyspring.rest;
import my.example.jerseyspring.repository.EmployeeRepository;
import my.example.jerseyspring.repository.models.Employee;
import org.springframework.stereotype.Service;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.util.List;
@Service
@Path("/employees")
public class EmployeeService {
final EmployeeRepository employeeRepository;
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
@Context
UriInfo uriInfo;
@GET
@Path("/all")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Employee> getAll() {
return employeeRepository.selectAll();
}
@GET
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Employee getEmployee(@PathParam("id") int id) {
return employeeRepository.select(id);
}
@GET
@Path("/search")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Employee> searchEmployee(@QueryParam("name") String name) {
return employeeRepository.search(name);
}
@POST
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response addEmployee(Employee employee) {
employeeRepository.insert(employee.getId(), employee.getFirstName());
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(String.valueOf(employee.getId()));
return Response.created(builder.build()).build();
}
@PUT
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response updateEmployee(Employee employee) {
employeeRepository.update(employee.getId(), employee.getFirstName());
//Si vous en créez un nouveau, vous devez renvoyer créé, mais dans cet exemple, il s'agit d'une erreur, donc il renvoie toujours ok.
return Response.ok().build();
}
@DELETE
@Path("/{id}")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response deleteEmployee(@PathParam("id") int id) {
employeeRepository.delete(id);
//Pour renvoyer le statut de l'entité, renvoyez ok.
//S'il est accepté mais que le processus n'est pas terminé(Je viens juste de suivre, etc.)Retours acceptés
//Dans cet exemple, seule la suppression est terminée et le contenu correspondant est perdu.
return Response.noContent().build();
}
}
Aussi, j'apporterai la classe PaymentService
utilisée dans le projet Configuration minimale de Jersey + Spring.
Créez une classe pour le mappage d'exceptions dans le package rest.handlers
.
Requis pour chaque classe d'exception créée par le module de référentiel.
Pour le mappage des exceptions, cliquez ici (https://qiita.com/kasa_le/items/3c7e7a426acf846ee64e#%E4%BE%8B%E5%A4%96%E3%83%8F%E3%83%B3%E3 Veuillez vous référer à% 83% 89% E3% 83% AA% E3% 83% B3% E3% 82% B0).
Exemple) mappeur de classe ʻEmployeeNotFoundException`
NotFoundExceptionHandler.java
package my.example.jerseyspring.rest.handler;
import my.example.jerseyspring.repository.exceptions.EmployeeNotFoundException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class NotFoundExceptionHandler implements ExceptionMapper<EmployeeNotFoundException> {
public Response toResponse(EmployeeNotFoundException ex) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
Créez ʻapplicationContext.xml sous
src / main / resources` et faites-le comme suit.
applicationContext.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="my.example.jerseyspring"/>
<bean id="transactionBo" class="my.example.jerseyspring.repository.transaction.impl.TransactionBoImpl"/>
<bean id="employeeRepository" class="my.example.jerseyspring.repository.EmployeeRepository"/>
</beans>
webapp
Créez un dossier src / main / webapp
.
--Créez web.xml
sous webapp / WEB-INF
et faites-en le contenu suivant
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" 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_2_5.xsd">
<display-name>Restful Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.example.jerseyspring</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
--Créez ʻindex.jsp sous
webapp / ʻet faites-le comme suit
index.jsp
<html>
<body>
<h2>Jersey + Spring RESTful Web Application!</h2>
<p><a href="rest/payment/mkyong">Jersey resource</a>
<br>
<p><a href="rest/employees/all">All Employee List</a>
<p><a href="rest/employees/3">get id=3 employee</a>
</body>
</html>
Créez une classe EmployeeServiceTest
et une classe PaymentServiceTest
pour écrire un test.
EmployeeServiceTest.java
package my.example.jerseyspring.rest;
import my.example.jerseyspring.repository.EmployeeRepository;
import my.example.jerseyspring.repository.models.Employee;
import my.example.jerseyspring.rest.handler.DuplicateExceptionHandler;
import my.example.jerseyspring.rest.handler.NameNotFoundExceptionHandler;
import my.example.jerseyspring.rest.handler.NotFoundExceptionHandler;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:/applicationContext.xml")
public class EmployeeServiceTest extends JerseyTest {
@Autowired
EmployeeRepository employeeRepository;
@Override
protected Application configure() {
return new ResourceConfig(EmployeeService.class)
.register(DuplicateExceptionHandler.class)
.register(NameNotFoundExceptionHandler.class)
.register(NotFoundExceptionHandler.class)
.register(this);
}
@BeforeEach
@Override
public void setUp() throws Exception {
super.setUp();
}
@AfterEach
@Override
public void tearDown() throws Exception {
super.tearDown();
}
@ParameterizedTest
@ValueSource(strings = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public void getAll(String mediaType) {
final Response response = target("/employees/all").request().accept(mediaType).get();
assertThat(response.getHeaderString("Content-Type"))
.isEqualTo(mediaType);
List<Employee> content = response.readEntity(new GenericType<>() {
});
assertThat(content.size()).isEqualTo(5);
assertThat(content.get(0)).isEqualToComparingFieldByField(new Employee(3, "Cupcake"));
assertThat(content.get(1)).isEqualToComparingFieldByField(new Employee(4, "Donuts"));
assertThat(content.get(2)).isEqualToComparingFieldByField(new Employee(5, "Eclair"));
assertThat(content.get(3)).isEqualToComparingFieldByField(new Employee(8, "Froyo"));
assertThat(content.get(4)).isEqualToComparingFieldByField(new Employee(9, "Gingerbread"));
}
@ParameterizedTest
@MethodSource("getParamProvider")
public void getEmployee(int id, String mediaType) {
String urlPath = String.format("/employees/%d", id);
final Response response = target(urlPath).request().accept(mediaType).get();
assertThat(response.getHeaderString("Content-Type"))
.isEqualTo(mediaType);
Employee employee = response.readEntity(Employee.class);
Employee expect = employeeRepository.select(id);
assertThat(employee).isEqualToComparingFieldByField(expect);
}
static Stream<Arguments> getParamProvider() {
return Stream.of(
Arguments.of(3, MediaType.APPLICATION_JSON),
Arguments.of(4, MediaType.APPLICATION_JSON),
Arguments.of(5, MediaType.APPLICATION_JSON),
Arguments.of(8, MediaType.APPLICATION_JSON),
Arguments.of(9, MediaType.APPLICATION_JSON),
Arguments.of(3, MediaType.APPLICATION_XML),
Arguments.of(4, MediaType.APPLICATION_XML),
Arguments.of(5, MediaType.APPLICATION_XML),
Arguments.of(8, MediaType.APPLICATION_XML),
Arguments.of(9, MediaType.APPLICATION_XML)
);
}
@ParameterizedTest
@ValueSource(strings = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public void searchEmployee(String mediaType) {
final Response response = target("/employees/search")
.queryParam("name", "a")
.request()
.accept(mediaType)
.get();
assertThat(response.getHeaderString("Content-Type"))
.isEqualTo(mediaType);
List<Employee> content = response.readEntity(new GenericType<>() {
});
assertThat(content.size()).isEqualTo(3);
assertThat(content.get(0)).isEqualToComparingFieldByField(new Employee(3, "Cupcake"));
assertThat(content.get(1)).isEqualToComparingFieldByField(new Employee(5, "Eclair"));
assertThat(content.get(2)).isEqualToComparingFieldByField(new Employee(9, "Gingerbread"));
}
@ParameterizedTest
@MethodSource("postRawProvider")
public void addEmployee(int id, String bodyRaw, String mediaType) {
final Response response = target("/employees").request()
.post(Entity.entity(bodyRaw, mediaType));
assertThat(response.getStatus()).isEqualTo(201);
assertThat(response.getHeaderString("Location"))
.isEqualTo("http://localhost:9998/employees/" + id);
}
static Stream<Arguments> postRawProvider() {
final String json = "{\"firstName\":\"Honeycomb\",\"id\":11}";
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<employee><firstName>KitKat</firstName><id>19</id></employee>";
return Stream.of(
Arguments.of(11, json, MediaType.APPLICATION_JSON),
Arguments.of(19, xml, MediaType.APPLICATION_XML)
);
}
@ParameterizedTest
@MethodSource("putRawProvider")
public void updateEmployee(int id, String bodyRaw, String mediaType) {
final Response response = target("/employees").request()
.put(Entity.entity(bodyRaw, mediaType));
assertThat(response.getStatus()).isEqualTo(200);
Employee employee = target("/employees/" + id).request().get(Employee.class);
Employee expected = employeeRepository.select(id);
assertThat(employee).isEqualToComparingFieldByField(expected);
}
static Stream<Arguments> putRawProvider() {
final String json = "{\"firstName\":\"Frozen yogurt\",\"id\":8}";
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<employee><firstName>Cup Cake</firstName><id>3</id></employee>";
return Stream.of(
Arguments.of(8, json, MediaType.APPLICATION_JSON),
Arguments.of(3, xml, MediaType.APPLICATION_XML)
);
}
@Test
public void deleteEmployee() {
final Response response = target("/employees/9")
.request().delete();
assertThat(response.getStatus()).isEqualTo(204);
}
@Test
public void exception_selectEmployee() {
final Response response = target("/employees/1").request().get();
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
public void exception_searchEmployee() {
final Response response = target("/employees/search?name=android").request().get();
assertThat(response.getStatus()).isEqualTo(404);
}
@ParameterizedTest
@MethodSource("putRawProvider")
public void exception_addEmployee(int id, String bodyRaw, String mediaType) {
final Response response = target("/employees").request()
.post(Entity.entity(bodyRaw, mediaType));
assertThat(response.getStatus()).isEqualTo(409);
}
@ParameterizedTest
@MethodSource("putExceptionProvider")
public void exception_updateEmployee(int id, String bodyRaw, String mediaType) {
final Response response = target("/employees").request()
.put(Entity.entity(bodyRaw, mediaType));
assertThat(response.getStatus()).isEqualTo(404);
}
static Stream<Arguments> putExceptionProvider() {
final String json = "{\"firstName\":\"Lollipop\",\"id\":21}";
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<employee><firstName>Jelly Bean</firstName><id>17</id></employee>";
return Stream.of(
Arguments.of(21, json, MediaType.APPLICATION_JSON),
Arguments.of(3, xml, MediaType.APPLICATION_XML)
);
}
@Test
public void exception_deleteEmployee() {
final Response response = target("/employees/1").request().get();
assertThat(response.getStatus()).isEqualTo(404);
}
}
Dans Exemple multi-module, la partie qui obtenait l'objet Sington en tant que ʻEmployeeRepository.getInstance est à la variable membre déclarée par
@ Autowired. Accès et changement. Avec l'annotation
@ Autowired, Spring va DI pour vous, mais en fait, il semble que différentes instances seront créées pour la personne qui travaille réellement avec le service et la personne qui teste (cela devrait être un singleton, mais probablement le test). J'ai vu un article disant qu'il est normal de faire
ResourceConfig # register (this)` (car le contexte est différent du contexte de l'application).
Cependant, n'est-ce pas un bug qui fonctionne avec cela? Parce qu'il y a un message d'avertissement? Il y a aussi une opinion, donc je ne sais pas si elle est correcte.
https://stackoverflow.com/questions/34453448/how-to-access-spring-bean-from-jerseytest-subclass
Cette fois, la classe de référentiel n'est pas le sujet principal en premier lieu, elle fournit juste un accès temporaire aux données, donc je suis content de cela une fois. Cependant, sachez que cela peut cesser de fonctionner à mesure que la version de Spring ou de Jersey augmente.
La classe PaymentServiceTest
est également importée à partir de l'exemple de configuration minimum (https://qiita.com/kasa_le/items/59ebd6b5490945dd5580).
Apportez également la classe TransactionBoMock
créée pour le test de remplacement simulé DI.
Ensuite, placez ʻapplicationContext.xml dans le dossier
resourcesdu dossier
test` afin de pouvoir remplacer le bean, et procédez comme suit.
test/resources/applicationContext.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="my.example.jerseyspring"/>
<bean id="transactionBo" class="my.example.jerseyspring.repository.transaction.impl.TransactionBoMock"/>
<bean id="employeeRepository" class="my.example.jerseyspring.repository.EmployeeRepository"/>
</beans>
Je n'ai pas créé d'interface pour EmployeeRepository, donc je ne la remplacerai pas cette fois, mais normalement, je devrais utiliser une classe Mocked pour tester par rapport à l'implémentation d'origine qui récupère les données de DB, etc.
La structure du dossier serverapi
devrait ressembler à ceci:
.
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── my
│ │ └── example
│ │ └── jerseyspring
│ │ └── rest
│ │ ├── EmployeeService.java
│ │ ├── PaymentService.java
│ │ └── handler
│ │ ├── DuplicateExceptionHandler.java
│ │ ├── NameNotFoundExceptionHandler.java
│ │ └── NotFoundExceptionHandler.java
│ ├── resources
│ │ └── applicationContext.xml
│ └── webapp
│ ├── WEB-INF
│ │ └── web.xml
│ └── index.jsp
└── test
├── java
│ └── my
│ └── example
│ └── jerseyspring
│ ├── repository
│ │ └── transaction
│ │ └── impl
│ │ └── TransactionBoMock.java
│ └── rest
│ ├── EmployeeServiceTest.java
│ └── PaymentServiceTest.java
└── resources
└── applicationContext.xml
21 directories, 13 files
(1)JUnitTest Exécutez JUnitTest pour voir si tous les tests réussissent.
$ mvn clean test
Configurez et déployez Tomcat.
Vous devriez voir une page comme celle ci-dessous, cliquez sur le lien et vous devriez voir la valeur de retour de l'API.
Si vous souhaitez vérifier l'entrée / la sortie du système POST ou de Json / Xml, veuillez vérifier en utilisant Curl ou Postman.
Les projets à ce jour sont téléchargés ci-dessous. https://github.com/le-kamba/spring-jersey-sample/tree/spring_jersey
J'ai pu le faire en douceur sans devenir accro, sauf pour la partie singleton.
À propos, la structure des dossiers a été mise en place en mettant la commande ** tree ** dans brew sur mac. Je devais le faire dès l'installation de Homebrew en premier lieu. (Vous ne l'avez pas mis?)
#Installation Homebrew
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
#installation d'arbre
$ brew install tree
Quelle est la différence entre Spring DI et new? https://qiita.com/uqichi/items/5f59817beb3dff9c0c1e
Recommended Posts