Configurando Servlets y JSP en Jetty
Jetty es un servidor web ligero y flexible que se utiliza ampliamente en aplicaciones Java. En esta entrada, veremos cómo configurar un proyecto básico que utiliza servlets y JSP en Jetty, ideal para aprender los fundamentos antes de pasar a frameworks más avanzados como Spring Boot.
Requisitos previos
- Tener conocimientos básicos de Java y familiaridad con conceptos web como HTTP.
- Contar con Maven para gestionar dependencias.
- Tener instalado un JDK (Java Development Kit) compatible, como JDK 8 o superior.
- Cualquier ide para trabajar con Java (Yo estoy familiarizado con Netbeans, pero puedes elegir el que deseas.)
Paso 1: Crear el Proyecto Maven
Estructura del Proyecto
mi-proyecto/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── ejemplo/ │ │ │ ├── servlet/ │ │ │ │ ├── HolaMundoServlet.java │ │ │ │ └── IndexServlet.java │ │ │ └── AppMain.java │ └── webapp/ │ ├── WEB-INF/ │ │ ├── web.xml │ │ └── jsp/ │ │ └── index.jsp └── pom.xml
Se debe crear un proyecto Maven de tipo aplicación de consola o aplicación Java, que integre Jetty embebido en el proyecto. Además, debe incluir las dependencias necesarias para soportar Servlets y JSP, y estar empaquetado como un JAR ejecutable.
Paso 2: Editar el archivo pom.xml
En Maven, necesitamos definir las dependencias y plugins necesarios para Jetty. Aquí tienes un ejemplo básico:
<?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.ejemplo</groupId> <artifactId>servlet</artifactId> <version>1.0</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.release>17</maven.compiler.release> <exec.mainClass>com.ejemplo.AppMain</exec.mainClass> </properties> <!-- DEPENDENCIA DE JSON (OPCIONAL) --> <dependencies> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> <!-- Reemplaza con la última versión disponible --> </dependency> <!-- DEPENDENCIAS NECESARIAS DE JETTY PARA CORRER JSP y servlets --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>11.0.23</version> </dependency> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>11.0.23</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jsp</artifactId> <version>11.0.23</version> </dependency> <!-- JSTL (Jakarta Standard Tag Library) --> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>2.0.0</version> </dependency> <!-- Additional Jetty Dependencies --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-annotations</artifactId> <version>11.0.23</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-plus</artifactId> <version>11.0.23</version> </dependency> <!-- DEPENDENCIA DE MYSQL (OPCIONAL) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies> <build> <plugins> <!-- Plugin para compilar con Java 21 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> <!-- Plugin para ejecutar la aplicación desde Maven --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.0.0</version> <configuration> <mainClass>com.ejemplo.AppMain</mainClass> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.7.1</version> <!-- Usa la versión más reciente disponible --> <configuration> <archive> <manifest> <mainClass>com.ejemplo.AppMain</mainClass> <!-- Cambia al nombre de tu clase principal --> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
Dependencias Opcionales en el pom.xml
En el archivo pom.xml
de este proyecto, se han añadido las siguientes dependencias como opcionales, ya que su uso depende de las necesidades específicas de cada implementación:
Estas dependencias no son estrictamente necesarias para el funcionamiento básico del servlet. Su inclusión se basa en los requisitos específicos del proyecto, como trabajar con JSON o conectarse a una base de datos MySQL. Si no las necesitas, puedes eliminarlas sin afectar la configuración del servlet.
Paso 3: Crear un Servlet.
Ahora crearemos un servlet llamado HolaMundoServlet
, que es una clase Java encargada de procesar solicitudes HTTP y devolver una respuesta. En este caso, el servlet responderá con un mensaje 'Hola Mundo' en formato HTML.
package com.ejemplo.servlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class HolaMundoServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // Establecer el tipo de contenido como HTML response.setContentType("text/html"); // Obtener el flujo de salida para escribir la respuesta PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head><title>Hola Mundo Servlet</title></head>"); out.println("<body>"); out.println("<h1>¡Hola Mundo desde el Servlet!</h1>"); out.println("</body>"); out.println("</html>"); // Imprimir un mensaje en HTML } }
Explicación:
- Extiende
HttpServlet
: La clase HolaMundoServlet
extiende de HttpServlet
, que es la clase base para crear servlets en Java. - Método
doGet
: El método doGet
se utiliza para manejar solicitudes HTTP GET. Aquí es donde se define la lógica para responder a la solicitud. PrintWriter
para la salida: Usamos el objeto PrintWriter
para enviar contenido al navegador. En este caso, estamos enviando una respuesta HTML simple con un encabezado que dice "¡Hola Mundo desde el Servlet!".- Establecer el tipo de contenido:
response.setContentType("text/html")
asegura que la respuesta sea interpretada como HTML por el navegador.
HttpServlet
: La clase HolaMundoServlet
extiende de HttpServlet
, que es la clase base para crear servlets en Java.doGet
: El método doGet
se utiliza para manejar solicitudes HTTP GET. Aquí es donde se define la lógica para responder a la solicitud.PrintWriter
para la salida: Usamos el objeto PrintWriter
para enviar contenido al navegador. En este caso, estamos enviando una respuesta HTML simple con un encabezado que dice "¡Hola Mundo desde el Servlet!".response.setContentType("text/html")
asegura que la respuesta sea interpretada como HTML por el navegador.Paso 4: Crear el IndexServlet
En esta parte, crearemos el IndexServlet
, que será el encargado de mostrar la página principal de la aplicación. Este servlet se encargará de responder a las solicitudes en la raíz de la aplicación (/
) y redirigir al usuario al archivo JSP correspondiente, en este caso, index.jsp
.
El código para el IndexServlet
es el siguiente:
package com.ejemplo.servlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class IndexServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // Redirigir al archivo JSP (index.jsp) request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response); } }
Explicación del código:
doGet
: Este método maneja las solicitudes GET. Cuando el usuario accede a la URL raíz de la aplicación, el servlet captura la solicitud y la redirige a la página JSP.request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response);
: Esta línea le indica al servlet que, en lugar de devolver contenido HTML directamente, debe reenviar la solicitud al archivo JSPindex.jsp
dentro de la carpetaWEB-INF/jsp
. La ventaja de usar esta ruta es que los archivos JSP en la carpetaWEB-INF
no son accesibles directamente desde la URL, lo que mejora la seguridad.
Paso 5: Crear el archivo index.jsp
El archivo index.jsp
es el archivo que se mostrará al usuario cuando acceda a la aplicación a través de la URL raíz (/
). Este archivo es procesado por el servlet IndexServlet
, que redirige la solicitud hacia él.
Aquí tienes un ejemplo básico de contenido para el archivo index.jsp
:
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bienvenido a la Aplicación Jetty</title>
</head>
<body>
<h1>¡Bienvenido a la aplicación con Jetty!</h1>
<p>Esta es la página principal de la aplicación. Estás viendo un archivo JSP que fue procesado por un servlet.</p>
<p>Para más información, consulta la documentación o explora los otros recursos de la aplicación.</p>
</body>
</html>
web.xml
en Jetty embebidoweb.xml
cuando configuramos un proyecto embebido. Por ello, es necesario crearlo manualmente para definir los servlets, mapeos y otras configuraciones.El archivo web.xml
es el descriptor de despliegue de la aplicación web, donde se configuran servlets, filtros y otros componentes clave de la aplicación.
A continuación, te mmuestro cómo hacerlo:
1. Ubicación del archivo web.xml
El archivo web.xml
debe colocarse en la siguiente ruta dentro de tu proyecto Maven:
src/main/webapp/WEB-INF/web.xml
web.xml
Agrega la siguiente configuración básica al archivo:
<?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>HolaMundoServlet</servlet-name>
<servlet-class>com.ejemplo.servlet.HolaMundoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HolaMundoServlet</servlet-name>
<url-pattern>/holaMundo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>IndexServlet</servlet-name>
<servlet-class>com.ejemplo.servlet.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexServlet</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>IndexServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- CON ESTA CONFIGURACION INDICO EL RUTEO DE LOS RECURSOS ESTATICOS Y SUS RESPECTIVAS CARPETAS SEAN SCRIPTS HTML Y CSS -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/scripts/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/messageview/*</url-pattern>
</servlet-mapping>
</web-app>
Agrega la siguiente configuración básica al archivo:
<?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>HolaMundoServlet</servlet-name>
<servlet-class>com.ejemplo.servlet.HolaMundoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HolaMundoServlet</servlet-name>
<url-pattern>/holaMundo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>IndexServlet</servlet-name>
<servlet-class>com.ejemplo.servlet.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>IndexServlet</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>IndexServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- CON ESTA CONFIGURACION INDICO EL RUTEO DE LOS RECURSOS ESTATICOS Y SUS RESPECTIVAS CARPETAS SEAN SCRIPTS HTML Y CSS -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/scripts/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/messageview/*</url-pattern>
</servlet-mapping>
</web-app>
Explicación del Código:
- Definición del Servlet: En
<servlet>
, se especifican el nombre del servlet (HolaMundoServlet
) y la clase Java que lo implementa (com.ejemplo.servlet.HolaMundoServlet
).
- Mapeo del Servlet: En
<servlet-mapping>
, se asocia el servlet con una URL específica (/holaMundo
). Esto permite que el servlet responda cuando se accede a esa ruta.
<servlet>
, se especifican el nombre del servlet (HolaMundoServlet
) y la clase Java que lo implementa (com.ejemplo.servlet.HolaMundoServlet
).<servlet-mapping>
, se asocia el servlet con una URL específica (/holaMundo
). Esto permite que el servlet responda cuando se accede a esa ruta.Opción con Anotaciones (Servlet 4.0 o superior)
Si tu servidor soporta Servlet 4.0 o superior, puedes simplificar la configuración usando anotaciones. Esto elimina la necesidad de modificar el archivo web.xml
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/holaMundo")
public class HolaMundoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getWriter().write("¡Hola, Mundo!");
}
}
Con la anotación @WebServlet("/holaMundo")
, el servlet se registra automáticamente y estará accesible en la ruta /holaMundo
.
Nota: Aunque este método es más simple, es posible que se requieran configuraciones adicionales dependiendo de tu entorno o del servidor de aplicaciones que estés utilizando.
¿Cuál Opción Usar?
- Sin Anotaciones (Uso de
web.xml
): Ideal para aplicaciones más tradicionales o cuando se necesita un control explícito. - Con Anotaciones: Recomendado para proyectos modernos, siempre que el servidor soporte Servlet 4.0 o superior.
Consideraciones Finales
Si eliges usar anotaciones, verifica la compatibilidad de tu servidor y considera que algunas configuraciones, como la gestión de dependencias o la inicialización de recursos, podrían necesitar ajustes adicionales. Si enfrentas problemas, siempre puedes optar por el método basado en web.xml
.
Clase principal para iniciar Jetty: AppMain
La siguiente clase define la configuración principal para iniciar un servidor Jetty embebido en el puerto 9090 y servir JSPs y Servlets desde el proyecto Maven. Este ejemplo es completamente funcional y puede ser adaptado a tus necesidades.
Código de la clase AppMain
package com.ejemplo; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; /** * Clase principal para configurar y levantar el servidor Jetty. */ public class AppMain { public static void main(String[] args) throws Exception { // Crear una instancia del servidor en el puerto 9090 Server server = new Server(9090); // Configurar el contexto web para JSP y Servlets WebAppContext context = new WebAppContext(); context.setContextPath("/"); // Define el path base de la aplicación context.setResourceBase("src/main/webapp"); // Carpeta que contiene los JSP y recursos estáticos context.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false"); // Deshabilita el listado de directorios context.setParentLoaderPriority(true); // Prioriza el ClassLoader del servidor // Asignar el contexto al servidor server.setHandler(context); // Iniciar el servidor server.start(); server.join(); } }
Arranque del Proyecto con Jetty
Generación y ejecución desde el IDE:
Una vez con el proyecto construido y configurado con Jetty en el archivopom.xml
, compílalo y ejecútalo directamente desde tu IDE. Esto iniciará el servidor Jetty embebido.Acceso al proyecto desplegado:
Una vez que el servidor Jetty esté en funcionamiento, podrás acceder a la aplicación desde la siguiente URL:
http://localhost:9090/
El navegador mostrará el siguiente resultado
Probar el Servlet "Hola Mundo"
Accede al servlet desde el navegador:
Una vez que el servidor esté en ejecución, abre tu navegador y visita la siguiente URL para probar el servlet HolaMundoServlet
:
http://localhost:9090/holaMundo
El resultado será:Para finalizar
Espero que esta guía te haya sido útil para configurar y poner en marcha un proyecto con Jetty, gestionar servlets y probar su funcionamiento. Ten en cuenta que, al utilizar JSP, pueden surgir limitaciones en la depuración debido a la integración con el servidor embebido.
Si deseas explorar más a fondo el proyecto o probarlo directamente, he dejado el código fuente disponible para su descarga. Aquí
No dudes en dejar un comentario si tienes alguna duda o sugerencia. ¡Feliz desarrollo y éxito con tus proyectos!
Comentarios
Publicar un comentario