Professional Documents
Culture Documents
¿Está el
Servidor NO
Cargado?
SÍ
¿Es el
servidor NO Cargar Servlet
reciente?
SÍ
Procesar Petición
Enviar
Respuesta
Contenedor Tomcat
• El contenedor de Servlets más popular
• Open source, disponible en:
http://jakarta.apache.org/tomcat/
Instalando Tomcat 5
• Requisitos:
– Haber instalado Java
• Extraer fichero:
downloads\Tomcat5.5\jakarta-tomcat-
5.5.7.zip
• Crear las siguientes variables de entorno, por medio
de Panel de Control->Sistema-
>Avanzado->Variables de Entorno:
– TOMCAT_HOME=<TOMCAT_INSTALL_DIR>
6 Pasos Para Crear tu Primer Servlet
out.println("<html>");
out.println("<head>");
String title = rb.getString("helloworld.title");
out.println("<title>" + title + "</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h1>" + title + "</h1>");
out.println("</body>");
out.println("</html>");
}
}
Compilar el Código
• Guardar el código en %TOMCAT_HOME
%\webapps\myapp\WEB-INF\classes
• Compilar el código:
javac –classpath %TOMCAT_HOME
%\common\lib\servlet-api.jar
HelloWorldExample.java
Crear el web.xml
• Nombre recibido por el deployment descriptor
– Debe colocarse en el directorio WEB-INF
• web.xml es un documento XML que tiene
como elemento raíz: <web-app>
• Se pueden encontra n elementos <servlet>
que cuelgan de él
Crear el web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Servlet 2.4 Examples</display-name>
<description>
Servlet 2.4 Examples.
</description>
<servlet>
<servlet-name>HelloWorldExample</servlet-name>
<servlet-class>HelloWorldExample</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldExample</servlet-name>
<url-pattern>/HelloWorldExample</url-pattern>
</servlet-mapping>
</web-app>
Ejecutar el Código
• Arrancar Tomcat si es necesario, mediante el
comando: %TOMCAT_HOME
%\bin\catalina.bat run
• Invocar al servlet:
http://localhost:8080/myapp/Hel
loWorldExample
Resultado de Ejecutar Servlet
Servlets: Jerarquía
// examples\servlets\ej2_ciclovida_servlet
import javax.servlet.*;
import java.io.IOException;
public class CicloVidaServlet implements Servlet {
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("service");
}
public void destroy() {
System.out.println("destroy");
}
public String getServletInfo() {
return null;
}
public ServletConfig getServletConfig() {
return null;
}
}
Servlets: Operaciones duraderas
• Respuestas a peticiónes de clientes que
requieran de un tiempo de proceso muy largo.
• Puede que el servlet deba destruirse y estas
operaciones aun no hayan concluido.
• Es responsabilidad del programador
encargarse de su gestión.
Servlets: Operaciones duraderas
• Necesitaremos por tanto:
– Mantener un seguimiento de las tareas (threads) que se
estén ejecutando en el método “service”
– Proporcionar una finalización correcta haciendo que los
procesos largos que aun no hayan concluido puedan
terminar correctamente en el método “destroy” del
servlet.
– En ciertos casos poder terminar los procesos que aun
siguen en ejecución si es necesario.
Servlets: Operaciones duraderas
<servlet>
<servlet-name>ConfigDemoServletExample</servlet-name>
<servlet-class>ConfigDemoServlet</servlet-class>
<init-param>
<param-name>adminEmail</param-name>
<param-value>dipina@ilargi.org</param-value>
</init-param>
<init-param>
<param-name>adminContactNumber</param-name>
<param-value>6542214213</param-value>
</init-param>
</servlet>
Recuperando Configuración
• Recuperando información de configuración del fichero web.xml, revisar ejemplo
examples\servlets\ej3_configinfo_servlet
// ...
}
Contexto del Servidor
• ServletContext representa el entorno donde se ejecuta el servidor, es
decir, el Servlet Container
– Se puede obtener una referencia a él mediante el método
ServletConfig.getServletContext()
– Algunos métodos que se pueden utilizar son:
• getMajorVersion de la Servlet API soportada por el contenedor
• getMinorVersion
• setAttribute guarda un objeto en el ServletContext
• getAttributeNames
• getAttribute
• removeAttribute
• A través del contexto de un servlet se puede compartir estado entre varios
servlets.
• Revisar ejemplo
examples\servlets\ej4_contextinfo_servlet
Contexto del Servidor
ServletConfig servletConfig;
• POST: Lo mismo que GET pero los parámetros van en línea aparte dentro del cuerpo de
la petición. El manejo es idéntico pero a través del método “doPost”.
POST /cgi-bin/search.sh HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/vnd.ms-excel, application/vnd.ms-powerpoint,
application/msword, application/x-shockwave-flash, */*
Referer: http://localhost:9999/search.html
Accept-Language: es,eu;q=0.7,en-gb;q=0.3
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;
.NET CLR 1.1.4322)
Host: localhost:9999
Content-Length: 13
Connection: Keep-Alive
Cache-Control: no-cache
keyword=diego
Servlets: Métodos
• Por defecto retornan BAD_REQUEST(400)
• Son llamados desde el método “service”.
• Reciben interfaces instanciadas:
– “HttpServletRequest” para manejo de la
informacion enviada por el usuario.
– “HttpServletResponse” para poder enviar
una respuesta en forma de pagina web.
Servlets: Respondiendo en HTML
• 2 pasos:
– Indicar una cabecera de respuesta de contenido (antes de
cualquier tipo de respuesta)
• Una manera es usando el método “setHeader” de
“HttpServletResponse”.
• Al ser un proceso tan común existe un método que nos lo soluciona
directamente: “setContentType” de
“HttpServletResponse”.
– Crear y enviar código HTML válido.
• Revisar
examples\servlets\ej6_dogetdopost_se
rvlet
Ejemplo doGet() y doPost()
// compile: javac -classpath %TOMCAT_HOME%\common\lib\servlet-api.jar
DoGetDoPostServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
}
Ejemplo doGet() y doPost()
public void doPost(
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>The POST method</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("The servlet has received a POST. Thank you.");
out.println("</BODY>");
out.println("</HTML>");
}
}
Servlets: Recogiendo la información de
usuario.
• 2 formas de envío de información:
– En la línea URL mediante una ‘?’
– En una línea separada.
• En los antiguos CGIs el parseo era muy
complejo. En Servlets usar
“getParameter” de
“HttpServletRequest” que devuelve “”
(si no hay valor) o null (si no existe).
Servlets: Recogiendo la información de
usuario
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Obtaining the Parameter</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("The request's parameters are:<BR>");
Listando Parámetros Recibidos
Enumeration enumeration = request.getParameterNames();
while (enumeration.hasMoreElements()){
String parameterName = (String) enumeration.nextElement();
out.println(parameterName + ": " +
request.getParameter(parameterName) + "<BR>" );
}
out.println("<FORM METHOD=GET>");
out.println("<BR>First Name: <INPUT TYPE=TEXT NAME=FirstName>");
out.println("<BR>Last Name: <INPUT TYPE=TEXT NAME=LastName>");
out.println("<BR><INPUT TYPE=SUBMIT VALUE=Submit>");
out.println("</FORM>");
out.println("</BODY>");
out.println("</HTML>");
}
}
Servlets: Recogiendo la información de
usuario
• Cabeceras: Además de la información de la línea de
petición, datos añadidos opcionales (excepto
“Content-Length” en los métodos POST).
Accept Los tipos del formato MIME que acepta el navegador cliente.
Accept-Charset Los sets de caracteres que el navegador cliente espera.
Accept-Encoding Las codificaciónes de datos (por ejemplo gzip) que el
navegador cliente soporta y conoce. Así el servlet puede consultar
explícitamente información de codificación y así aprovechar las ventajas
de HTML gzipeado indicándolo en la cabecera de respuesta Content-
Encoding.
Servlets: Recogiendo la información de
usuario
Accept-Language El lenguaje que el navegador cliente espera.
Authorization Información de autentificación, que generalmente se crea
como respuesta a una cabecera WWW Authenticate enviada desde el
servidor.
Connection Indica si se va a usar conexión persistente. Si un servlet recibe
el valor Keep-Alive o una petición con una línea indicando HTTP 1.1
podrá hacer uso de las ventajas que estas ofrecen ahorrando tiempo en
páginas con muchos elementos pequeños como imágenes o applets. El
servlet ha de indicar el tamaño del contenido a enviar como respuesta
mediante la cabecera Content-Length. Para ello se puede usar la clase
ByteArrayOutputStream y al final enviar todos los datos.
Content-Length Usada en los mensajes POST para indicar el tamaño
de los datos.
Servlets: Recogiendo la información de
usuario
Cookie Una cabecera muy importante para envío de información.
From La dirección de email del cliente.
Host El host y el puerto sacados de la URL original.
If-Modified-Since Para indicar que solo han de enviarse documentos
posteriores al actual. Si no es así, se envía una respuesta 304 "Not
Modified".
Pragma Si contiene el valor no-cache indica que el servidor ha de enviar
una nueva copia del documento.
Referer La URL de la página que contenía el link que el cliente siguió para
llegar a la pagina actual.
User-Agent El tipo de navegador que usa el cliente. Es útil si se va enviar
contenido especifico para un tipo de navegador.
UA-Pixels, UA-Color, UA-OS, UA-CPU Cabeceras no estándar enviadas
desde IE indicando el tamaño de pantalla, la profundidad de color, el SO y
el tipo de cpu usado en el cliente.
Servlets: Recogiendo la información de
usuario
import java.util.*;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Enumeration enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String header = (String) enumeration.nextElement();
out.println(header + ": " + request.getHeader(header) + "<BR>");
}
}
}
Servlets: Políticas de acceso concurrente
(threading)
• Los servlets están diseñados para soportar múltiples
accesos simultáneos por defecto.
• El problema puede surgir cuando se hace uso de un
recurso compartido.
• Se exponen soluciones a poder considerar:
– Hacer que el servlet permita un único acceso cada vez.
– Hacer que el recurso sea el que posea la política de acceso
concurrente.
Servlets: Políticas de acceso concurrente
(threading)
• Para hacer que el servlet trate a un cliente cada
vez, únicamente hay que hacer que nuestra
clase, además de heredar de
“HttpServlet”, implemente la interfaz
“SingleThreadModel” que es una interfaz
sin métodos.
Servlets: Accediendo a variables CGI
• Una colección de información derivada de muchos
elementos que es accesible a través del objeto
“HttpServletRequest” y el contexto del
servlet.
• Estas variables pueden ser proporcionadas por:
– La petición (la línea de petición o parte del URI o las
cabeceras).
– Del socket en sí (la IP).
– De los parámetros de instalación del servidor web (los
mapeos de las URL a los paths).
Servlets: Accediendo a variables CGI
AUTH_TYPE
El esquema especificado si se recibe una cabecera Authorization. Puede ser basic o
digest.
request.getAuthType()
CONTENT_LENGTH
Solo para peticiónes POST e indica el numero de bytes enviados.
String.valueOf(request.getContentLength()) o
request.getContentLength
CONTENT_TYPE
El tipo de MIME.
request.getContentType()
DOCUMENT_ROOT
La ruta el directorio http://host/
getServletContext().getRealPath("/")
http_XXX_YYY
Acceso a librerías HTTP
request.getHeader("Xxx-Yyy")
Servlets: Accediendo a variables CGI
PATH_INFO
Información de path añadida a la petición. De todas formas no tiene por que ser tratada de
manera independiente (no como en los CGIs).
request.getPathInfo()
PATH_TRANSLATED
Información de path de mapeo en el las rutas reales del servidor.
request.getPathTranslated()
QUERY_STRING
Para las peticiónes GET. Es un string aun codificado en URL. Mejor usar
request.getParameter
request.getQueryString()
REMOTE_ADDR
La IP del cliente.
request.getRemoteAddr()
REMOTE_HOST
El nombre de dominio del cliente. Si no se puede devuelve la IP.
request.getRemoteHost()
Servlets: Accediendo a variables CGI
REMOTE_USER
La parte de usuario de una cabecera Authorization.
request.getRemoteUser()
REQUEST_METHOD
El tipo de petición: GET, POST, HEAD, PUT, DELETE, OPTIONS, o TRACE.
request.getMethod()
SCRIPT_NAME
El path al servlet
request.getServletPath()
SERVER_NAME
El nombre del servidor web
request.getServerName()
SERVER_PORT
El numero del puerto donde el servidor web esta “escuchando”.
Equivalente a String.valueOf(request.getServerPort()) Pero directamente…
request.getServerPort()
Servlets: Accediendo a variables CGI
SERVER_PROTOCOL
Nombre y versión usados en la línea de petición (e.i. HTTP/1.0 or HTTP/1.1).
request.getProtocol()
SERVER_SOFTWARE
Información de identificación del servidor web
getServletContext().getServerInfo()
Servlets: Respondiendo: Códigos de
estado
• La respuesta esta compuesta por:
– Una línea de estado (200 OK).
– Cabeceras de respuesta.
– Una línea en blanco.
– Un documento.
• La línea de estado indica la versión del protocolo http
y un código de estado para indicar diferente
información al cliente:
– Enviar al usuario a otros enlaces.
– Indicar que el contenido es una imagen, PDF...
– Requerir un password.
Servlets: Respondiendo: Códigos de
estado
// Revisar: examples\servlets\ej11_forward_servlet
RequestDispatcher rd =
request.getRequestDispatcher("SecondServlet");
rd.forward(request, response);
Gestión de Sesiones
• HTTP no tiene estado
• Necesario utilizar trucos para permitirlo:
– Reescritura de urls
– Campos hidden <input type=“hidden”
name=“saludo” value=“hola”>
– Cookies
– HttpSession
Servlets: Respondiendo: Cookies
• Pequeños trozos de información textual que el
servidor puede enviar al cliente y que éste no
modifica y reenvía al servidor cuando vuelve a visitar
el mismo sitio.
– Identificar a un usuario concreto.
– Para sitios con baja necesidad de seguridad, poder evitar el
login y password.
– Personalizar las webs recordando cada peculiaridad de
cliente.
– Publicidad enfocada (personalizada) dado que se puede
almacenar información sobre las preferencias del usuario
mientras navega, busca información etc.
Servlets: Respondiendo: Cookies
• Las cookies no son un grave problema de seguridad.
• Los navegadores sólo permiten 20 cookies por sitio
web y 300 en total.
• Limitadas a 4kb.
• Pueden ser un problema de privacidad. Puede que
algunos usuarios desactiven las cookies por diversas
razones por lo que no se recomienda depender
completamente del uso de ellas.
Servlets: Respondiendo: Cookies
API JD BC
G e s t o r d e D r iv e r s
D r iv e r A P I
P r o to c o lo
A P I N a tiv o D r iv e r d e R e d
J D B C -O D B C N a tiv o
P a rte e n J a v a e n J a v a P u ro
T ip o 1 D r iv e r e n J a v a
T ip o 2 T ip o 3
T ip o 4
P r o to c o lo
de R ed
G e s to r d e D r iv e r d e P r o p ie ta r io
D r iv e r O D B C S G B D N a t iv o
S e r v id o r
D r iv e r O D B C
D r iv e r d e
S G B D N a tiv o
P r o to c o lo P r o to c o lo P r o to c o lo P r o to c o lo
SG BD SG BD SG BD SG BD
N a tiv o N a tiv o N a tiv o N a t iv o
JDBC de Javasoft: arquitectura II
• Gestor de drivers es núcleo de arquitectura y
comunica aplicaciones Java con cuatro tipos
diferentes de drivers:
– Puente ODBC-JDBC más el driver ODBC
• Traduce JDBC en ODBC
• No adecuado si parte cliente es anónima
– Necesidad de registrar fuente ODBC en cada máquina
• Uso: aplicaciones de dos capas en red local
JDBC de Javasoft: arquitectura III
– API Nativo parte en Java:
• Traduce JDBC en protocolo específico de BD: Oracle JDBC/OCI
driver
• Requieren algo de código nativo en cada máquina cliente en forma
de un driver específico que se debe instalar
• Uso: servidores RMI, servlets
– Driver de Red en Java Puro:
• Utiliza protocolo comunicaciones publicado para la comunicación
con un servidor remoto
• Servidor se comunica con la BD utilizando ODBC o un driver
nativo
• Java puro: applets se descarga lo mínimo
• No requiere código instalado en máquina cliente
JDBC de Javasoft: arquitectura IV
– Protocolo nativo en Java Puro:
• Implementan protocolo de BD de un suministrador
• Específicos para BD concreta
• No tienen necesidad de intermediarios
• Alto rendimiento
JDBC URLs
• Carga de un driver
– Crea instancia de si mismo
– Se registra con el gestor
String myDriver =
“sun.jdbc.odbc.JdbcOdbcDriver”;
Class.forName(myDriver);
• Conexión a la BD:
String url = “jdbc:odbc:clientes”;
String user = “dba”;
String pass = “sql”;
Connection dbCon =
DriverManager.getConnection(url, user,
pass);
JDBC API: java.sql.* II
• Otras posibilidades:
– PreparedStatement, se genera el plan de acceso la
primera vez que se solicita la ejecución
PreparedStatement ps =
dbCon.prepareStatement(“sqlString”);
– CallableStatement procedimientos almacenados
– Acceso al esquema o metadatos
– Control transaccional superficial
• Defecto automático (1 SQL 1 commit)
• Deshabilitar (N SQL 1 commit o rollback)
dbCon.setAutoCommit(false);
…
dbCon.commit();
Un ejemplo JDBC
import java.sql.*;
…
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:CuentasBD";
con = DriverManager.getConnection(url, "", "");
stmt = con.createStatement();
Vector cuentas = new Vector();
String sql = "select * from CUENTAS order by
numeroCTA";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
cuentas.add(new
CuentaBancaria(rs.getString("numeroCTA"),
rs.getDate("fechaExpiracion"),
rs.getFloat("saldo")));
}
stmt.close();
con.close();
SQL Inmerso (Embedded SQL – ESQL)
ESTÁTICO
• El lenguaje de programación junto con el cual se utiliza
SQL se denomina lenguaje anfitrión
• Objetivo: insertar sentencias SQL en aplicaciones
codificadas en cualquier lenguaje:
– C, C++, COBOL, FORTRAN, Pascal, ADA y Java
– Identificadores especiales para cada lenguaje, se usan para
separar las instrucciones de SQL inmerso y el código del
lenguaje anfitrión:
• Java SQLJ:
– # sql {insert into Pedidos values(:p1
:p2};
• C PRO*C:
– EXEC SQL DECLARE stu_cursor CURSOR FOR
SELECT * FROM STUDENT ORDER BY NAME;
• Precompilador genera código en lenguaje apropiado a
partir de las sentencias SQL incrustadas
SQL Embebido (Embedded SQL –
ESQL) (cont)
• Ventajas:
– Verificación de sintaxis en tiempo de
compilación mayor eficiciencia
• Desventajas:
– BD debe ser conocida y su esquema accesible
en tiempo de compilación
– Precompiladores no estándar y propietario
para cada BD
SQLJ vs. JDBC
String vName; int vSalary; String vJob;
Java.sql.Timestamp vDate;
... ESTÁTICO SQLJ
#sql { SELECT Ename, Sal
INTO :vName, :vSalary
FROM Emp
WHERE Job = :vJob and HireDate = :vDate };
firstName = request.getParameter("firstName");
lastName = request.getParameter("lastName");
userName = request.getParameter("userName");
password = request.getParameter("password");
Statement s = con.createStatement();
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws
ServletException {
System.out.println("Filter initialized");
this.filterConfig = filterConfig;
}
}
Web.xml
<web-app>
<filter>
<filter-name>
Trim Filter
</filter-name>
<filter-class>
TrimFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>
Trim Filter
</filter-name>
<servlet-name>
DoublyFilteredServlet
</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>
DoublyFilteredServlet
</servlet-name>
<servlet-class>
DoublyFilteredServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DoublyFilteredServlet</servlet-name>
<url-pattern>/servlet/DoublyFilteredServlet</url-pattern>
</servlet-mapping>
</web-app>
Servlet
• Son flexibles y muy potentes
• Sin embargo, es muy lioso mezclar código de
marcado y código Java
– A menudo hay más código de marcado que código
Java
• SOLUCIÓN JSP