Laboratorio Web

MENU

Ejercicio del Carrito de Compra con Servlets

En este ejemplo aprenderemos a utilizar los Servlets en J2EE y a mapearlos en el xml.

Como ejercicio, haremos el típico proyecto del carro de la compra.

Capa V.O.

En primer lugar, creamos el paquete VO y dentro de este, las clases Producto y LineaPedido.

Creación del paquete VO y las clases Producto y LineaPedido

Producto

Producto tendrá un "id", un "nombre" y un "precio".

En estas clases:

  • Hacemos el constructor usando las variables
  • Hacemos el constructor del Producto en función del id
  • Sobreescribimos el método equals()
  • Sobreescribimos el método toString()
package com.pablofv.vo;

public class Producto {
	// Variables de Producto
	private int id;
	private String nombre;
	private double precio;

	// Constructor de la clase
	public Producto(int id, String nombre, double precio){
		this.id = id;
		this.nombre = nombre;
		this.precio = precio;
	}
	
	// Constructor específico
	public Producto(int id){
		this.id = id;
	}

	// Getters y Setters
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public double getPrecio() {
		return precio;
	}

	public void setPrecio(double precio) {
		this.precio = precio;
	}
	
	// Sobreescritura del método equals()
	@Override
	public boolean equals(Object obj) {
		return (obj instanceof Producto) && 
			   ((Producto) obj).getId() == this.id;
	}

	// Sobreescritura del método toString()
	@Override
	public String toString() {
		return this.nombre + " (" + String.format( "%.2f", this.precio ) + "€)";
	}

}
			

LineaPedido

LineaPedido tendrá una variable de tipo Producto llamado "producto", un "precio" y una "cantidad".

En estas clases:

  • Hacemos el constructor usando las variables
  • Hacemos el constructor de LineaPedido en función del objeto "producto", donde el precio lo marcará el precio de la clase Producto.
    Este precio lo obtenemos por el getter del precio del producto: producto.getPrecio();
    La cantidad la inicializamos a 1
  • Sobreescribimos el método equals()
  • Sobreescribimos el método toString()
package com.pablofv.vo;

public class LineaPedido {
	
	// Variables de LineaPedido
	private Producto producto;	// variable de tipo Producto
	private double precio;
	private int cantidad;
	
	// Constructor con un producto
	public LineaPedido(Producto producto) {
		this.producto = producto;
		this.precio = producto.getPrecio();	// El precio viene del getter de Producto
		this.cantidad = 1;			// Iniciamos la cantidad a 1
	}
	
	// Constructor de la clase
	public LineaPedido(Producto producto, double precio, int cantidad) {
		this.producto = producto;
		this.precio = precio;
		this.cantidad = cantidad;
	}

	// Getters y Setters
	public Producto getProducto() {
		return producto;
	}

	public void setProducto(Producto producto) {
		this.producto = producto;
	}

	public double getPrecio() {
		return precio;
	}

	public void setPrecio(double precio) {
		this.precio = precio;
	}

	public int getCantidad() {
		return cantidad;
	}

	public void setCantidad(int cantidad) {
		this.cantidad = cantidad;
	}
	
	// Sobreescritura del método equals()
	@Override
	public boolean equals(Object obj) {
		return (obj instanceof LineaPedido) && 
			   ((LineaPedido) obj).getProducto().equals(this.producto);
	}
	
	// Sobreescritura del método toString()
	@Override
	public String toString() {
		return this.producto.getNombre()   " ("   String.format( "%.2f", this.precio )   "€): "   this.cantidad   " unidad"   (this.cantidad>1?"es":"");
	}

}


			

Capa Manager

Para este ejercicio no utilizaremos bases de datos. En lugar de eso, crearemos manualmente nuestros productos utilizando un ArrayList.

Creación del paquete manager y la clase ProductoManager

ProductoManager

Crearemos un paquete "manager" y dentro de este, la clase ProductoManager.

Esta clase tendrá:

  • Un lista de objetos de tipo Producto. private List<Producto> productos;
  • Un constructor donde introduciremos los productos
  • Un método para mostrar los productos
  • Un método para obtener la id del producto
package com.pablofv.manager;

import java.util.ArrayList;
import java.util.List;

import com.pablofv.vo.Producto;

public class ProductoManager {
	
	// Lista de objetos de tipo Producto
	private List<Producto> productos;
	
	// Constructor donde introducimos los productos
	public ProductoManager() {
		this.productos = new ArrayList<Producto>();
		this.productos.add(new Producto(1, "Zapatos caballero", 65.25));
		this.productos.add(new Producto(2, "Zapatos señora", 85.60));
		this.productos.add(new Producto(3, "Camisa azul", 55.00));
		this.productos.add(new Producto(4, "Pantalón marrón", 80.50));
		this.productos.add(new Producto(5, "Vestido rojo", 120.00));
		this.productos.add(new Producto(6, "Bolso de piel blanco", 90.00));
	}
	
	// Mostrar los productos
	public List<Producto> getProductos() {
		return this.productos;
	}
	
	// Obtener la id del producto
	public Producto getProducto(int id) {
		int posicion = this.productos.indexOf(new Producto(id));
		return posicion >= 0 ? this.getProductos().get(posicion) : null;
	}

}				
			

Capa Servlets

ServletInicio

La aplicación empezará en este servlet.

Crearemos un Servlet llamado ServletInicio

Lo primero que haremos será eliminar la anotación, si la tiene, para mapearlo en el archivo web.xml

@WebServlet("/ServletInicio")		// Debemos eliminar esta línea para mapearlo en web.xml
public class ServletInicio extends HttpServlet {
...	// resto del código			
			

Dentro del método init, creamos una variable de tipo ProductoManager

public class ServletInicio extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ProductoManager productoManager;
			

Ahora actuaremos en el doGet

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//seleccionamos el tipo de contenido en la cabecera antes de acceder al Writer
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		//Escribimos la respuesta
		out.println("<!doctype html>");
		out.println("<html><head><title>Listado de productos y carrito</title></head><body>");
			out.println("<div id=\"contenedor-global\">");
				out.println("<section id=\"contenedor-productos\">");
					out.println("<h1>Listado de productos</h1>");
					// Llamada a la función que pinta los productos
					this.pintarProductos(out);
				out.println("</section>");
				out.println("<section id=\"contenedor-carrito\">");
					out.println("<h1>Carrito de la compra</h1>");
					// Llamada a la función que pinta el carrito
					this.pintarCarrito(request, out);
				out.println("</section>");
			out.println("</div>");
		out.println("</body></html>");
		//Cerramos el Writer
		out.close();
	}				

			

En el doPost llamaremos al doGet

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}
			

Finalmente, creamos las funciones pintarProductos y pintarCarrito

	// Función que pinta los productos
	private void pintarProductos(PrintWriter out) {
		
		List<Producto> productos = (List<Producto>) this.productoManager.getProductos();
		
		if(productos == null || productos.isEmpty()) {
			out.println("<h2>Actualmente no hay productos disponibles</h2>");
		} else {
			out.println("<ul>");
			for(Producto producto:productos) {
				out.println("<li>"   producto   " - <a href=\"ServletProcesarPeticion?id="   producto.getId()   "\" title=\"A%u2013adir al carrito el producto "   producto.getNombre()   "\">A%u2013adir al carrito</a></li>");
			}
			out.println("</ul>");
		}
		
	}
	
	// Función que pinta el carrito
	private void pintarCarrito(HttpServletRequest request, PrintWriter out) {
		
		List<LineaPedido> carrito = (List<LineaPedido>) request.getSession(true).getAttribute("carrito");
		
		if(carrito == null || carrito.isEmpty()) {
			out.println("<h2>El carrito actualmente est%u2021 vac%u2019o</h2>");
		} else {
			double total = 0;
			out.println("<ul>");
			for(LineaPedido lineaPedido:carrito) {
				total  = (lineaPedido.getPrecio()*lineaPedido.getCantidad());
				out.println("<li>"   lineaPedido   " - <a href=\"ServletProcesarPeticion?op=r&id="   lineaPedido.getProducto().getId()   "\" title=\"A%u2013adir al carrito el producto "   lineaPedido.getProducto().getNombre()   "\">Restar una unidad del producto</a></li>");
			}
			out.println("</ul>");
			out.println("<p>Total: "   String.format( "%.2f", total )   "&euro;</p>");
		}
		
	}
			

En estas funciones hemos llamado a otro Servlet por el método get.

Hemos llamado al Servlet ServletProcesarPeticion en la etiqueta <a> de html y le hemos pasado como parámetro la id de un producto de la línea de pedido.

Mapeando ServletInicio en web.xml

Procedemos a mapear el Servlet en el archivo web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
	version="3.0">
  
  <servlet>
    <servlet-name>ServletInicio</servlet-name>
    <servlet-class>com.pablofv.servlets.ServletInicio</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ServletInicio</servlet-name>
    <url-pattern>/ServletInicio</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>ServletInicio</welcome-file>
  </welcome-file-list>
  
</web-app>				
			

ServletProcesarPeticion

Anteriormente, hemos referenciado en una etiqueta <a> a un Servlet y le hemos pasado unos parámetros.

También hemos mapeado ese Servlet en el archivo web.xml

Ahora construiremos el Servlet donde procesaremos las funciones.

Para empezar, crearemos un objeto de tipo ProductoManager:

private ProductoManager productoManager;
			

Lo llamaremos en el método init

public void init(ServletConfig config) throws ServletException {
	super.init(config);
	this.productoManager = new ProductoManager();
}
			

Actuaremos ahora en el doGet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
	// Inicializamos el id a 0
	int id = 0;
	
	// Hacemos un try catch al id
	try {
		id = Integer.parseInt(request.getParameter("id"));
	} catch(Exception ex) {
		ex.printStackTrace();
	}
	
	// creamos una variable para almacenar la operación a realizar
	String operacion = request.getParameter("op");
	
	// dependiendo del parámetro que se le pase añadirá o restará una unidad
	if(operacion != null && operacion.equals("r")) {
		this.restarUnidad(request, id);
	} else {
		this.anadirUnidad(request, id);
	}
	
	// Finalmente lo mandamos al Servlet de inicio 
	response.sendRedirect("ServletInicio");
}				
			

Y en el doPost:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	this.doGet(request, response);
}			

Definimos las funciones para Añadir Productos y Eliminar Productos

			// Función para restar unidad
private void restarUnidad(HttpServletRequest request, int id) {

	Producto producto = this.productoManager.getProducto(id);
	List<LineaPedido> carrito = (List<LineaPedido>) request.getSession(true).getAttribute("carrito");

	if (producto != null && carrito != null) {

		int posicion = carrito.indexOf(new LineaPedido(producto));

		if (posicion >= 0) {
			LineaPedido lp = carrito.get(posicion);
			int cantidad = lp.getCantidad() - 1;

			if (cantidad > 0) {
				lp.setCantidad(cantidad);
			} else {
				carrito.remove(posicion);
			}
		}

		request.getSession().setAttribute("carrito", carrito);
	}

}

// Función para añadir unidad
private void anadirUnidad(HttpServletRequest request, int id) {

	Producto producto = this.productoManager.getProducto(id);
	List<LineaPedido> carrito = (List<LineaPedido>) request.getSession(true).getAttribute("carrito");

	if (producto != null) {

		if (carrito == null) {
			carrito = new ArrayList<LineaPedido>();
			carrito.add(new LineaPedido(producto));
		} else {
			int posicion = carrito.indexOf(new LineaPedido(producto));

			if (posicion >= 0) {
				LineaPedido lp = carrito.get(posicion);
				lp.setCantidad(lp.getCantidad()   1);
			} else {
				carrito.add(new LineaPedido(producto));
			}
		}

		request.getSession().setAttribute("carrito", carrito);
	}
}
		

Finalmente, mapeamos el Servlet en el archivo web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
	version="3.0">
  
  <servlet>
    <servlet-name>ServletInicio</servlet-name>
    <servlet-class>com.pablofv.servlets.ServletInicio</servlet-class>
  </servlet>
  
  <servlet>
    <servlet-name>ServletProcesarPeticion</servlet-name>
    <servlet-class>com.pablofv.servlets.ServletProcesarPeticion</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ServletInicio</servlet-name>
    <url-pattern>/ServletInicio</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
    <servlet-name>ServletProcesarPeticion</servlet-name>
    <url-pattern>/ServletProcesarPeticion</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>	
    <welcome-file>ServletInicio</welcome-file>
  </welcome-file-list>
  
</web-app>
			

La aplicación está lista para su ejecución.

Puedes descargarte el archivo .war con el ejemplo.

Artículo en desarrollo, disculpen los inconvenientes.