[JAVA] [Mise à jour décembre 2018] Astuces pour le serveur Web intégré et le serverlet créés avec Jetty9

Comme vous le savez, Jetty9 est un serveur Web léger et hautement fonctionnel, un conteneur de servlets.

Voici un exemple de code qui inclut des conseils de configuration et des servlets fréquemment utilisés lors de l'utilisation de Jetty9 en tant qu'application Java intégrée.

L'ensemble de code source de travail (projet maven) est répertorié sur https://github.com/riversun/jetty9-quick-start.

Les articles sur HTTPS (SSL / TLS) avec Jetty9 sont résumés sur https://qiita.com/riversun/items/2909019123b28471ea79.

Conseils de paramétrage intégrés de Jetty9 (opération confirmée avec la v.9.4.12)

● Ajouter un servlet

Ajoutez un servlet appelé ExampleServlet.java qui accepte avec le chemin "/ api"

//ServletContextHandler gère le servlet
ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

//Ajouter un servlet
servletHandler.addServlet(new ServletHolder(new ExampleServlet()), "/api");

● Spécifiez la taille de téléchargement du formulaire

Si vous essayez de télécharger une grande taille de données, vous pouvez obtenir ** java.lang.IllegalStateException: Form too large **. Dans ce cas, spécifiez la taille requise avec ** setMaxFormContentSize **.


//Spécifiez la taille de téléchargement du formulaire
servletHandler.setMaxFormContentSize(1024 * 1024 * 1024);

● Spécifiez l'emplacement du contenu statique (fichier statique)

Spécifiez la base de ressources avec ** setResourceBase **.

//ResourceHandler gère le contenu statique (en gros)
final ResourceHandler resourceHandler = new ResourceHandler();

//Spécifiez l'emplacement du contenu statique
resourceHandler.setResourceBase(System.getProperty("user.dir") + "/htdocs");

● Je ne souhaite pas afficher une liste de fichiers de contenu statique

C'est une fonction traditionnelle ~~ curieuse ~~ des serveurs Web tels qu'Apache. Si vous ne souhaitez pas afficher la liste des fichiers (liste), procédez comme suit

//Ne pas afficher la liste des fichiers de contenu statique (liste)
resourceHandler.setDirectoriesListed(false);

● Je souhaite modifier le code HTML par défaut de index.html

Peut être modifié avec ** setWelcomeFiles **

//Spécifiez le fichier à afficher initialement
resourceHandler.setWelcomeFiles(new String[] { "index.html" });

● Désactivez le cache. Ne mettez pas en cache.

Un moyen de désactiver la mise en cache du contenu statique qui afflige les développeurs HTML et JavaScript. ** setCacheControl ** vous libère des coups répétés F5 d'eau sur les pierres brûlées.

//Ne pas mettre en cache
resourceHandler.setCacheControl("no-store,no-cache,must-revalidate");

● N'envoyez pas d'informations sur la version du serveur dans les en-têtes, etc.

Il est utilisé lorsque vous ne souhaitez pas afficher d'informations telles que le numéro de version de la jetée dans l'en-tête HTTP ou l'écran d'erreur par défaut. Il peut être défini avec ** HttpConfig # setSendServerVersion **.

Je vais vous montrer deux méthodes (Ce que je veux faire est simple, mais le code est un peu plus long. C'est plus compliqué que jetty8 avec refactoring jetty9)

[Méthode 1] Créez votre propre connecteur http et définissez httpConfig

//Initialisez le serveur avec le constructeur par défaut
final Server jettyServer = new Server();
jettyServer.setHandler(handlerList);

final int PORT = 8080;

//classe de configuration http
final HttpConfiguration httpConfig = new HttpConfiguration();

//Ne mettez pas les informations de version du serveur dans l'en-tête
httpConfig.setSendServerVersion(false);
final HttpConnectionFactory httpConnFactory = new HttpConnectionFactory(httpConfig);
final ServerConnector httpConnector = new ServerConnector(jettyServer, httpConnFactory);
httpConnector.setPort(PORT);
jettyServer.setConnectors(new Connector[] { httpConnector });

[Méthode 2] Retirez le connecteur http (existant) et définissez httpConfig

final int PORT = 8080;

final Server jettyServer = new Server(PORT );

for (Connector conn : jettyServer.getConnectors()) {
  for (ConnectionFactory connFactory : conn.getConnectionFactories()) {
    if (connFactory instanceof HttpConnectionFactory) {
      ((HttpConnectionFactory) connFactory).getHttpConfiguration().setSendServerVersion(false);
    }
  }
}

Exemple de code complet Servlet sur Jetty9

Exemple de servlet de type API Web avec accès CORS (interdomaine) qui renvoie un JSON contenant le code décrit ci-dessus. Définissez la dépendance de Maven, copiez et exécutez, et accédez à http: // localhost: 8080 / api? Message = hello.

package com.example.jetty;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Jetty9 Quick Start Example
 */
public class ServletApp
{
	public static void main(String[] args) {

		//ServletContextHandler gère le servlet
		ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

		//Spécifiez la taille de téléchargement du formulaire
		servletHandler.setMaxFormContentSize(1024 * 1024 * 1024);

		//Ajouter un servlet
		servletHandler.addServlet(new ServletHolder(new ExampleServlet()), "/api");

		//ResourceHandler gère le contenu statique (en gros)
		final ResourceHandler resourceHandler = new ResourceHandler();

		//Spécifiez l'emplacement du contenu statique
		resourceHandler.setResourceBase(System.getProperty("user.dir") + "/htdocs");

		//Ne pas afficher la liste des fichiers de contenu statique (liste)
		resourceHandler.setDirectoriesListed(false);

		//Spécifiez le fichier à afficher initialement
		resourceHandler.setWelcomeFiles(new String[] { "index.html" });

		//Ne pas mettre en cache
		resourceHandler.setCacheControl("no-store,no-cache,must-revalidate");

		HandlerList handlerList = new HandlerList();

		//Spécifiez resourceHandler pour venir en premier (à l'inverse, le contenu statique ne sera pas appelé pour toujours.)
		handlerList.addHandler(resourceHandler);
		handlerList.addHandler(servletHandler);

		//Initialisez le serveur avec le constructeur par défaut
		final Server jettyServer = new Server();
		jettyServer.setHandler(handlerList);

		final int PORT = 8080;

		//classe de configuration http
		final HttpConfiguration httpConfig = new HttpConfiguration();

		//Ne mettez pas les informations de version du serveur dans l'en-tête
		httpConfig.setSendServerVersion(false);
		final HttpConnectionFactory httpConnFactory = new HttpConnectionFactory(httpConfig);
		final ServerConnector httpConnector = new ServerConnector(jettyServer, httpConnFactory);
		httpConnector.setPort(PORT);
		jettyServer.setConnectors(new Connector[] { httpConnector });

		try {
			jettyServer.start();
			jettyServer.join();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@SuppressWarnings("serial")
	public static class ExampleServlet extends HttpServlet {

		final ObjectMapper mObjectMapper = new ObjectMapper();

		final class Result {
			public boolean success;
			public String message;
		}

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

			//obtenir le paramètre de requête
			final String paramMessage = req.getParameter("message");

			//POJO pour le stockage des réponses(Convertir en JSON plus tard)
			final Result result = new Result();
			result.success = true;
			result.message = "You say '" + paramMessage + "'";

			// CORS(Cross-Origin Resource Sharing)Activer
			resp.addHeader("Access-Control-Allow-Origin", "*");
			resp.addHeader("Access-Control-Allow-Headers", "Content-Type");

			//Contenu qui renvoie JSON-Définir le type sur JSON
			final String CONTENT_TYPE = "application/json; charset=UTF-8";
			resp.setContentType(CONTENT_TYPE);

			final PrintWriter out = resp.getWriter();
			//Convertir POJO en JSON dans Jackson
			final String json = mObjectMapper.writeValueAsString(result);

			//Générer une réponse
			out.println(json);
			out.close();

		}

		@Override
		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Sorry, POST is not supported");
		}

		@Override
		protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Sorry, PUT is not supported");
		}

		@Override
		protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Sorry, DELETE is not supported");
		}

		@Override
		protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

			// For PreFlight Access
			// CORS(Cross-Origin Resource Sharing)Activer
			resp.addHeader("Access-Control-Allow-Origin", "*");
			resp.addHeader("Access-Control-Allow-Headers", "Content-Type");

		}

	}

		
}

Maven

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.12.v20180830</version>
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.12.v20180830</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8.1</version>
</dependency>

Code source

Le code source est ici https://github.com/riversun/jetty9-quick-start

en conclusion

Pour le fonctionnement détaillé de ** Jetty **, utilisez le motif de "Créer un serveur HTTPS avec 20 lignes!" [cet article](https: / /qiita.com/riversun/items/2909019123b28471ea79).

Recommended Posts

[Mise à jour décembre 2018] Astuces pour le serveur Web intégré et le serverlet créés avec Jetty9
Hello World avec Java Servlet et JSP (démarrage facile du serveur Web avec Maven + Jetty)
Parmi les trois serveurs Web embarqués Java, Tomcat, Jetty et Undertow, lequel fonctionnait sur GraalVM?
Serveur Web et serveur d'applications Rails
Comparaison du développement d'applications WEB avec Rails et Java Servlet + JSP
[Astuces] Comment résoudre les problèmes avec XCode et Swift pour les débutants