Commit 3ff51648 by Patryk Czarnik

RestTechnicznie

parent 66e3cfbe
/target/
/.settings/
/.classpath
/.project
/*.iml
/.idea/
<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>
<groupId>pl.alx.kjava</groupId>
<artifactId>PC37-RestTechnicznie</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</project>
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/a")
public class A {
@GET
public String get() {
return "AAAAAAAA";
}
}
package rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
// przykładowy adres
// http://localhost:8080/PC36-RestTechniczne-1.0/rest1/a
@ApplicationPath("/rest1")
public class AplikacjaRestowa1 extends Application {
// Definicja aplikacji JAX-RS, w której skład wchodzą wszystkie dostępne w projekcie klasy oznaczone adnotacjami @Path lub @Provider
// Klasy zasobów działają w trybie "per-request" - dla każdego zapytania jest tworzony nowy obiekt klasy zasobu
// np. jest tworzony nowy wyzerowany licznik - /rest1/licznik będzie zawsze zwracać 1
}
package rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/rest2")
public class AplikacjaRestowa2 extends Application {
// Sam podaję klasy, które wchodzą w skład aplikacji JAX-RS
// Podaj się zarówno zasoby (@Path), jak i rozszerzenia (@Provider)
// Klasy zasobów działają w trybie "per-request"
// Czyli licznik /rest2/licznik będzie zawsze zwracać 1
@Override
public Set<Class<?>> getClasses() {
// Są klasy A i B, a nie ma C
HashSet<Class<?>> zbior = new HashSet<>();
zbior.add(A.class);
zbior.add(B.class);
zbior.add(Licznik.class);
zbior.add(Kontekst.class);
zbior.add(EBean.class);
return zbior;
// Od Javy 9:
// return Set.of(A.class, B.class, Licznik.class, Kontekst.class, EBean.class);
}
}
package rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/rest3")
public class AplikacjaRestowa3 extends Application {
// Sam podaję klasy, które wchodzą w skład aplikacji JAX-RS
// Podaj się zarówno zasoby (@Path), jak i rozszerzenia (@Provider)
@Override
public Set<Class<?>> getClasses() {
System.out.println("Aplikacja3.getClasses");
// te klasy działają w trybie "per-request"
HashSet<Class<?>> zbior = new HashSet<>();
zbior.add(A.class);
zbior.add(Kontekst.class);
return zbior;
}
@Override
public Set<Object> getSingletons() {
System.out.println("Aplikacja3.getSingletons");
Licznik licznik = new Licznik();
licznik.setLicznik(100);
// Te klasy działają w trybie singleton - ten sam obiekt obsługuje różne zapytania.
// Czyli licznik /rest3/licznik będzie zwraca coraz większe wartości
HashSet<Object> zbior = new HashSet<>();
zbior.add(new B());
zbior.add(new Kontekst());
zbior.add(licznik);
zbior.add(new EBean());
return zbior;
}
}
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/b")
public class B {
{ System.out.println("Powstaje obiekt B"); }
@GET
public String get() {
return "BBBB";
}
}
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/c")
public class C {
@GET
public String get() {
return "CCC";
}
}
package rest;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/ejb")
@Stateless
// @Singleton // też działa
public class EBean implements Serializable {
private static final long serialVersionUID = -2627946805995054930L;
private AtomicInteger licznik = new AtomicInteger();
// Dzięki temu, że jesteśmy w klasie EJB, można korzystać z adnotacji Java EE
// @PersistenceUnit
// private EntityManager em;
public EBean() {
System.out.println("EBean konstruktor");
}
@PostConstruct
public void postConstruct() {
System.out.println("EBean @PostConstruct");
}
@PreDestroy
public void preDestroy() {
System.out.println("EBean @PreDestroy");
}
@GET
public String get() {
return "Hello EJB. Licznik = " + licznik.incrementAndGet();
}
}
package rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path("/calc")
public class Kalkulator {
@GET
@Path("/{x}+{y}")
public long dodaj(@PathParam("x") long a, @PathParam("y") long b) {
return a+b;
}
@GET
@Path("/{x}-{y}")
public long odejmij(@PathParam("x") long a, @PathParam("y") long b) {
return a-b;
}
@GET
@Path("/{x}*{y}")
public long pomnoz(@PathParam("x") long a, @PathParam("y") long b) {
return a*b;
}
@GET
@Path("/{x}/{y}")
public long podziel(@PathParam("x") long a, @PathParam("y") long b) {
return a/b;
}
}
package rest;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
@Path("/kontekst")
@Produces("text/plain")
public class Kontekst {
@GET
public String info(
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Context Request restRequest,
@Context HttpHeaders headers,
@Context ServletContext servletContext,
@Context ServletConfig servletConfig,
@Context HttpServletRequest servletRequest,
@Context HttpServletResponse servletResponse
) {
StringBuilder b = new StringBuilder();
b.append("UriInfo\n");
b.append("Base URI : ").append(uriInfo.getBaseUri()).append('\n');
b.append("Absolute path: ").append(uriInfo.getAbsolutePath()).append('\n');
b.append("Path : ").append(uriInfo.getPath()).append('\n');
b.append("\nHttpHeaders\n");
b.append(headers.getRequestHeaders());
// Request restRequest - wiąże się z obsługą keszowania i typów zawartości
b.append("\nServletContext\n");
b.append("ServlerInfo: ").append(servletContext.getServerInfo()).append('\n');
b.append("\nServletRequest\n");
b.append("RemoteAddr: ").append(servletRequest.getRemoteAddr()).append('\n');
b.append("LocalAddr : ").append(servletRequest.getLocalAddr()).append('\n');
b.append("URI : ").append(servletRequest.getRequestURI()).append('\n');
b.append("Parametry :\n");
for (Map.Entry e : servletRequest.getParameterMap().entrySet()) {
String[] v = (String[]) e.getValue();
b.append(" * " + e.getKey() + " : " + Arrays.toString(v) + "\n");
}
b.append("\nZalogowany wg serwletu: ").append(servletRequest.getRemoteUser()).append('\n');
b.append("Zalogowany wg SecurityContext: ").append(securityContext.getUserPrincipal()).append('\n');
return b.toString();
}
}
package rest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/licznik")
@Produces("text/plain")
@Consumes("text/plain")
public class Licznik {
private int licznik = 0;
@GET
public synchronized int getLicznik() {
return ++licznik;
}
@PUT
public synchronized void setLicznik(int licznik) {
this.licznik = licznik;
}
}
package rest;
import java.time.LocalDateTime;
import java.util.Arrays;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
/* Przykładowe adresy z parametrami:
/rest1/parametry/query?a=Ala&b=Ola&b=Ela&t=Basia&t=Kasia&t=Zosia
/rest1/parametry/matrix;a=Ala;b=Ola;b=Ela;t=Basia;t=Kasia;t=Zosia
*/
@Path("/parametry")
@Produces("text/plain")
public class Parametry {
@GET
@Path("/query")
public String query(
@QueryParam("a") String a,
@QueryParam("b") String b,
@QueryParam("t") String[] t) {
return "Parametr a = " + a
+ "\nParametr b = " + b
+ "\nTablica: " + Arrays.toString(t);
}
@GET
@Path("/matrix")
public String matrix(
@MatrixParam("a") String a,
@MatrixParam("b") String b,
@MatrixParam("t") String[] t) {
return "Parametr a = " + a
+ "\nParametr b = " + b
+ "\nTablica: " + Arrays.toString(t);
}
// /rest1/parametry/path/Ala/123/98765qwerty@res-zta
@GET
@Path("/path/{a}/{b}/{cyfry:\\d+}{litery:\\w+}{reszta}")
public String pathParam(
@PathParam("a") String a,
@PathParam("b") String b,
@PathParam("cyfry") String cyfry,
@PathParam("litery") String litery,
@PathParam("reszta") String reszta
) {
return "Parametr a = " + a
+ "\nParametr b = " + b
+ "\nCyfry: " + cyfry
+ "\nLitery: " + litery
+ "\nReszta: " + reszta;
}
@GET
@Path("/headers")
public String headers(
@HeaderParam("accept") String accept,
@HeaderParam("user-agent") String agent
) {
return "Accept: " + accept
+ "\nUser-Agent: " + agent;
}
@GET
@Path("/cookies")
public String cookies(
@CookieParam("ciacho") String ciacho,
@CookieParam("JSESSIONID") String sessionId
) {
return "Ciacho: " + ciacho
+ "\nSesja: " + sessionId;
}
@GET
@Path("/ustaw")
// ustawia ciacho
public Response ustawCiacho() {
String ciacho = LocalDateTime.now().toString();
return Response.ok()
.cookie(new NewCookie("ciacho", ciacho))
.type("text/plain")
.entity("Ustawiam ciacho na: " + ciacho)
.build();
}
}
package rest;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
@Path("/sesja")
public class Sesja {
@Context
private HttpServletRequest request;
@Produces("text/plain")
@GET
public int licznik() {
HttpSession sesja = request.getSession();
AtomicInteger licznik = null;
synchronized (sesja) {
licznik = (AtomicInteger) sesja.getAttribute("x");
if(licznik == null) {
licznik = new AtomicInteger(100);
sesja.setAttribute("x", licznik);
sesja.setMaxInactiveInterval(30); // po 30s sesja wygasa
}
}
return licznik.getAndIncrement();
// tak jakby return licznik++
}
}
package serwlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/serwlet")
public class ZwyklySerwlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Jestem zwyklym serwletem");
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Elementy techniczne JAX-RS</title>
</head>
<body>
<h1>Elementy techniczne JAX-RS</h1>
<ul>
<li><a href="serwlet">zwykły serwlet</a> - działający poza JAX-RS</li>
</ul>
<h2>Trzy wersje aplikacji</h2>
<ol>
<li>rest1 - ustawienia domyślne - <i>per request</i>
<ul>
<li><a href="rest1/a">A</a> - istnieje</li>
<li><a href="rest1/b">B</a> - istnieje</li>
<li><a href="rest1/c">C</a> - istnieje</li>
<li><a href="rest1/licznik">Licznik</a> - zawsze 1</li>
</ul>
</li>
<li>rest2 - <code>getClasses()</code> - <i>per request</i>
<ul>
<li><a href="rest2/a">A</a> - istnieje</li>
<li><a href="rest2/b">B</a> - istnieje</li>
<li><a href="rest2/c">C</a> - nie istnieje</li>
<li><a href="rest2/licznik">Licznik</a> - zawsze 1</li>
</ul>
</li>
<li>rest3 - <code>getSingletons()</code> - niektóre zasoby jako singletony
<ul>
<li><a href="rest3/a">A</a> - istnieje</li>
<li><a href="rest3/b">B</a> - istnieje</li>
<li><a href="rest3/c">C</a> - nie istnieje</li>
<li><a href="rest3/licznik">Licznik</a> - globalny</li>
</ul>
</li>
</ol>
<h2>Elementy techniczne</h2>
<ul>
<li><a href="rest1/kontekst">kontekst</a> - informacje wstrzyknięte za pomocą @Context</li>
<li><a href="rest1/sesja">sesja</a> - licznik w sesji</li>
<li><b>Parametry</b>
<ul>
<li><a href="rest1/parametry/query?a=Ala&b=Ola&b=Ela&t=Basia&t=Kasia&t=Zosia">@QueryParam</a></li>
<li><a href="rest1/parametry/matrix;a=Ala;b=Ola;b=Ela;t=Basia;t=Kasia;t=Zosia">@MatrixParam</a></li>
<li><a href="rest1/parametry/path/Ala/123/98765qwerty@res-zta">@PathParam</a></li>
<li><a href="rest1/parametry/headers">@HeaderParam</a></li>
<li><a href="rest1/parametry/cookies">@CookieParam</a></li>
<li><a href="rest1/parametry/ustaw">Ustaw ciacho</a></li>
</ul>
</li>
</ul>
<h2>Kalkulator</h2>
<ul>
<li><a href="rest1/calc/12+13">dodawanie</a></li>
<li><a href="rest1/calc/12*13">mnożenie</a></li>
</ul>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment