Diapositiva 1

Download Report

Transcript Diapositiva 1

Tema 1- Servlets
Dr. Diego Lz. de Ipiña Gz. de Artaza
http://paginaspersonales.deusto.es/dipina
http://paginaspersonales.deusto.es/dipina/cursos/J2EECesine.zip
[email protected]
Introducción


Necesidad de mecanismos para desarrollar
“aplicaciones web”  contenido dinámico
Cuando escribes una URL en tu navegador:





El navegador establece una conexión TCP/IP con
el servidor
El navegador envía una petición al servidor
El servidor devuelve una respuesta al cliente
El servidor cierra la conexión
Los mensajes intercambiados entre el cliente
y el servidor son HTTP
HTTP


Especificación de HTTP:
http://www.w3.org/Protocols/rfc2616/rf
c2616.html
Básicamente debemos saber que los
comandos principales son HTTP GET y
POST.
Tecnología Servlet

Piedra angular del desarrollo de
aplicaciones web en Java

Los JSPs son de hecho servlets
“disfrazados”
Características de los Servlets

Pensados para reemplazar a los CGIs


Cada petición de un cliente hacía al
servidor lanzar un nuevo proceso con el
programa CGI
No es la única tecnología disponible:


ASP.NET
PHP (plataforma LAMP)
Ventajas





Rendimiento  cada petición es procesada
por un único proceso en el contenedor de
servlets
Portabilidad  heredado de Java
Rápido desarrollo  acceso a las
riquísimas librerías de Java
Robustez  gestionados por la máquina
virtual de Java (garbage collection)
Amplio soporte  muchos desarrolladores
y compañías utilizan esta tecnología
Arquitectura
Servlet Container = servidor web capaz
de ejecutar servlets
En una aplicación JSP, el contenedor se
corresponde a un JSP container.


Servlet Container
HTTP Request
Browser
HTTP Response
HTTP Server
Contenido Estático
Servlet
Funcionamiento de un Servlet
Recibir
Petición
¿Está el
Servidor
Cargado?
NO
SÍ
¿Es el
servidor
reciente?
SÍ
Procesar Petición
Enviar
Respuesta
NO
Cargar Servlet
Contenedor Tomcat 5




El contenedor de Servlets más popular
Actualmente en la versión 5.0
Open source, disponible en:
http://jakarta.apache.org/tomcat/
Vamos a instalarlo ...
Instalando Tomcat 5

Requisitos:



Haber instalado Java 5
Extraer fichero:
downloads\Tomcat5.5\jakartatomcat-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
1.
2.
3.
4.
5.
6.
Crear una estructura de directorios
bajo Tomcat para tu aplicación
Escribir el código del servlet
Compilar el código
Crear un descriptor de explotación
(deployment descriptor)
Ejecutar Tomcat
Invocar el servlet desde un navegador
Crear directorio bajo Tomcat
para tu aplicación
El directorio %TOMCAT_HOME%/webapps es dónde cuelgas
tus aplicaciones
Una aplicación web es un conjunto de servlets y otros
recursos instalados bajo el espacio URL de un servidor
Pasos:



1.
2.
Crear un directorio bajo webapps con el nombre de tu aplicación
‘myapp’, que aparecerá en la url a tu aplicación
Crear el directorio WEB-INF debajo de ‘myApp’


Crear subdirectorio clases
Crear subdirectorio lib
Podéis hacer copy/paste del contenido del directorio
examples\servlets\ej1_holamundo_servlet bajo
%TOMCAT_HOME\webapps\myapp


Vamos a reutilizar continuamente el contexto
myapp
Escribir el Código del Servlet
// HelloWorldExample.java
import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorldExample extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
ResourceBundle rb =
ResourceBundle.getBundle("LocalStrings",request.getLocale());
response.setContentType("text/html");
PrintWriter out = response.getWriter();
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\W
EB-INF\classes
Compilar el código:
javac –classpath
%TOMCAT_HOME%\common\lib\servle
t-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.ba
t run
Invocar al servlet:
http://localhost:8080/myapp/H
elloWorldExample
Resultado de Ejecutar Servlet
Servlets: Jerarquía


La jerarquía de clases java es...
Únicamente hay que hacer polimorfismo
de los métodos que se quieran tratar.
Las APIs

Dos paquetes permiten la programación
de servlets:



javax.servlet
javax.servlet.http
Revisar documentación:


Arrancar Tomcat
Visitar: http://localhost:8080
Servlets: Ciclo de vida

Ciclo de vida de un servlet:
Servlets: Ciclo de vida



Viene dado por tres métodos: init, service y
destroy
INICIALIZACIÓN: Una única llamada al método
“init” por parte del servidor. Incluso se pueden
recoger unos parametros concretos con
“getInitParameter” de “ServletConfig”.
SERVICIO: una llamada a service() por cada
invocación al servlet



¡Cuidado! El contenedor es multihilo
DESTRUCCIÓN: Cuando todas las llamadas desde
el cliente cesen o un temporizador del servidor así lo
indique. Se usa el método “destroy”
Revisar documentación de la clase
javax.servlet.Servlet
Demostrando el Ciclo de Vida
// 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

Posible solución: Contador
public ShutdownExample extends HttpServlet {
private int serviceCounter = 0;
private Object lock = new Object();
protected void enteringServiceMethod() {
synchronized(lock) { serviceCounter++; }
}
protected void leavingServiceMethod(){
synchronized(lock) {
serviceCounter--;
if (serviceCounter == 0 && isShuttingDown()) notifyAll();
}
}
protected int numServices() {
synchronized(lock) { return serviceCounter; }
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
enteringServiceMethod();
try { super.service(req, resp); }
finally { leavingServiceMethod(); }
}
Servlets: Operaciones
duraderas

Falta indicar la terminación.
public ShutdownExample extends HttpServlet {
private boolean shuttingDown;
protected void setShuttingDown(boolean flag) {
shuttingDown = flag;
}
protected boolean isShuttingDown() {
return shuttingDown;
}
public void destroy() {
synchronized(lock) {
if (numServices() > 0) {
setShuttingDown(true);
}
while(numServices() > 0) {
try { wait(); }
catch (InterruptedException e) {
}
}
}
}
}
Recuperando Configuración

Recuperando información de configuración del fichero web.xml
<servlet>
<servlet-name>ConfigDemoServletExample</servlet-name>
<servlet-class>ConfigDemoServlet</servlet-class>
<init-param>
<param-name>adminEmail</param-name>
<param-value>[email protected]</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
public class ConfigDemoServlet implements Servlet {
ServletConfig cfg;
public void init(ServletConfig config) throws ServletException {
this.cfg = config;
Enumeration parameters = config.getInitParameterNames();
while (parameters.hasMoreElements()) {
String parameter = (String) parameters.nextElement();
System.out.println("Parameter name : " + parameter);
System.out.println("Parameter value : " +
config.getInitParameter(parameter));
}
}
// ...
}
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;
public void init(ServletConfig config) throws ServletException {
servletConfig = config;
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
ServletContext servletContext = servletConfig.getServletContext();
Enumeration attributes = servletContext.getAttributeNames();
while (attributes.hasMoreElements()) {
String attribute = (String) attributes.nextElement();
System.out.println("Attribute name : " + attribute);
System.out.println("Attribute value : " +
servletContext.getAttribute(attribute));
}
System.out.println("Major version : " + servletContext.getMajorVersion());
System.out.println("Minor version : " + servletContext.getMinorVersion());
System.out.println("Server info : " + servletContext.getServerInfo());
}
Peticiónes y Respuestas

En el método service() los parámetros:



ServletRequest tiene los siguientes métodos:





getParameterNames
getParameter
getRemoteAddress
getRemoteHost
ServletResponse tiene entre otros el método:


ServletRequest representa la petición del cliente y
ServletResponse la respuesta del servidor
getWriter
Revisar
examples\servlets\ej5_requestresponse_servlet
Ejemplo ServletRequest y
ServletResponse
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<HTML>");
// ...
out.println("<BR>Server Port: " + request.getServerPort());
out.println("<BR>Server Name: " + request.getServerName());
out.println("<BR>Protocol: " + request.getProtocol());
out.println("<BR>Character Encoding: " + request.getCharacterEncoding());
out.println("<BR>Content Type: " + request.getContentType());
out.println("<BR>Content Length: " + request.getContentLength());
out.println("<BR>Remote Address: " + request.getRemoteAddr());
out.println("<BR>Remote Host: " + request.getRemoteHost());
out.println("<BR>Scheme: " + request.getScheme());
Enumeration parameters = request.getParameterNames();
while (parameters.hasMoreElements()) {
String parameterName = (String) parameters.nextElement();
out.println("<br>Parameter Name: " + parameterName);
out.println("<br>Parameter Value: " +
request.getParameter(parameterName));
}
Enumeration attributes = request.getAttributeNames();
while (attributes.hasMoreElements()) {
String attribute = (String) attributes.nextElement();
out.println("<BR>Attribute name: " + attribute);
out.println("<BR>Attribute value: " + request.getAttribute(attribute));
}
out.println("</BODY>");
out.println("</HTML>");
}
Clase GenericServlet

El uso de la interfaz Servlet tiene dos
inconvenientes:



Hay que proveer implementaciones de los
cinco métodos de Servlet
Hay que cachear la referencia a
ServletConfig pasada como parámetro
La clase GenericServlet provee una
implementación vacía de los 5 métodos
de Servlet y recuerda ServletConfig
Ejemplo GenericServlet
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class SimpleServlet extends GenericServlet {
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>");
out.println("Extending GenericServlet");
out.println("</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("Extending GenericServlet makes your code simpler.");
out.println("</BODY>");
out.println("</HTML>");
}
}
Paquete
javax.servlet.http



Normalmente siempre vamos a trabajar con
él cuando programemos servlets.
Sus miembros y métodos son más
convenientes y ofrecen más funcionalidad
Principalmente vamos a tratar con tres clases:



HttpServlet
HttpServletRequest
HttpServletResponse
HttpServlet


Hereda de GenericServlet
Tiene 6 métodos doXXX que son invocados
cada vez que el correspondiente comando
HTTP es recibido:






doPost
doPut
doGet
doDelete
doOptions
doTrace
Servlets: Explicación de
métodos HTTP

GET: Paso de parámetros en la propia URL de acceso
al servicio o recurso del servidor. Método “doGet”
GET /query.html?keyword='diego' HTTP/1.1
Accept: image/gif, image/x-xbitmap,
image/jpeg, image/pjpeg, application/vnd.msexcel, application/vnd.ms-powerpoint,
application/msword, application/x-shockwaveflash, */*
Accept-Language: es,eu;q=0.7,en-gb;q=0.3
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
Connection: Keep-Alive
Servlets: Explicación de
métodos HTTP

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.*;
public class DoGetDoPostServlet extends HttpServlet {
public void doGet(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 GET method</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("The servlet has received a GET. " +
"Now, click the button below.");
out.println("<BR>");
out.println("<FORM METHOD=POST>");
out.println("<INPUT TYPE=SUBMIT VALUE=Submit>");
out.println("</FORM>");
out.println("</BODY>");
out.println("</HTML>");
}
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




Si el parametro tiene mas de un valor se usa
“getParameterValues” de “HttpServletRequest”
que devuelve un array de strings.
Los nombres de los parametros son accesibles mediante
“getParameterNames” de “HttpServletRequest”
que devuelve un Enumeration de strings.
Se puede leer la línea directamente con “getReader” o
“getInputStream” de “HttpServletRequest”.
Revisar:
examples\servlets\ej7_listparams_servlet
Listando Parámetros Recibidos
// compile: javac -classpath %TOMCAT_HOME%\common\lib\servlet-api.jar
PruebaServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class PruebaServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
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

Los métodos para acceder a estas cabeceras son:




“getHeader” de “HttpServletRequest” que
devuelve un String.
“getHeaderNames” de “HttpServletsRequest”
que devuelve un Enumeration de strings.
Puede que algunos clientes recojan información
de un servlet. Para ello se puede hacer
polimorfismo del método “getServletInfo”
que debe devolver un String.
Revisar:
examples\servlets\ej8_listheaders_se
rvlet
Listando Cabeceras
http://localhost:8080/myapp/servlet/PruebaServlet
// compile: javac -classpath %TOMCAT_HOME%\common\lib\servlet-api.jar
PruebaServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

import java.util.*;
public class PruebaServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
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

La línea de estado consta de:




Versión del protocolo HTTP: La suministra
el servidor.
El código de estado: Lo podemos indicar
nosotros. Usar el método “setStatus” de
“HttpServletResponse”.
Un mensaje: Suele estar relacionado con el
código de estado.
El código debe indicarse antes de cualquier
acceso al PrintWriter.
Ejemplo HTTP Response
HTTP/1.1 200 OK
Date: Thu, 06 Aug 1998 12:00:15 GMT
Server: Apache/1.3.0 (Unix)
Last-Modified: Mon, 22 Jun 1998 09:23:24
GMT
Content-Length: 6821
Connection: close
Content-Type: text/html
Cuerpo de la respuesta ...
Servlets: Respondiendo:
Códigos de estado

Aunque “setStatus” es la manera más
flexible, hay unos códigos muy comunes y
unos métodos para usarlos:



“sendError” envía un mensaje de error 404.
“sendRedirect” que se usa para enviar un
mensaje 302 conjuntamente con la cabecera de
respuesta “Location” indicando la nueva URL.
Es importante conocer la versión de protocolo
HTTP soportado con “getProtocol” de
“HttpServletRequest”.
Servlets: Respondiendo:
Códigos de estado
100
Continue
Continuar con la petición parcial. (HTTP 1.1)
101
Switching Protocols
El servidor debera responder con la cabecera Upgrade y asi cambiar de protocolo. (HTTP
1.1)
200
OK
Todo correcto. Por defecto en los servlets.
201
Created
El servidor ha creado un documento. En la cabecera Location se incluye la URL.
202
Accepted
La petición ha sido aceptada pero el procesamiento no ha terminado.
Servlets: Respondiendo:
Códigos de estado
203
Non-Authoritative Information
El documento ha sido devuelto correctamente pero alguna cabecera es incorrecta (HTTP
1.1)
204
No Content
No hay nuevo documento. El cliente debe presentar el actual.
205
Reset Content
No hay nuevo documento pero el cliente debe refrescar el actual. Para resetear las variables
CGI de los formularios (HTTP 1.1)
206
Partial Content
El cliente envio una petición parcial con una cabecera Range y el servidor la ha rellenado.
(HTTP 1.1)
300
Multiple Choices
El documento que se ha solicitado se puede encontrar en múltiples sitios. La preferida o por
defecto del servidor se ha de indicar en la cabecera Location.
Servlets: Respondiendo:
Códigos de estado
301
Moved Permanently
El documento solicitado está en otro sitio. Se indica la URL en la cabecera Location. El
navegador debería ir directamente.
302
Found
Similar a 301, pero la nueva URL debe entenderse como temporal. "Moved Temporarily" en
HTTP 1.0, con la constante SC_MOVED_TEMPORARILY de HttpServletResponse, (no
SC_FOUND). Tambien se puede usar el método directo response.sendRedirect(url).
303
See Other
Lo mismo que 301/302. (HTTP 1.1)
304
Not Modified
Cuando se determina que el cliente hace una petición condicional y se quiere indicar que el
documento que actualmente posee es el correcto (e.i. como respuesta a una cabecera IfModified-Since).
305
Use Proxy
El documento solicitado debería ser accedido por el proxy indicado en la cabecera
Location. (HTTP 1.1)
Servlets: Respondiendo:
Códigos de estado
307
Temporary Redirect
Identico a 302. No hay una variable en HttpServletResponse. (HTTP 1.1)
400
Bad Request
petición con sintaxis errónea.
401
Unauthorized
El cliente intento acceder a una pagina protegida con password sin la autorizacion
necesaria. La respuesta incluye una cabecera WWW-Authenticate para que el cliente
introduzca los datos en un dialogo que envia sus datos en la cabecera Authorization.
403
Forbidden
El recurso no esta disponible por un error en el servidor (permisos, acceso erroneo…).
404
Not Found
El recurso no pudo ser accedido. Posee un método propio HttpServletResponse:
sendError(message).
Servlets: Respondiendo:
Códigos de estado
405
Method Not Allowed
El método de petición (GET, POST, HEAD, DELETE, PUT, TRACE, etc.) no es permitido para
el recurso solicitado. (HTTP 1.1)
406
Not Acceptable
Incompatibilidad de tipo MIME. (HTTP 1.1)
407
Proxy Authentication Required
Lo mismo que 401, pero se obliga a usar una cabecera Proxy-Authenticate por parte
del servidor. (HTTP 1.1)
408
Request Timeout
El cliente tardo demasiado en enviar una petición. (HTTP 1.1)
409
Conflict
Generalmente en método PUT. Suele enviarse si se ha solicitado una versión incorrecta de
un recurso. (HTTP 1.1)
Servlets: Respondiendo:
Códigos de estado
410
Gone
El documento no esta disponible. La diferencia con 404 es que tiene carácter temporal.
(HTTP 1.1)
411
Length Required
El servidor no puede procesar la petición si el usuario no envía una cabecera ContentLength. (HTTP 1.1)
412
Precondition Failed
Alguna precondición especificada en las cabeceras de petición era falsa. (HTTP 1.1)
413
Request Entity Too Large
El documento solicitado es mayor de lo que el servidor esta dispuesto a gestionar. Si el
servidor estará dispuesto de gestionarlo mas tarde deberá incluir una cabecera de
respuesta Retry-After. (HTTP 1.1)
414
Request URI Too Long
La URL es demasiado larga. (HTTP 1.1)
Servlets: Respondiendo:
Códigos de estado
415
Unsupported Media Type
La petición esta en un formato desconocido. (HTTP 1.1)
416
Requested Range Not Satisfiable
El cliente introdujo una cabecera Range inadecuada en su petición. (HTTP 1.1)
417
Expectation Failed
El valor de la cabecera de petición Expect no se ha podido contrastar. (HTTP 1.1)
500
Internal Server Error
Un mensaje genérico para indicar que el servidor está confuso.
501
Not Implemented
El servidor no posee la funcionalidad para completar la petición. Por ejemplo si el usuario
ha hecho una petición PUT que el servlet no es capaz de procesar.
502
Bad Gateway
Usado por servidores que funcionan como proxies o puertas de enlace para indicar que
recibió una respuesta incorrecta por el servidor remoto.
Servlets: Respondiendo:
Códigos de estado
503
Service Unavailable
El servidor no puede responder por mantenimiento o colapso de conexiones. Se
puede enviar conjuntamente a una cabecera Retry-After.
504
Gateway Timeout
Usado por servidores que funcionan como proxies o puestas de enlace para
indicar que no recibido respuesta del servidor remoto en un tiempo adecuado.
(HTTP 1.1)
505
HTTP Version Not Supported
El servidor no es capaz de responder a la version del protocolo http indicado en
la petición. (HTTP 1.1)
Servlets: Respondiendo:
Cabeceras de respuesta


Un componente más en la línea de estado.
Íntimamente ligadas con los códigos de
estado.





Especificar cookies
Suministrar la fecha de modificación (para la
caché)
Instruir al navegador sobre la recarga de la página
después de un intervalo designado
Decir cuanto tiempo va a estar el fichero usando
conexiones persistentes
...
Servlets: Respondiendo:
Cabeceras de respuesta

El método más general para indicar
una cabecera de respuesta es
“setHeader” de
“HttpServletResponse” y recibe 2
strings:
1.
2.

El nombre de la cabecera.
El valor de la cabecera.
Antes de usar PrintWriter.
Servlets: Respondiendo:
Cabeceras de respuesta

Existen 2 métodos para cabeceras
relacionadas con:


FECHAS: “setDateHeader” para ahorrar el
tener que pasar una fecha Java (Date) a
milisegundos.
ENTEROS: “setIntHeader” para ahorrar el
tener que pasar un entero a String.
Servlets: Respondiendo:
Cabeceras de respuesta


Se puede consultar si una cabecera ya
ha sido indicada en la respuesta
mediante el método
“containsHeader”.
Para añadir un valor a una cabecera que
ya haya sido seleccionada, se usan los
métodos “addHeader”,
“addDateHeader” y “addIntHeader”.
Servlets: Respondiendo:
Cabeceras de respuesta

"HttpServletResponse" también suministra
unos métodos para especificar cabeceras
comunes:




"setContentType" selecciona la cabecera
Content-Type.
"setContentLength" selecciona la cabecera
Content-Length, útil si el navegador soporta
conexiones HTTP persistentes (keep-alive).
"addCookie" selecciona un cookie (no existe el
correspondiente setCookie, ya que es normal que
haya varias líneas Set-Cookie).
"sendRedirect" selecciona la cabecera Location
y el código de estado 302.
Servlets: Respondiendo:
Cabeceras de respuesta
Allow
Indica los métodos que soporta el servidor
Content-Encoding
Indica el método usado para codificar el documento. El usar compresión puede
reducir el tamaño de los documentos pero antes es mejor asegurarse que la
compresión esta soportada usando la cabecera Accept-Encoding (e.i.
request.getHeader("Accept-Encoding")).
Content-Length
Indica el numero de bytes que se están enviando. Solo es necesaria si se están
usando conexiones http persistentes (sep-alive). Lo mas sencillo es escribir en
un ByteArrayOutputStream, luego ver el tamaño e indicarlo en ContentLength y al final enviarlo con
byteArrayStream.writeTo(response.getOutputStream()).
Content-Type
Indica el tipo de codificación MIME del documento. Por defecto es
text/plain, por lo que se suele indicar text/html. Existe un método para
ello en HttpServletResponse que es setContentType.
Date
Indica la hora actual. Hay que usar el método setDateHeader.
Servlets: Respondiendo:
Cabeceras de respuesta
Expires
Indica el tiempo en el que el contenido debe considerarse no valido y por lo
tanto no introducirlo en la cache.
Last-Modified
Indica cuándo cambio el documento por última vez. El cliente puede preguntar
por ello usando la cabecera de petición If-Modified-Since que se trata
como una GET condicional y se responde con Last-Modified si la fecha es
posterior. En otro caso se envia 304 (Not Modified) como estado. Usar
setDateHeader.
Location
Indica la URL donde el cliente debe ir. Se suele usar con el estado 302 y el
método sendRedirect de HttpServletResponse.
Server
Indica el tipo de servidor. No lo suele indicar el servlet sino el propio servidor
web.
Set-Cookie
Indica la cookie asociada a la página. Es recomendable no usar
response.setHeader("Set-Cookie", ...), y en su defecto addCookie
de HttpServletResponse.
Servlets: Respondiendo:
Cabeceras de respuesta
Refresh
Indica cuándo debería pedir el navegador una página actualizada. En lugar de
recargar la página actual, podemos especificar otra página a cargar mediante
setHeader("Refresh", "5; URL=http://host/path"). Se suele
seleccionar mediante la cabecera HTML <META HTTP-EQUIV="Refresh"
CONTENT="5; URL=http://host/path"> en la sección HEAD, mejor que
una cabecera explícita desde el servidor. Esto es porque la recarga o el reenvio
automático es algo deseado por los autores de HTML que no tienen accesos a
CGI o servlets. Pero esta cabecera significa "Recarga esta página o ve a URL
especificada en n segundos" y no significa "recarga esta página o ve la URL
especificada cada n segundos". Por eso tenemos que enviar una cabecera
Refresh cada vez. De todas formas no es una cabecera oficial del HTTP 1.1, pero
es una extensión soportada por Netspace e Internet Explorer
WWW-Authenticate
Indica el tipo de autorización y dominio que debería suministrar el cliente en su
cabecera Authorization. Esta cabecera es necesaria en respuestas que tienen
una línea de estado 401 (Unauthorized). (e.i. response.setHeader("WWWAuthenticate", "BASIC realm=\"executives\"")).
Servlets: Acceso a recursos
ACCEDER A RECURSOS DEL SERVIDOR


Posibilidades:
1.
2.

Hacer que el servlet haga una petición HTTP.
Pedir el recurso mediante el "RequestDispatcher".
Para acceder al RequestDispatcher hay que
recoger el contexto del servlet mediante el
método “getServletContext”.
Servlets: Acceso a recursos
Seguidamente debemos acceder al recurso:

ServletContext sc = getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher(“/pagina.html");

Una vez tenemos el recurso accesible
podemos:


Hacer que el recurso sea el encargado de dar la
respuesta a la petición. Usamos el método
“forward” por lo que no podemos responder
nosotros.
Hacer una respuesta conjunta a la petición entre el
recurso y nuestro servlet usando el método
“include”
Servlets: Acceso a recursos



En otra ocasiones puede que se quiera
compartir recursos entre distintos
servlets.
Hacer uso de los atributos del
“ServletContext”.
Útil para servlets del mismo servidor y
sobre todo para servlets de la misma
aplicación.
Servlets: Acceso a recursos

CONVENCIÓN PARA NOMBRES DE
ATRIBUTOS: Se suele usar la misma
nomenclatura usada para los paquetes para
evitar conflictos.


Añadir un atributo: Se usa el método
“setAttribute” de “ServletContext”. Esto
se suele hacer en la inicialización del servlet. El
control de que varios servlets manejen un mismo
atributo es responsabilidad del desarrollador.
Recoger un atributo: Se usa el método
“getAttribute” de “ServletContext”. Hay
que convertir el objeto que devuelve al tipo
requerido.
Servlets: Acceso a recursos

Eliminar un atributo: Se puede eliminar un
atributo del contexto usando el método
“removeAttribute” de “ServletContext”.
Reenviando Respuestas


Es posible delegar el procesamiento de un
servlet a otro mediante la clase
javax.servlet.RequestDispatcher
Define dos métodos:


include  sirve para incluir contenido de otro
recurso
forward  para enviar una petición de un
servlet a otro

Difiere de HttpServetResponse.sendRedirect(),
que redirige la petición con la ayuda del navegador
Reenviando Respuestas

Para obtener un objeto
RequestDispatcher:


A partir del método getRequestDispatcher o
getNamedDispatcher de
javax.servlet.ServletContext  path
recibido relativo al directorio raíz del servidor o
nombre del recurso
El método getRequestDispatcher de
javax.servlet.ServletRequest  recibe
un path como parámetro relativo a la petición
actual HTTP
Reenviando Respuestas
// Revisar:
examples\servlets\ej10_include_servlet
RequestDispatcher rd =
request.getRequestDispatcher("/servlet/SecondSe
rvlet?name=diego");
rd.include(request, response);
// 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



Para utilizar cookies lo único que hay que hacer
es:
1) Crear una cookie: “new Cookie(String
name, String value)”
El nombre no puede contener ni espacios ni:
[ ] ( ) = , " / ? @ : ;
2) Especificar algún atributo a la cookies
mediante alguno de sus métodos:

getComment/setComment: Comentarios asociados
a la cookie.
Servlets: Respondiendo:
Cookies


getDomain/setDomain: Indicar el dominio
al que se aplica la cookie. Por defecto la
cookie se devuelve a la misma dirección que
la envió, pero así podemos indicar que se
reenvíe a otros servidores en el mismo
dominio. El dominio debe empezar por un ‘.’
getMaxAge/setMaxAge: Indicar el tiempo
que debe pasar en segundos hasta que la
cookie expire. Si no se indica la cookie dura
una sesión.
Servlets: Respondiendo:
Cookies



getName/setName: Indicar el nombre de
la cookie.
getPath/setPath: Indica a que rutas
responde la cookie. Si no se indica nada, la
cookie se envía para cualquier página en el
mismo path actual. Se podría usar para
usos generales como
someCookie.setPath("/"). Hay que
incluir al menos el directorio actual.
getSecure/setSecure: Sólo vale para
sesiones seguras (e.i. SSL).
Servlet: Respondiendo:
Cookies



getValue/setValue: Indicar el valor de
la cookie.
getVersion/setVersion: Indicar con
que version del protocolo funciona esta
cookie.
3) Añadir la cookie a la respuesta:
“response.addCookie(Cookie)”
Servlets: Respondiendo:
Cookies


Para acceder a las cookies que el cliente
reenvía cada vez que accede al recurso
se usa el método “getCookies” de
“HttpServletRequest” que devuelve
un array de cookies.
Con los métodos “getName” y
“getValue” de “Cookie” se accede a
la información de la cookie.
Servlets: Seguimiento de
sesión



El protocolo HTTP no posee la capacidad de
almacenar estados.
Se complican mucho las tareas de guardar las
acciones (e.i. Compras) de un usuario.
3 posibles soluciones:




Cookies.
Añadir información en la URL
Usar campos ocultos de formularios (HIDDEN)
Revisar:
examples\servlets\ej12_cookie_servlet
Servlets: Seguimiento de
sesión



Los servlets proporcionan una solución
técnica: La API HttpSession.
Una interfaz de alto nivel construida
sobre los cookies y la reescritura de las
urls (pero transparente para el
desarrollador).
Permite almacenar objetos.
Servlets: Seguimiento de
sesión

Pasos para trabajar con sesiones:

BUSCAR EL OBJETO HttpSession
ASOCIADO A UNA PETICIÓN: Se usa el
método “getSession” de
“HttpServletRequest” que devuelve
null si no hay una sesión asociada.
Entonces podríamos crear una pero al ser
una tarea sumamente común, se pasa
true y él mismo se encarga de crear una.
Servlets: Seguimiento de
sesión


BUSCAR INFORMACION ASOCIADA A LA
SESION: Usar los métodos “getValue” (o
“getAttribute” para versiones del API Servlet
2.2+) que devuelve un Object o null. Para
asignar un valor dentro de una sesión se usa el
método “putValue” (o “setAttribute” para
versiones del API Servlet 2.2+). Para conocer los
nombres de los valores están los métodos
“getValueNames” (o “getAttributeNames
para versiones del API Servlet 2.2+) que devuelve
un Enumeration.
Existen otros métodos que aportan información
sobre la sesión.
Servlets: Seguimiento de
sesión
getId. Este método devuelve un identificador único generado para cada
sesión. Algunas veces es usado como el nombre clave cuando hay un
sólo valor asociado con una sesión, o cuando se uso la información de
logging en sesiones anteriores.
isNew. Esto devuelve true si el cliente (navegador) nunca ha visto la
sesión, normalmente porque acaba de ser creada en vez de empezar
una referencia a una petición de cliente entrante. Devuelve false para
sesión preexistentes.
getCreationTime. Devuelve la hora, en milisegundos desde 1970, en la
que se creo la sesión. Para obtener un valor útil para impresión,
pasamos el valor al constructor de Date o al método setTimeInMillis de
GregorianCalendar.
getLastAccessedTime. Esto devuelve la hora, en milisegundos desde
1970, en que la sesión fue enviada por última vez al cliente.
getMaxInactiveInterval. Devuelve la cantidad de tiempo, en
segundos, que la sesión debería seguir sin accesos antes de ser
invalidada automáticamente. Un valor negativo indica que la sesión
nunca se debe desactivar.
Servlets: Seguimiento de
sesión



AÑADIR INFORMACION A UNA SESION: Los métodos
“putValue” y “setAttribute” eliminan (machacan) el
valor anterior del atributo por lo que para añadir información
hay que recuperar el valor primero y después de modificarlo,
volver a pasarlo a la sesión.
INVALIDAR UNA SESION: Automáticamente el servidor
web invalida tras un periodo de tiempo (30’) sin peticiones o
manualmente usando el método “invalidate”.
Revisar:
examples\servlets\ej13_session_servlet
JDBC de Javasoft: arquitectura
I
Aplicación
Java
Aplicación
Java
API JDBC
Gestor de Drivers
Driver API
JDBC-ODBC
Tipo 1
Gestor de
Driver ODBC
API Nativo
Parte en Java
Tipo 2
Driver de
SGBD Nativo
Driver de Red
en Java Puro
Tipo 3
Protocolo
Nativo
Driver en Java
Tipo 4
Protocolo
de Red
Propietario
Servidor
Driver ODBC
Driver de
SGBD Nativo
Protocolo
SGBD
Nativo
Protocolo
SGBD
Nativo
Protocolo
SGBD
Nativo
Protocolo
SGBD
Nativo
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


URL: esquema de nombres para
localizar BD
Sintaxis:




jdbc:<subprotocolo>:<subnombre>
jdbc:odbc:cliente
jdbc:msql://www.deusto.es:1112/c
atalogo
jdbc:mysql://localhost:3306/docm
an
Correspondencia tipos
SQL/Java
Tipo SQL
Tipo Java
Descripción
CHAR
string
Un carácter
VARCHAR
string
Cadena de caracteres de longitud
variable
NUMERIC
java.math.BigDeci
mal
BIT
INTEGER
boolean
int
Valor numérico para cantidades
económicas
Valor binario (0 o 1)
Entero de 32 bits con signo
REAL
float
Valor en punto flotante
DATE
java.sql.Date
Formato Fecha ‘aaaa-mm-dd’
TIME
java.sql.Time
Formato Hora ‘hh-mm-ss’
JDBC API: java.sql.* I

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
Ejecución de sentencias SQL

Statement stmt = dbCon.createStatement();
3 posibilidades:


executeQuery()  1 conjunto de resultados
ResultSet res = stmt.executeQuery(“select *
from compradores where prio=1”);

executeUpdate()
DML (insert, update, deletee)  nº filas afectadas

DDL (create table)  0
int total = stmt.executeUpdate(“insert into
prioridad (cod-pri, descripcion) values
(4, ‘crítica’)”);


execute ()

Cuando no se sabe que va a devolver  ResultSet o
nº
JDBC API: java.sql.* III
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
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 };
SQLJ vs. JDBC
String vName; int vSalary; String vJob;
Java.sql.Timestamp vDate;
...
DINÁMICO  JDBC
PreparedStatement stmt =
connection.prepareStatement( "SELECT Ename, Sal " + "FROM Emp " +
"WHERE Job =? and HireDate = ?");
stmt.setString(1, vJob);
stmt.setTimestamp(2, vDate);
ResultSet rs = stmt.executeQuery();
rs.next();
vName = rs.getString(1); vSalary = rs.getInt(2);
rs.close();
Servlet con JDBC
// examples\servlets\ej14-db_servlet
public class RegistrationServlet extends HttpServlet {
private
private
private
private
String
String
String
String
firstName = "";
lastName = "";
userName = "";
password = "";
public void init() {
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("JDBC driver loaded");
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
}
}
Servlet con JDBC
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
sendPageHeader(response);
firstName = request.getParameter("firstName");
lastName = request.getParameter("lastName");
userName = request.getParameter("userName");
password = request.getParameter("password");
boolean error = false;
String message = null;
try {
Connection con = DriverManager.getConnection("jdbc:odbc:UsersDB");
System.out.println("got connection: " + password);
Statement s = con.createStatement();
String sql = "SELECT UserName FROM Users" +
" WHERE userName='" + StringUtil.fixSqlFieldValue(userName) + "'";
ResultSet rs = s.executeQuery(sql);
System.out.println("Ejecutando select: ");
if (rs.next()) {
rs.close();
message = "The user name <B>" + StringUtil.encodeHtmlTag(userName) +
"</B> has been taken. Please select another name.";
System.out.println(message);
error = true;
}
// ...
}
Servlet Filters


Un filtro te da acceso a los objetos
HttpServletRequest y HttpServletResponse
antes y después, respectivamente, de que lleguen a
un recurso web.
Los filtros se declaran en el web.xml con el
elemento xml <filter> y su uso se indica mediante
<filter-mapping>




Se puede asociar un filtro a un patrón de url
Además los filtros se pueden encadenar
Definidos por los interfaces: Filter,
FilterConfig y FilterChain
Revisar:
examples\servlets\ej15_filter_servlet
Ejemplo Filter
// compile: javac -classpath %TOMCAT_HOME%\common\lib\servletapi.jar;. UpperCaseFilter.java
import java.io.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.Enumeration;
public class UpperCaseFilter implements Filter {
private FilterConfig filterConfig = null;
public void destroy() {
System.out.println("Filter destroyed");
this.filterConfig = null;
}
Ejemplo Filter
public void doFilter(ServletRequest request, ServletResponse
response,
FilterChain chain)
throws IOException, ServletException {
System.out.println("Filter");
Enumeration enum = request.getAttributeNames();
while (enum.hasMoreElements()) {
String attributeName = (String) enum.nextElement();
String attributeValue = (String)
request.getAttribute(attributeName);
request.setAttribute(attributeName,
attributeValue.toUpperCase());
}
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