Ejercicio Hibernate

Con lo que hemos visto del enlace anterior vamos a crear en esa misma aplicación una api REST para dar mantenimiento a los países de la bd de trifulcas. Campos:

country_id
country
last_update

El last_update es de la base de datos, lo podemos obviar en nuestro POJO.

Una vez funcione la API podemos crear un mantenimiento web usando MVC. El controlador será un servlet que pasará los datos a una página JSP. Si en la página JSP usamos JSTL (https://github.com/juanpfuentes/Java/blob/main/src/java/jstl.md) todo irá mejor.
¡Ánimo!

Crear la API

Añadimos la siguiente dependencia:

<dependency>
			<groupId>org.json</groupId>
			<artifactId>json</artifactId>
			<version>20220924</version>
		</dependency>

Mapeamos el servlet, creamos un actorDAO para acceder a los datos e implementamos el get:

@WebServlet("/Api/*")
public class Api extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ActorDAO actorDAO;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public Api() {
		super();
		actorDAO = new ActorDAO();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			String id = request.getPathInfo();
			System.out.println(id);
			if (id == null) {
				List<Actor> actores = actorDAO.getActors();
				JSONArray actoresJSON = new JSONArray(actores);
				response.getWriter().append(actoresJSON.toString());
			} else {
				int idActor = Integer.parseInt(id.substring(1));
				Actor actor = actorDAO.getActor(idActor);
				JSONObject actorJSON = new JSONObject(actor);
				response.getWriter().append(actorJSON.toString());
			}
		} catch (Exception ex) {
			JSONObject mensaje = new JSONObject();
			mensaje.put("Mensaje", "Error en la petición");
			mensaje.put("Error", ex);
			response.getWriter().append(mensaje.toString());
		}
	}

EL POST:

protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// Me mandarán los valores del actor en formato JSON
		// Tendré que insertarlo en la BD
		JSONObject mensaje = new JSONObject();
		try {
			String data = request.getReader().lines().collect(Collectors.joining());
			JSONObject actorJSON = new JSONObject(data);

			Actor actor = new Actor(0, actorJSON.getString("first_name"), actorJSON.getString("last_name"), null);

			if (actorDAO.addActor(actor)) {
				mensaje.put("Mensaje", "Actor insertado con éxito");
			} else {
				mensaje.put("Mensaje", "Error en la inserción");
			}
			response.getWriter().append(mensaje.toString());
		} catch (Exception ex) {
			mensaje.put("Mensaje", "Error en la petición");
			mensaje.put("Error", ex);
			response.getWriter().append(mensaje.toString());
		}
	}

DAO Actor

Para tener acceso a datos tenemos que tener un POJO que nos represente la entidad y un DAO para las operaciones comunes.

package com.trifulcas.dao;

import java.sql.Date;

public class Actor {

	private int actor_id;
	private String first_name;
	private String last_name;
	private Date last_update;
	
	public Actor(int actor_id, String first_name, String last_name, Date last_update) {
		this.actor_id = actor_id;
		this.first_name = first_name;
		this.last_name = last_name;
		this.last_update = last_update;
	}
	
	/**
	 * @return the actor_id
	 */
	public int getActor_id() {
		return actor_id;
	}
	/**
	 * @param actor_id the actor_id to set
	 */
	public void setActor_id(int actor_id) {
		this.actor_id = actor_id;
	}
	/**
	 * @return the first_name
	 */
	public String getFirst_name() {
		return first_name;
	}
	/**
	 * @param first_name the first_name to set
	 */
	public void setFirst_name(String first_name) {
		this.first_name = first_name;
	}
	
	/**
	 * @return the last_name
	 */
	public String getLast_name() {
		return last_name;
	}
	/**
	 * @param last_name the last_name to set
	 */
	public void setLast_name(String last_name) {
		this.last_name = last_name;
	}
	/**
	 * @return the last_update
	 */
	public Date getLast_update() {
		return last_update;
	}
	/**
	 * @param last_update the last_update to set
	 */
	public void setLast_update(Date last_update) {
		this.last_update = last_update;
	}
	
	public String toString() {
		return actor_id+" | "+first_name+" | "+last_name+" | "+last_update;
	}
	
}

Para acceder a los datos:

public class ActorDAO {

	private Connection con;
	private int max_records = 1000;

	public ActorDAO() {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");

		} catch (Exception ex) {
			System.out.println(ex);
		}
	}

	public Actor getActor(int id) {
		Actor res = null;
		try {
			String sql = "select * from actor where actor_id=?";
			PreparedStatement stmt = con.prepareStatement(sql);

			stmt.setInt(1, id);

			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				res = new Actor(rs.getInt("actor_id"), rs.getString("first_name"), rs.getString("last_name"),
						rs.getDate("last_update"));
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}

	public List<Actor> getActors(int limite) {
		List<Actor> res = new ArrayList<Actor>();
		try {
			String sql = "select * from actor limit ?";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setInt(1, limite);
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				Actor temp = new Actor(rs.getInt("actor_id"), rs.getString("first_name"), rs.getString("last_name"),
						rs.getDate("last_update"));
				res.add(temp);
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}
	
	/**
	 * Devuelve un arraylist de actores cuyo apellido contenga la cadena que le pasamos
	 * @param cad cadena a buscar
	 * @return ArrayList de actores
	 */
	public List<Actor> getActors(String cad) {
		List<Actor> res = new ArrayList<Actor>();
		try {
			String sql = "select * from actor where last_name like ?";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, '%'+cad+'%');
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				Actor temp = new Actor(rs.getInt("actor_id"), rs.getString("first_name"), rs.getString("last_name"),
						rs.getDate("last_update"));
				res.add(temp);
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}

	public List<Actor> getActors() {
		return getActors(max_records);
	}

	public boolean addActor(Actor actor) {
		try {
			String sql = "insert into actor (first_name, last_name) values (?,?)";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, actor.getFirst_name());
			stmt.setString(2, actor.getLast_name());
			int res = stmt.executeUpdate();
			return res == 1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}

	public boolean updateActor(Actor actor) {
		try {
			String sql = "update actor set first_name=?, last_name=? where actor_id=?";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, actor.getFirst_name());
			stmt.setString(2, actor.getLast_name());
			stmt.setInt(3, actor.getActor_id());
			int res = stmt.executeUpdate();
			return res == 1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}

	public boolean deleteActor(Actor actor) {
		try {
			if (actor != null) {
				return deleteActor(actor.getActor_id());
			}
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}

	public boolean deleteActor(int actor_id) {
		try {
			String sql = "delete from actor where actor_id=?";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setInt(1, actor_id);
			int res = stmt.executeUpdate();
			return res == 1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}

}

Podemos probarlo en el main de una clase cualquiera:

public static void main(String[] args) {
         
        // He abstraído la base de datos
        ActorDAO bd=new ActorDAO();
         
        Actor penelope=bd.getActor(1);
         
        System.out.println(penelope.getFirst_name());
 
        List<Actor> actores=bd.getActors();
        for(Actor actor:actores) {
            System.out.println(actor);
        }
         
        Actor nuevo=new Actor(1,"w","e",null);
    }

Crear una página web dinámica que use un servlet

1.- Creo un proyecto Maven con el arquetipo webapp
2.- Añado las siguientes dependencias en el POM:

	<dependency>
			<groupId>jakarta.servlet</groupId>
			<artifactId>jakarta.servlet-api</artifactId>
			<version>6.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>jakarta.servlet.jsp.jstl</groupId>
			<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
			<version>2.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>jakarta.servlet.jsp.jstl</artifactId>
			<version>3.0.1</version>
		</dependency>

3.- Dentro de la carpeta ‘src/main’ creo una carpeta java
4.- Al crear esa carpeta nos sale arriba ‘Java Resources’
5.- Creamos ahí un paquete para poner nuestras clases. Por ejemplo ‘com.trifulcas.controller’
6.- Dentro de este paquete botón derecho ‘New->Servlet’
7.- Ponemos el enrutamiento con ‘@WebServlet(“/ruta_del_servlet”)’
8. Ejecutamos en servidor y al poner la ruta debería escribirse un mensaje que es el que tiene el servlet por defecto.

Dependencias Servlet

Tenemos que poner esto en el POM:

	<dependency>
			<groupId>jakarta.servlet</groupId>
			<artifactId>jakarta.servlet-api</artifactId>
			<version>6.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>jakarta.servlet.jsp.jstl</groupId>
			<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
			<version>2.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>jakarta.servlet.jsp.jstl</artifactId>
			<version>3.0.1</version>
		</dependency>

https://github.com/juanpfuentes/Java/blob/main/src/java/servlet.md

JSTL:

https://www.javatpoint.com/jstl

Ejercicio mini web

Vamos a crear una miniweb con lo siguiente:

Al entrar nos aparecerá una página de login con usuario y contraseña:

Usuario:[ ]
Password:[ ]
[Enviar]

Si el usuario no es ‘admin’ ‘admin’ nos vuelve a la página de login.
Si es ‘admin’ ‘admin’ nos sale una página con estos enlaces:

Tabla de multiplicar
Numero mayor

Si pinchan en tabla de multiplicar nos sale una página con lo siguiente:
Número[ ]
[Enviar]

Si nos introducen un número en esta misma página se mostrará la tabla de multiplicar de ese número

Si pinchan en mayor nos sale una página con lo siguiente:
Número 1 [ ] Número 2 [ ]
[Enviar]
Al darle a enviar nos dice cual es el número mayor de los dos

Mejoras: que tanto en la tabla de multiplicar como en los números ya estén por defecto los valores que hemos enviado en vez de quedarse en blanco.

Ejemplos JSP

https://www3.ntu.edu.sg/home/ehchua/programming/java/JSPByExample.html

https://beginnersbook.com/jsp-tutorial-for-beginners/

https://www.javatpoint.com/jsp-tutorial

Capturar parámetros:

https://www.javatpoint.com/request-implicit-objectç

Variables de sesión:
https://www.javatpoint.com/session-implicit-object

Para declarar variables o funciones hay que usar el !:

https://www.javatpoint.com/session-implicit-object

Código de algunas páginas:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet"
	href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<!-- jQuery library -->
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- Popper JS -->
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>

<!-- Latest compiled JavaScript -->
<script
	src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
	<h1>Hola Mundo!!</h1>
	<%
	out.print("<p>Vengo del código</p>");
	String nombre = "Juan";
	%>

	<p><%=nombre%></p>

	<%
	double num = Math.random();
	if (num > 0.5) {
		out.print("<h2>Ha salido cara</h2><p>crocretamente ha salido:" + num + "</p>");
	} else{
		out.print("<h2>Ha salido cruz</h2><p>crocretamente ha salido:" + num + "</p>");
	}
	if (num > 0.5) {
	%>
	<h2>Ha salido cara</h2>
	<p>
		crocretamente ha salido:
		<%=num%>
	</p>
	<%
	} else {
	%>
	<h2>Ha salido cruz</h2>
	<p>
		concretamente ha salido:
		<%=num%>#
	</p>
	<%
	}
	%>
	<button class="btn btn-primary">soy codigo</button>

</body>
</html>
	<!-- Imprimo con la función out de JSP -->
	<p>
		<%
		out.print("Esto es código JSP");
		%>
	</p>

	<!-- %= es un atajo si solo quiero imprimir -->
	<p><%="Esto es también"%></p>

	<!-- Uso clases de java -->
	<h3><%=java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("dd-MM-yyy HH:mm"))%></h3>


	<!-- Declaraciones -->
	<%!String nombre = "Ana Pi";

	String saludo(String nombre) {
		return "Hola " + nombre;
	}%>

	<!-- Uso lo declarado -->

	<p><%=saludo(nombre)%></p>
	<p><%=saludo("Juan Buj")%></p>

Ejercicio clases Dungeons & Dragons

Vamos a hacer una especie de juego antiguo de dragones y mazmorras. Tendremos un tablero y en medio estará nuestro héroe. Puede moverse en todas las direcciones y en principio no sabe lo que se va a encontrar. Hay tesoros (que sirven para incrementar nuestra potencia) y monstruos (con los que peleamos). Si derrotamos a todos los monstruos hemos ganado.

Antes de empezar nos pedirá el tamaño del tablero (ancho y alto) aunque tendremos valores por defecto. También el número de monstruos y de tesoros. Se crea el tablero se coloca al héroe y se piden movimientos hasta que el usuario escriba ‘FIN’, se derroten a todos los monstruos o nos muramos.

Cada vez que proporcionamos un movimiento (U,D,L,R) movemos al héroe a esa posición. Las posiciones que no se han visitado se muestran con asterisco, las visitadas se dejan en blanco.

Cuando el héroe encuentra un tesoro se le da el mensaje, las monedas que ha ganado y cuanto se ha incrementado la potencia. Se le pide que pulse una tecla para continuar.

Cuando el héroe encuentra un monstruo se le avisa, se calcula quien ha ganado (un porcentaje respecto a la potencia) y pueden pasar dos cosas:
1.- Gana el héroe: se incrementa su potencia
2.- Pierde el héroe: Se acaba el juego y se le pregunta si quiere volver a empezar.

Esto sería lo básico. Posibles mejoras:

1.- Poción de vida. Si el usuario las encuentra y lo mata un monstruo puede seguir la partida.
2.- Poción de visión: Si el usuario la usa cuando le toca su movimiento puede ver lo que tiene a su alrededor.
3.- Modificar el enfrentamiento para que sea por turnos y que reste ‘vida’ dependiendo de la potencia. Esto nos permitiría tener monstruos con más personalidad (mucha vida pero poca potencia, poca vida pero mucha potencia)
4.- Que las monedas no te den automáticamente potencia, sino que te permitan comprar más vida o más potencia (u otras cosas que se nos puedan ocurrir)
5.- Modo automático: el héroe se mueve a través del tablero aleatoriamente y nos va mostrando los mensajes sin que tengamos que intervenir.
6.- Mundo infinito: Poner puertas en los lados del tablero que nos permitan ir a otras habitaciones que se irán generando.