====== Servlets ======
===== Notas iniciales =====
* Son clases normales y corrientes de java que han de heredar de: //javax.servlet.http.HttpServlet//
* Cuando un servlet es añadido, editado y\o compilado Tomcat ha de ser actualizado; para ello puede ser reiniciado o símplemente usar algún metodo para la recarga del contexto de la aplicación (//Reload the context//).
* Para acceder a un Servlet es necesario que exista el archivo web.xml de la aplicación, donde encontremos la URL del Servlet.
===== Pasos para la creación de un servlet =====
- Creamos una aplicación en Tomcat con su carpetita ///WEB-INF//, ///WEB-INF/src// y ///WEB-INF/classes//.
- En WEB-INF/src creamos nuestros archivos .java que luego compilaremos. Si la clase que utilizamos es MyServlet y está en el paquete mypck.mysvl el archivo deberá de ser el siguiente: WEB-INF/src/mypck/mysvl/MyServlet.java. Una vez lo compilasemos deberíamos de colocar la clase en WEB-INF/classes/mypck/mysvl/MyServlet.class.
- En WEB-INF deberemos de colocar el archivo web.xml que enlace nuestro servlet con el nombre mi_servlet:
prueba
mypck.mysvl.MyServlet
prueba
/mi_servlet
* Ahora sólo necesitaremos ir a: dirección del server/nombre aplicación/mi_servlet
===== Estructura =====
* Los servlets heredan de la clase //HttpServlet// y sobreescriben los métodos //doGet// o //doPost// según si el formulario usado en el html ha enviado los datos por GET o por POST. Los dos métodos reciben dos parámetros: un //javax.servlet.http.HttpServletRequest// (para la entrada de datos) y un //javax.servlet.http.HttpServletResponse// (para la salida de datos). Este último tiene un método llamado //getPrinter// que devuelve un objeto //PrintWriter//, perfecto para hacer la escritura de datos en html en la respuesta del cliente.
* El objeto HttpServletResponse tiene un método llamado //setContentType//, con este elegimos el tipo de datos (y por tanto como han de ser tratados estos) que enviaremos al cliente, si lo que queremos es enviar en html pondremos: ''text/html''.
* Antes de que alguno de los métodos doGet o doPost sean llamados, se llama a //service//, otro método de la clase HttpServlet. Este es el que elige a qué método llamar, este método no deberíamos sobreescribirlo.
* Otro método importante a tener en cuenta es el método //init//, este se llama cuando se crea el servlet (la primera vez que se llama a este), sólo una vez.
* Los servlets pueden ser llamados desde distintos sitios a la vez, esto puede dar problemas debido a que están desarrollados con multithreading y tal vez se necesite bloquear alguna que otra variable. Podemos forzar al sistema a ejecutar nuestros servlets en forma de thread simple implementando en ellos la interface: //SingleThreadModel//.
===== Recoger datos de formularios =====
Un formulario como el siguiente enviaría los datos al servlet //prueba// ubicado en la misma ruta en la que este esté:
* Podremos recoger los valores introducidos por el usuario mediante el método del //request// llamado //getParameter//. ''request.getParameter("firstName");'' Si viniese más de un solo valor podríamos usar el método //getParameterValues//.
* Para recoger el nombre de los parametros usaremos el método //getParameterNames// (en el request).
* Para recoger los datos en formato raw utilizaremos los métodos del request //getReader// o //getInputStream//. Uno de los casos en los que esto pueda ser útil es al recoger un fichero (para subir ficheros podremos utilizar la librería //fileupload// de //jakarta//).
===== Información Extra =====
==== Cabeceras HTTP 1.1 ====
Estas cabeceras te dan la posivilidad de acceder a información de la transferencia de datos cliente-servidor. Para acceder a ellas únicamente utilizaremos los métodos //getHeader// y //getHeaderNames// que devolverán los strings correspondientes a los valores de estas. Podemos encontrarnos con las siguientes:
* **host**: Correspondiente a la dirección del cliente.
* **user-agent**: Indica información sobre la plataforma del cliente, el SO, el navegador...
* **accept-language, accept-encoding y accept-charset**: Sobre el tipo de carácteres que usa el cliente.
* **referer**: La página web desde la que ha sido llamado.
...
==== Variables CGI ====
Otra forma de recoger información de la conexión con tu cliente es la de usar algunos métodos que contiene el objeto //request//:
* **getAuthType**: Tipo de autorización.
* **getContentLength**: El número de bytes que se te ha enviado.
* **getPathInfo, getServletContext().getRealPath y getPathTranslated**: Recoger la ruta usada para llamar a tu servlet.
* **getRemoteAddr y getRemoteHost**: Dirección del cliente.
...
===== Response =====
Veamos los métodos que pueden sernos útiles en el objeto HttpServletResponse:
* **sendRedirect**: Le pasamos un string y redirige la web en la que está el usuario a otra nueva con dirección correspondiente al string.
* **setStatus**: Indica un estado al cliente (existen ciertos códigos para ello).
* **sendError**: Devuelve un estado de error al navegador del cliente.
===== Cookies =====
Las cookies, con las que podemos guardar información en el mismo ordenador cliente (logins y passwords, identificadores en una compra, preferencias de una web...), son fáciles de utilizar mediante servlets. Para ello en el objeto //response// existe un método llamado //setCookie// al que se le pasa un objeto Cookie; no hay mucho destacable en este objeto, tal vez el método //setMaxAge// por el que indicamos mediante segundos cuanto tiempo permanecerá válida la cookie. Bueno, sí... Otro método curioso es //getPath// que se combina con //setPath//, estos nos permitirán indicar en qué rutas será válida la cookie, por defecto es en la que se envia pero podemos indicar que se use en toda nuestra web pasándole el directorio raíz: //cookie.setPath("/")//.
El objeto //request// tiene un método llamado //getCookies// que recoge las cookies correspondientes a tu web en el cliente; si //getCookies// devuelve //null// es porque el cliente no ha recogido anteriormente cookies en tu web.
===== Sesiones =====
- Recogeremos la sesión del objeto //request// mediante el método //getSession//, este retorna un objeto //HttpSession//
- Para ver los datos asociados a una sesión usaremos el método //getAttribute//
- De la misma forma, también podremos guardar datos mediante el método //setAttribute//
- Para eliminar la información de la sesión lo que haremos será llamar a //removeAttribute// (para eliminar un dato concreto), //invalidate// (para eliminar todos los datos de la sesión) o //logout// (para destruir la sesión).
* Nosotros no debemos de crear ningún objeto sesión, se crea automáticamente con la primera petición a nuestra página (sólo debemos de llamar al //request.getSession())// aunque si queremos si la sesión se acaba de crear, //getSession// permite pasarsele un boolean, si este es false retornará null si la sesión no existía anteriormente. Aunque también existe el método isNew.
* Los atributos, o datos adjuntos a una sesión, son objetos que tienen como id un string y que se almacenan en el mismo objeto HttpSession. Para recogerlos deberemos hacer un cast de Object al tipo deseado.
* Los métodos //getCreationTime//, //getLastAccessedTime//, //getMaxInactiveIntervall// y //setMaxInactiveIntervall// nos permiten controlar la caducidad de la sesión, cuando fue creada, cuando fue usada por última vez...
* Una vez utilices los objetos sesiones todas las páginas de tu dominio se generarán dinámicamente, no tendrás ninguna página estática (hasta que no hagas un logout de la sesión), para poder manejar las nuevas urls deberás parsearlas tanto para añadirlas en tus links como para hacer una redirección, gracias a Dios existen los métodos //encodeURL// y //encodeRedirectURL// que se usan de la siguiente forma:
* Método //encodeURL//
String url = "laquesea.html";
String newUrl = response.encodeURL(url);
response.getWriter().print("': filtered.append(">"); break;
case '"': filtered.append("""); break;
case '&': filtered.append("&"); break;
default: filtered.append(c);
}
}
return(filtered.toString());
}
private static boolean hasSpecialChars(String input) {
boolean flag = false;
if ((input != null) && (input.length() > 0)) {
char c;
for(int i=0; i': flag = true; break;
case '"': flag = true; break;
case '&': flag = true; break;
}
}
}
return(flag);
}
==== Cómo generar imágenes? ====
- Indicaremos que se va a enviar una imágen: ''response.setContentType("image/jpeg");''
- No usaremos el PrintWriter (recogido mediante el método getWriter) sino un stream: ''OutputStream out = response.getOutputStream();''
- Usaremos un objeto BufferedImage para ir dibujando sobre él.
- Mediante el método write de la clase ImageIO volcaremos el BufferedImage sobre el OutputStream: ''ImageIO.write(image, "jpg", out);'' (siendo //image// el BufferedImage).
==== Redirigir página ====
Método que según la cuenta bancacria de un cliente redirigirá la salida a una página o a otra:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BankCustomer customer = BankCustomer.getCustomer(request.getParameter("id"));
String address;
if (customer == null) {
address = "/WEB-INF/bank-account/UnknownCustomer.jsp";
} else if (customer.getBalance() < 0) {
address = "/WEB-INF/bank-account/NegativeBalance.jsp";
request.setAttribute("badCustomer", customer);
} else if (customer.getBalance() < 10000) {
address = "/WEB-INF/bank-account/NormalBalance.jsp";
request.setAttribute("regularCustomer", customer);
} else {
address = "/WEB-INF/bank-account/HighBalance.jsp";
request.setAttribute("eliteCustomer", customer);
}
RequestDispatcher dispatcher = request.getRequestDispatcher(address);
dispatcher.forward(request, response);
}