Como de costumbre en estas notas de J2EE me referiré al pdf del curso de KernelPanik impartido por el gurú Max
y a la copia del pdf que guardo en local
La intención del modelo MVC es la de separar la Vista del Modelo del Controlador ( y es una muy buena intención muy útil ) y eso no se puede hacer bien con los modelos que hemos visto hasta ahora. O metíamos código java en la vista ( la presentación ) haciendo que quedase muy feo y complicado de leer o metemos código html en el modelo haciéndolo imposible de maquetar.
La solución propuesta en java han sido las JSP
Las JavaServer Pages son una tecnología Java por la cual se escriben páginas html con código Java incrustado. El servidor de aplicaciones (el Tomcat en nuestro caso) al detectarlas las compila y las convierte automáticamente en un Servlet por lo que son tan rápidas y potentes como cualquier otro servlet. Pero con la ventaja de tener un aspecto y formato html fácil de de leer, manipular y mantener. Ya que, si lo hacemos bien, tan sólo contiene la presentación de los datos.
Para que el servidor reconozca qué es html y qué es código java y de qué tipo hay cuatro tipo de tags ( etiquetas en adelante) que sirven para que el servidor de aplicaciones reconozca el código java y su carácter.
<%= expresion %> <% out.println(“HOLA MUNDO”.toLowerCase()); %><%@ page import=”org.kernelPanic.MiClasse” %><%! codigo %> Las marcas de inicio y final son <%=expresión%> . Estan pensadas para escribir información de manera dinámica. En pantalla se imprimirá el resultado de evaluar la expresión.
<span><%= "HOLA MUNDO".toLowerCase() %><span>
hará:
<span>hola mundo</span>
Las marcas de inicio y final son <% codi %> . Sirven para incrustar código Java puro y duro en la JSP. Para obtener el mismo <span>hola mundo</span> habrá que hacer esto:
<span><% out.println("HOLA MUNDO".toLowerCase()); %><span>
Se usan para especificar aspectos que afectan a tóda la página. Normalmente se definen al principio del fichero. Controlan ámbitos cómo la inclusión de páginas.
Ejemplos:
<%@ page import=”org.kernelPanic.MiClasse” %>
<%@ page include=”archivoAIncluir.jsp” %>
<%@ page contentType=”text/html; charset=UTF-8” %>
Como se ha comentado por ahi arriba el JSP se convertirá en un Servlet. Las declaraciones sirven para definir variables o métodos fuera del método principal. De este modo se puede llamar a esas variables y métodos desde le método principal
Su sintaxis es :
<%! codigo %>
Ejemplo:
<%@ page import="java.util.Date" %> <%! Date miFecha = new Date(); %> La fechoa es <%= miFecha %>
Una vez que el Servlet controlador ha acabado de realizar todas las acciones que deba realizar es el momento de llamar a las páginas jsp que mostrarán los datos.
Eso se hace mediante el RequestDispatcher. Primero obtenemos el objeto de el HTTPServletResponse y a continuación llamamos a su método forward
RequestDispatcher dispatch=request.getRequestDispatcher("pagina.jsp");
dispatch.forward(request, response);
De este módo se pasa el testigo a la pagina.jsp que se encuentra en la raíz de nuestro proyecto web.
El Servlet y las JSP comparten 3 contextos ( Scopes ) que nos permiten pasar datos de uno al otro.
ex:
request.setAttribute("encuesta", encuesta);
Desde el JSP se pueden recuperar los datos que se han guardado en cada uno de los contextos desde el Servlet.
por ejemplo, para recuperar los datos de la encuesta guardados en el request
request.getAttribute(“encuesta”);
Vamos a incluir una lista de oficios en nuestra encuesta para que la gente pueda decir qué es lo que hace. para ello crearemos una nueva tabla oficios.txt con posibles oficios.
Para usar java dentro de una página JSP la primera opción es incrustar el código, usar un Scriplet. Pero como verás a continuación es una técnica sucia y que produce un código complejo de entender y desagradable.
Primero crearemos un DTO que representará un oficio, y un DAO para acceder a cada uno de ellos a través de un listado.
Oficio.java
package net.juantxu.encuesta.dto;
public class Oficio {
private int id;
private String nombre;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getNombre() {
return nombre;
}
}
OficiosDAO.java
package net.juantxu.encuesta.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import net.juantxu.encuesta.dto.Oficio;
public class OficiosDAO {
private Connection getConnexio() throws NamingException, SQLException {
Connection con;
Context ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/Encuesta");
con = ds.getConnection();
Statement st = con.createStatement();
st.execute("SET NAMES utf8");
return con;
}
public List<Oficio> getOficios() throws NamingException, SQLException {
List<Oficio> lista;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConnexio();
ps = con.prepareStatement("select * from oficio order by nombre" );
rs = ps.executeQuery();
lista = meteEnLista(rs);
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
}
return lista;
}
private List<Oficio> meteEnLista(ResultSet rs)throws SQLException {
ArrayList<Oficio> listado = new ArrayList<Oficio> ();
while (rs.next()) {
Oficio o = new Oficio();
o.setId((Integer)rs.getInt("id"));
o.setNombre(rs.getString("nombre"));
listado.add(o);
}
return listado;
}
}
Fijate que tan sólo queremos añadir un select mas…. y index.jsp queda tal que así:
<%@ page language=“java” contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.Set"%>
<%@ page import="net.juantxu.encuesta.dto.ListaDeOficios"%>
<%@ page import="net.juantxu.encuesta.dao.ListaDeOficiosDAO"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Encuesta de Satisfacción Laborar</title>
</head>
<body>
<h1>Encuesta de satisfacción laboral</h1>
<form name="frmEncuesta" action="EncuestaAccion" method="post">
<label>Quien eres :</label><input type="text" name="nombre" value="tu nombre/ apodo"><br />
<label>Donde Trabajas :</label><input type="text" name="empresa" value="el nombre de tu empresa"><br />
<label>Qué haces :<select name="oficio">
<%
OficiosDAO listado= new OficiosDAO();
List oficios = listado.getOficios();
Iterator i = oficios.iterator();
while (i.hasNext() ){
Oficio o = (Oficio)i.next();
%>
<option value="<%=o.getId()%>"> <%=o.getNombre()%></option>
<%
}%>
</select>
<br />
<label>¿Tipo de Contrato?</label>
<select name="tipoContrato">
<option value="1" >Indefinido</option>
<option value="2" >Obra y servicio</option>
<option value="3" >6 meses</option>
<option value="4" >3 meses</option>
<option value="5" >12 meses</option>
<option value="6" >1/2 jornada indefinido</option>
<option value="7" >1/2 jornada Obra y servicio</option>
<option value="8" >1/2 jornada 6 meses</option>
<option value="9" >1/2 jornada 3 meses</option>
<option value="10" >1/2 jornada 12 meses</option>
<option value="11" >becario</option>
</select>
<br />
( CONTINUA HASTA EL FINAL IGUAL QUE LA PRIMERA VERSIÓN)
Fijate que tenemos que declarar todos los imports en las cabeceras y lo liado y complicado que puede ser tener código java y html todo mezclado.
Para dar una solución a este problema surgió la JAVA STANDARD TAG LIBRARY
Las custom tags no son otra cosa que etiquetas especiales que el programador define para evitar que el código se parezca a lo de aquí arriba. Mediante estas custom tags el programador puede definir unas etiquetas especiales que le indiquen a java que ese código se encuentra en otro lado. Exacto no son más que enlaces al código java de verdad.
Como que se pueden definir a tu gusto, los chicos de Sun nos han proporcionado la JAVA STANDARD TAG LIBRARY que es una especificación de lo que serán las etiquetas mas normales y comunes y qué es lo que deben hacer. ¡Recuerda que es una especificación! no una implementación. No está el código, sinó lo que debe hacer ese código.
Una implementación es lo que han hecho los chicos de jakarta
Nada más sencillo que irte a la página de descargas de las librerías de tags de jakarta y bajarte las librerías 1.1.2 lo descomprimes donde te de la gana y ves lo que hay dentro
jakarta-taglibs-standard-1.1.2/doc jakarta-taglibs-standard-1.1.2/javadoc jakarta-taglibs-standard-1.1.2/lib ==> Aqui están las librerías que nos interesan jakarta-taglibs-standard-1.1.2/tld jakarta-taglibs-standard-1.1.2/LICENSE jakarta-taglibs-standard-1.1.2/NOTICE jakarta-taglibs-standard-1.1.2/README1 jakarta-taglibs-standard-1.1.2/standard-doc.war ==> Esto tambien es interesante jakarta-taglibs-standard-1.1.2/standard-examples.war ==> Y los ejemplos son siempre bienvenidos
Empecemos por lo fácil, los ejemplos y la documentación.
Si copias los war standard-doc.war y standard-examles.war al directorio webapps del tomcat o el servidor de aplicaciones que tengas podrás ver los ejemplos y la documentación de como se hace.
en el caso que estés usando eclipse + tomcat tienes que copiarlos aqui:
<workspace>/.metadata/.plugins./org.eclipse.wst.server.core/tmp0/webapps
Ya que eclipse se crea una copia local del tomcat .
Espero que lo hayas adivinado ya…
En el caso de este servidor es :
El lenguaje de expresiones de JSP es el lenguaje por el cual se evaluan expresiones a fin de imprimir por pantalla el resultado. Generalmente el contenido de las variables evaluadas.
Por ejemplo :
<c:out value=”${expresion}” />
Imprime en el ServletOutputStream el contenido de la variable expresion
La idea es que el servlet, antes de llamar a la JSP le proporciona todas las variables que la JSP va a necesitar o bien en el objeto Request o bien en cualquier contexto que compartan. Para este primer ejemplo usaremos el objeto request.
El Servlet establece un atributo miVar
request.setAttribute(“miVar ”, “Hola soy una variable”);
Que JSP es capaz de recuperar
<c:out value=”${miVar}” />
Si el objeto en el request fuese un JAVA BEAN podemos acceder a la información que contiene mediante la notación de los puntos para acceder a sus getters y setters
<c:out value=”${programador.nombre}” /> ==> invocará a getNombre() para recuperar la información
Y como simpre hay un manual de SUN muy bonito en bárbaro: http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPIntro7.html
Una vez descargadas de la web de Jakarta y descomprimidas, copias el jstl.jar y el standard.jar que hay en el directorio lib del tar que te has bajado en el directorio WEB_INF/lib de tu aplicación web y ya está. Tan complicado como eso.
Para empezar hay que declarar la directiva que indica que vamos a usar una librería de etiquetas y que tiene un aspecto parecido a este:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
A partir de ahora, para hacer referencia a una etiqueta de la librería estandard tan sólo tienes que usar el prefijo y la etiqueta <prefix:tag …> :
<c:forEach var="variable" items="${matriz}" >
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_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Encuesta</display-name> <welcome-file-list> <welcome-file>EncuestaAccion</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>EncuestaAccion</display-name> <servlet-name>EncuestaAccion</servlet-name> <servlet-class> net.juantxu.encuesta.acciones.EncuestaAccion </servlet-class> </servlet> <servlet-mapping> <servlet-name>EncuestaAccion</servlet-name> <url-pattern>/EncuestaAccion</url-pattern> </servlet-mapping> <resource-ref> <description>Conexio BBDD</description> <res-ref-name>jdbc/Encuesta</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>
El Controlador ahora maneja todas las peticiones y hace lo que considera en funcion del tipo de petición. Así, si recive un GET simplemente carga los datos de los oficios y sirve la página. Si recive un POST entiende que primero tiene que guardar los datos que se le mandan y luego retornarte a la página.
EncuestaAccion.java
package net.juantxu.encuesta.acciones;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.juantxu.encuesta.dao.OficiosDAO;
import net.juantxu.encuesta.dao.OpinionDAO;
import net.juantxu.encuesta.dto.Oficio;
import net.juantxu.encuesta.dto.Opinion;
import net.juantxu.encuesta.dto.Satisfaccion;
/**
* Servlet implementation class for Servlet: EncuestaAccion
*
*/
public class EncuestaAccion extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
static final long serialVersionUID = 1L;
/* (non-Java-doc)
* @see javax.servlet.http.HttpServlet#HttpServlet()
*/
public EncuestaAccion() {
super();
}
/* (non-Java-doc)
* @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// como que el listado de oficios lo vamos a necesitar siempre
// he creado un método al que puedo llamar siempre getListaOficios().
request.setAttribute("oficios", getListaOficios() ); // llamo al método en el momento de establecer el atributo
// Pasamos el control al JSP
RequestDispatcher dispatch = request
.getRequestDispatcher("inicio.jsp");
dispatch.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Crear nuevo dao
OpinionDAO DAO = new OpinionDAO();
// Crear una nueva opinion
Opinion opinion = new Opinion();
// Creamos la lista de satisfacciones
ArrayList<Satisfaccion> sats = new ArrayList<Satisfaccion>();
// recuperar parametros de la opinion
opinion.setNombre(request.getParameter("nombre"));
opinion.setEmpresa(request.getParameter("empresa"));
// los ambitos
// pero como que lanza excepciones
HashMap<String, Integer> satisfacciones = new HashMap<String, Integer>();
try {
satisfacciones = DAO.getSatisfacciones();
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
// las satisfacciones
for (int i=1; i<7; i++){
// Crear una nueva satisfaccion
Satisfaccion sat = new Satisfaccion();
sat.setAmbito(i);
sat.setGrado( Integer.parseInt( request.getParameter(Integer.toString(i) ).trim() ) );
sats.add(sat);
}
opinion.setSatisfaccion(sats);
Integer tipoContratoE = new Integer(request.getParameter("tipoContrato"));
// los tipos de contratos
opinion.setTipoContrato(tipoContratoE);
// Abrimos try catch ya que OpinionDAO lanza excepciones
try {
// Guardar la opinion
DAO.guardarOpinion(opinion);
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
// Guardamos el listado de oficios en el request para que luego el jsp pueda recuperarlo
request.setAttribute("oficios", getListaOficios() );
// Pasamos el control al JSP
RequestDispatcher dispatch = request
.getRequestDispatcher("inicio.jsp");
dispatch.forward(request, response);
}
private List<Oficio> getListaOficios(){
List<Oficio> oficios = null;
// Abrimos un try - catch ya que OficiosDAO lanza excepciones
try {
OficiosDAO of= new OficiosDAO();
oficios = of.getOficios();
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
return oficios;
}
}
Por lo que, en el caso de que se recivan datos (POST ):
Opinion.java
package net.juantxu.encuesta.dto;
import java.util.List;
import net.juantxu.encuesta.dto.Satisfaccion;
public class Opinion {
private String nombre;
private String empresa;
private int tipoContrato;
private List<Satisfaccion> Satisfaccion;
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getNombre() {
return nombre;
}
public void setEmpresa(String empresa) {
this.empresa = empresa;
}
public String getEmpresa() {
return empresa;
}
public void setTipoContrato(int tipoContrato) {
this.tipoContrato = tipoContrato;
}
public int getTipoContrato() {
return tipoContrato;
}
public void setSatisfaccion(List<Satisfaccion> satisfaccion) {
Satisfaccion = satisfaccion;
}
public List<Satisfaccion> getSatisfaccion() {
return Satisfaccion;
}
}
Satisfaccion.java
package net.juantxu.encuesta.dto;
public class Satisfaccion {
private int ambito;
private int grado;
public void setAmbito(int ambito) {
this.ambito = ambito;
}
public int getAmbito() {
return ambito;
}
public void setGrado(int grado) {
this.grado = grado;
}
public int getGrado() {
return grado;
}
}
OpinionDAO.java
package net.juantxu.encuesta.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import net.juantxu.encuesta.dto.Opinion;
import net.juantxu.encuesta.dto.Satisfaccion;
public class OpinionDAO {
private Connection getConnexio() throws NamingException, SQLException {
Connection con;
Context ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/Encuesta");
con = ds.getConnection();
return con;
}
public void guardarOpinion(Opinion o) throws NamingException, SQLException{
Connection con = null;
long idEmpresa = 0;
long idUsuario = 0;
try {
con = getConnexio();
// primero la empresa
idEmpresa = insertaEmpresa(o,con);
// luego el usuario
idUsuario = insertaUsuario(o, idEmpresa, con);
// ahora el grado de satisfaccion
insertarSatisfacciones(o, idUsuario, idEmpresa, con);
// insertar el tipo de contrato del usuario
insertarTipoContrato(o, idUsuario, idEmpresa,con);
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (con != null)
con.close();
}
}
public HashMap<String, Integer> getSatisfacciones() throws NamingException, SQLException {
HashMap<String, Integer> lista = new HashMap<String, Integer> ();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConnexio();
ps = con.prepareStatement("select * from ambito" );
rs = ps.executeQuery();
lista = hazMapa(rs);
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
}
return lista;
}
private HashMap<String, Integer> hazMapa(ResultSet rs)throws SQLException {
HashMap<String, Integer> mapa = new HashMap<String, Integer> ();
while (rs.next()) {
mapa.put(rs.getString("nombre"), (Integer)rs.getInt("id"));
}
return mapa;
}
private void insertarTipoContrato(Opinion o, long idUsuario, long idEmpresa,Connection con)throws NamingException, SQLException{
PreparedStatement ps = null;
try {
ps = con.prepareStatement("insert into contratacion (id, usuario, empresa, tipoContrato ) values (0,?,?,?)" );
ps.setLong(1,idUsuario);
ps.setLong(2, idEmpresa);
ps.setInt(3, o.getTipoContrato() );
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (ps != null)
ps.close();
}
}
private void insertarSatisfacciones(Opinion o, long idUsuario, long idEmpresa,Connection con)throws NamingException, SQLException{
PreparedStatement ps = null;
List<Satisfaccion> satisfacciones = o.getSatisfaccion();
try {
Iterator<Satisfaccion> i = satisfacciones.iterator();
while (i.hasNext()){
Satisfaccion s = (Satisfaccion) i.next();
System.out.println("satisfaccion "+s.getAmbito() );
ps = con.prepareStatement("insert into satisfaccion (usuario, empresa, ambito, satisfaccion) values (?,?,?,?)" );
ps.setLong(1,idUsuario);
ps.setLong(2, idEmpresa);
ps.setInt(3, s.getAmbito() );
ps.setInt(4, s.getGrado() );
ps.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (ps != null)
ps.close();
}
}
private long insertaEmpresa(Opinion o, Connection con)throws NamingException, SQLException{
PreparedStatement ps = null;
long id=0;
try {
ps = con.prepareStatement("insert into empresa (id, nombre) values (0, ?)" );
ps.setString(1,o.getEmpresa().trim().toUpperCase());
ps.executeUpdate();
id = recuperarEmpresa(o.getEmpresa().trim().toUpperCase() , con);
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (ps != null)
ps.close();
}
return id;
}
private long recuperarEmpresa(String empresa, Connection con)throws NamingException, SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
long emp = 0;
try {
con = getConnexio();
ps = con.prepareStatement("select id from empresa where upper(nombre) = ?" );
ps.setString(1,empresa.toUpperCase());
rs = ps.executeQuery();
while(rs.next()){
emp = rs.getLong("id");
}
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
}
return emp;
}
private long insertaUsuario(Opinion o, long idEmpresa,Connection con)throws NamingException, SQLException{
PreparedStatement ps = null;
long id = 0;
try {
ps = con.prepareStatement("insert into usuario (id, nombre, empresa, fecha) values (0, ?,?, NOW())" );
ps.setString(1,o.getNombre().trim().toUpperCase());
ps.setLong(2, idEmpresa);
ps.executeUpdate();
id = recuperarUsuario(o.getNombre().trim().toUpperCase(), idEmpresa, con );
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (ps != null)
ps.close();
}
return id;
}
private long recuperarUsuario(String usuario, long empresa, Connection con)throws NamingException, SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
long emp = 0;
try {
con = getConnexio();
ps = con.prepareStatement("select id from usuario where upper(nombre) = ? and empresa = ?" );
ps.setString(1 ,usuario.toUpperCase());
ps.setLong(2, empresa);
rs = ps.executeQuery();
while(rs.next()){
emp = rs.getLong("id");
}
} catch (SQLException e) {
e.printStackTrace();
throw e;
} finally {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
}
return emp;
}
}
En consecuencia, el jsp pasa a ser mucho mas límpio y claro.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Encuesta de Satisfacción Laborar</title>
</head>
<body>
<h1>Encuesta de satisfacción laboral</h1>
<p>
Encuesta a los trabajadores sobre su grado de satisfacción respecto a la empresa en la que trabajan. Los autónomos tambien pueden participar
</p>
<form name="frmEncuesta" action="EncuestaAccion" method="post">
<h2>Encuesta</h2>
<label>Quien
eres :</label><input type="text" name="nombre" value="tu nombre/ apodo"><br />
<label>Donde Trabajas:</label><input type="text" name="empresa"
value="el nombre de tu empresa"><br />
<label>Qué haces :</label> <select name="oficio">
<c:forEach var="oficio" items="${oficios}">
<option value="<c:out value="${oficio.id}" />"><c:out
value="${oficio.nombre}" /></option>
</c:forEach>
</select> <br />
<label>¿Tipo de Contrato?</label> <select name="tipoContrato">
<option value="1">Indefinido</option>
<option value="2">Obra y servicio</option>
<option value="3">6 meses</option>
<option value="4">3 meses</option>
<option value="5">12 meses</option>
<option value="6">1/2 jornada indefinido</option>
<option value="7">1/2 jornada Obra y servicio</option>
<option value="8">1/2 jornada 6 meses</option>
<option value="9">1/2 jornada 3 meses</option>
<option value="10">1/2 jornada 12 meses</option>
<option value="11">becario</option>
</select> <br />
<div id="satisfaccion">
<h3>Grados de Satisfacción laboral</h3>
<p>En una escala del 1 al 10 puntua tus grado de satisfacción
laboral</p>
<c:forEach var="ambito" items="${ambitos}">
<label ><c:out value="${ambito.nombre}" /></label>
<select name="<c:out value="${ambito.id}" />">
<option value="0">??</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
<br />
</c:forEach>
</div>
<input type="submit" value="Enviar" /></form>
<div id="resultados">
<h2>Estadisticas</h2>
<table>
<tr>
<th>Media de satisfacción por ámbitos </th>
</tr>
<c:forEach var="media" items="${estadisticasPorAmbito}" varStatus="status">
<c:choose>
<c:when test="${status.count % 2 == 0}">
<c:set var="bgColor" value="#ffffff"/>
</c:when>
<c:otherwise>
<c:set var="bgColor" value="#cccccc"/>
</c:otherwise>
</c:choose>
<tr bgColor="<c:out value="${bgColor}" />">
<td> <c:out value="${media.nombre}" /> </td>
<td> <c:out value="${media.media}"></c:out></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
Bueno, he metido mucho mas contenido en el JSP para que veas lo largo y guarro que puede llegar a ser. Las librerías de tags nos permiten hacerlo un poquito mas limpio y claro. Aunque a veces, como en el caso del if/else no lo consiguen.
Como puedes ver, he hecho uso de un bucle para recorrer las listas de DTOs que voy insertando en el request. Igualmente se puede hacer uso de variables como el status para establecer el bgcolor de la tabla.
Como que empieza a ser complicado y feo de poner todo aquí te dejo un tar con todo esto y un poquito mas.
Puedes ver como queda aqui