El desarrollar aplicaciones web involucra la configuración de varias herramientas y tecnologías, peor aun si lo vemos desde una perspectiva de mantenibilidad; por ejemplo que la aplicación requiera constantes cambios. A principios en java esto fue una tarea difícil; poco a poco fueron apareciendo tecnologías posteriores a los servlets; estas facilitando en gran medida el desarrollo de aplicaciones web, por que no es que los servlets estén obsoletos.
Esta guía trata de brindar un breve vistazo sobre Struts 2, un framework para el desarrollo web que simplifica en gran medida el estilo de programación de Servlets y JSPs; mostrando a la vez como se integra con Spring para poder hacerle inyección de dependencias a las clases controladoras de struts . Además utilizaremos el framework Spring para facilitar el ingreso y obtención de datos por medio del uso de JdbcTemplate .
La ventaja del uso de la tecnología Spring en aplicaciones es claramente la Inversion De Control (IoC, por sus siglas en inglés) y la inyección de dependecias; ya que permite desarrollar sistemas de todo tipo con previstas a cambios futuros y con la facilidad de poder configurar todos los componentes desde un contenedor, situación que provoca que el sistema sea fácilmente mantenible.
Descripción
La aplicación consiste en una sencilla aplicación web que ingresa y consulta trabajadores basada en MVC mediante Struts Framework 2.
Conocimientos
Conocimientos básicos en: Html, Java y JSP. Además de conocer un poco el entorno de desarrollo Eclipse , el servidor java que este utilizando y mysql .
Requerimientos
Estos requerimientos son para seguir paso a paso la guía.
- Eclipse Galileo (For Java EE Developers), preferiblemente aunque puede ser otra distribución que permita el desarrollo de Dynamic Web Projects.
- Spring Tool Suite.
- Servidor Java local para correr la aplicación, en este caso utilicé JBoss 5.1, pero de igual manera puede optarse por Apache Tomcat.
- Servidor MySQL local, para poder instalar la base de datos a la cual se va a conectar la aplicación y las herramientas para administrar servidor(Opcional).
Librerias de las que depende el proyecto
Struts: junto con sus dependencias, se pueden encontrar en la distribución 2.x.x al descargarla. Estas son: struts2-core-xxxx.jar, commons-fileupload-xxxx.jar, freemarker-xxxx.jar, ognl-xxx.jar, commons-io-xxxx.jar, xwork-core-xxx.jar y struts2-spring-plugin-xxxxx.jar.
Spring: esta es una implementación de la versión 3.x.x (En el paso 3 muestro las librerías necesarias para realizar este proyecto; no vamos a utilizar todos los módulos de spring).
Conector Java Para MySQL.
Además deberá de incluirse la librería commons-logging.jar en caso que el servidor sea distinto(yo he necesitado esa librería para correr la aplicación en Tomcat) a JBoss 5.1
Pasos:
- Comenzaremos creando un proyecto Dynamic Web Project en Eclipse, File->New->Dynamic Web Project, el cual llamaremos Ejemplo. Si bien ya previamente habían configurado un servidor simplemente lo seleccionan del combo box Target Runtime, si no deberán crear uno nuevo (1); los pasos para realizar eso es muy simple, solamente deben de seleccionar la versión del servidor que tienen instalado e indicar en que parte se encuentra instalado. Luego damos Finish.

- Ahora procederemos a configurar las librerías que utilizara nuestro proyecto; primero se selecciona el proyecto en el Project Explorer y luego vamos a a la barra de menú en Project->Properties . Aqui configuraremos (1 y 2) librerías de usuario (User Library) con los respectivos jar de struts, mysql-connector y de spring, mediante la opción Add Library. Seguidamente se procede a pegar (3) copiar directamente las librerías necesarias en la carpeta lib, para que sean referenciadas en tiempo de ejecución de la aplicacion.


- A continuación procederemos a crear la base de datos en mysql con el nombre “ejemplos” y la tabla “trabajadores” que utilizaremos.CREATE DATABASE IF NOT EXISTS ejemplos;
USE ejemplos;
--
-- Definition of table `trabajadores`
--
DROP TABLE IF EXISTS `trabajadores`;
CREATE TABLE `trabajadores` (
`id` varchar(20) NOT NULL,
`nombre` varchar(20) NOT NULL,
`departamento` varchar(20) NOT NULL DEFAULT 'No Asignado',
`numero_trabajador` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`numero_trabajador`) USING BTREE,
UNIQUE KEY `Index_2` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1; - En el proyecto en eclipse crearemos la clase Trabajador.java con sus respectivos 3 atributos y métodos (getters y setters para los atributos) que va a ser la unidad del negocio en este ejemplo en el paquete com.misBeans:package com.misBeans;
public class Trabajador {
private String id;
private String nombre;
private String departamento;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDepartamento() {
return departamento;
}
public void setDepartamento(String departamento) {
this.departamento = departamento;
}
} - Creamos la interfaz TrabajadorDAO.java en un paquete llamado com.daos para implementar una clase de acceso de datos con un método para ingresar que tenga un parámetro del tipo trabajador y otro método para listar que nos devuelta objetos del tipo Trabajador.package com.daos;
import java.util.List;
import com.misBeans.Trabajador;
public interface TrabajadorDAO {
public boolean ingresarEmpleado(Trabajador t);
public List<Trabajador> listarEmpleados();
} - Ahora generamos una clase en el paquete mencionado en el punto anterior con el nombre TrabajadorDAOImplementacion con eclipse que implemente la interfaz creada previamente, ya por creada de igual forma con las herramientas para la manipulación de código fuente implementamos los métodos asignados en la interfaz. Asignamos el atributo plantilla del tipo JdbcTemplate. Además debemos agregar el método setDataSource(DataSource dataSource) para que spring pueda hacer una inyección de dependecia a la clase para instanciar plantilla mediante un bean en el contenedor que definiremos para asignar los datos con los cuales se conectara a la base de datos (driver, usuario, contraseña, url).package com.daos;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.misBeans.Trabajador;
public class TrabajadorDAOImplementacion implements TrabajadorDAO {
private JdbcTemplate plantilla;
public void setDataSource(DataSource dataSource) {
// se instancia plantilla con la inyeccion del datasource
this.plantilla = new JdbcTemplate(dataSource);
}
@Override
public boolean ingresarEmpleado(Trabajador t) {
// TODO Auto-generated method stub
// ingresamos 1 trabajador con el metodo update de plantilla
try {
this.plantilla.update("INSERT INTO trabajadores(id,nombre,departamento) VALUES(?,?,?)", t
.getId(), t.getNombre(), t.getDepartamento());
return true;
} catch (DataAccessException e) {
return false;
}
}
@Override
public List<Trabajador> listarEmpleados() {
// TODO Auto-generated method stub
// realizamos la consulta de de trabajadores
return this.plantilla.query("SELECT * FROM trabajadores" +
" ORDER BY numero_trabajador DESC LIMIT 10",
// se mapea el resultado de la consulta para que query
// retorne una lista con objetos de tipo Trabajador
new RowMapper<Trabajador>() {
public Trabajador mapRow(ResultSet rs, int rowNum)
throws SQLException {
Trabajador t = new Trabajador();
t.setId(rs.getString("id"));
t.setNombre(rs.getString("nombre"));
t.setDepartamento(rs.getString("departamento"));
return t;
}
});
}
}
- tDAO(tipo TrabajadorDAO, que la inicializara Spring mediante inyección de dependencia).
- id, nombre y departamento (los datos que se ingresaran desde el formulario ).
- trabajadores (atributo que sera llenado para la accion).
Aparte de esos, se definirán los siguientes métodos en la clase: Para los atributos id, nombre y departamento deberán asignarse métodos get y set respectivamente; para tDAO solo el método set y para el atributo trabajadores el método get.
package com.struts;
import java.util.List;
import com.daos.TrabajadorDAO;
import com.misBeans.Trabajador;
import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator;
import com.opensymphony.xwork2.validator.annotations.Validation;
public class ControladorTrabajador{
private TrabajadorDAO tDAO;
private String id;
private String nombre;
private String departamento;
private List<Trabajador> trabajadores;
public String ingresar() throws Exception {
//se instancia un objeto tipo trabajador
// se llena con los datos del formulario
Trabajador t = new Trabajador();
t.setId(getId());
t.setNombre(getNombre());
t.setDepartamento(getDepartamento());
//se llamado el metodo para ingresar enviando t
if(this.tDAO.ingresarEmpleado(t))
return "success";
else return "error";
}
public String listar() throws Exception{
//llamada al metodo para listar del objeto tDAO
// al retornar una lista con objetos se debe realizar un casting
this.trabajadores = (List<Trabajador>) this.tDAO.listarEmpleados();
return "success";
}
public void settDAO(TrabajadorDAO tDAO) {
this.tDAO = tDAO;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDepartamento() {
return departamento;
}
public void setDepartamento(String departamento) {
this.departamento = departamento;
}
public List<Trabajador> getTrabajadores() {
return trabajadores;
}
}
import java.util.List;
import com.daos.TrabajadorDAO;
import com.misBeans.Trabajador;
import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator;
import com.opensymphony.xwork2.validator.annotations.Validation;
public class ControladorTrabajador{
private TrabajadorDAO tDAO;
private String id;
private String nombre;
private String departamento;
private List<Trabajador> trabajadores;
public String ingresar() throws Exception {
//se instancia un objeto tipo trabajador
// se llena con los datos del formulario
Trabajador t = new Trabajador();
t.setId(getId());
t.setNombre(getNombre());
t.setDepartamento(getDepartamento());
//se llamado el metodo para ingresar enviando t
if(this.tDAO.ingresarEmpleado(t))
return "success";
else return "error";
}
public String listar() throws Exception{
//llamada al metodo para listar del objeto tDAO
// al retornar una lista con objetos se debe realizar un casting
this.trabajadores = (List<Trabajador>) this.tDAO.listarEmpleados();
return "success";
}
public void settDAO(TrabajadorDAO tDAO) {
this.tDAO = tDAO;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDepartamento() {
return departamento;
}
public void setDepartamento(String departamento) {
this.departamento = departamento;
}
public List<Trabajador> getTrabajadores() {
return trabajadores;
}
}

Damos Project->Properties en la barra de menú. Nos vamos a Java Build Path y en la pestaña Source seleccionamos Add Folder, se necesita expandir la carpeta Ejemplo y se marca el src del proyecto de eclipse.

La primera definición de bean sera para el data source tal y como se ve en la imagen inferior. Se debe de llenar el campo Id y la clase que se va a utilizar para el objeto (el botón browse facilita la búsqueda de la clase, en este caso DriverManagerDataSource para conectar con la Base de Datos), damos Next





<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="ds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
<property name="url"
value="jdbc:mysql://localhost:3307/ejemplos">
</property>
</bean>
<bean id="trabajadorDAO"
class="com.daos.TrabajadorDAOImplementacion">
<property name="dataSource" ref="ds"></property>
</bean>
<bean id="ControladorTrabajador" class="com.struts.ControladorTrabajador">
<property name="tDAO" ref="trabajadorDAO"></property>
</bean>
</beans>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="ds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
<property name="url"
value="jdbc:mysql://localhost:3307/ejemplos">
</property>
</bean>
<bean id="trabajadorDAO"
class="com.daos.TrabajadorDAOImplementacion">
<property name="dataSource" ref="ds"></property>
</bean>
<bean id="ControladorTrabajador" class="com.struts.ControladorTrabajador">
<property name="tDAO" ref="trabajadorDAO"></property>
</bean>
</beans>
En este archivo declaramos dos acciones:
- IngresarTrabajador:Se encargara de procesar los datos al ingresarlos al formulario y esta enlazada al método ingresar de la clase ControladorTrabajador.
- Formulario:Se encargara de consultar los trabajadores ingresados y esta enlazada al método listar de laclase ControladorTrabajador.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory"
value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<package name="default" extends="struts-default">
<action name="IngresarTrabajador" class="ControladorTrabajador" method="ingresar">
<result name="success" type="redirectAction">Formulario</result>
<result name="error" type="redirectAction">Formulario</result>
<result name="input">/index.jsp</result>
</action>
<action name="Formulario" class="ControladorTrabajador" method="listar">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory"
value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<package name="default" extends="struts-default">
<action name="IngresarTrabajador" class="ControladorTrabajador" method="ingresar">
<result name="success" type="redirectAction">Formulario</result>
<result name="error" type="redirectAction">Formulario</result>
<result name="input">/index.jsp</result>
</action>
<action name="Formulario" class="ControladorTrabajador" method="listar">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
Configuración del archivo web.xml, lo único que tenemos que agregar serian la definición del filtro junto con su respectivo mapeo por url para la invocación de las acciones que se realizan en cualquier implementación básica de Struts 2 y además deberemos definir el listener de Spring que se encargará de iniciar el contexto junto con todos los beans que se coloquen en el archivo applicationContext.xml exponiéndolos para que queden listos para su uso.
<?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>Ejemplo</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
<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>Ejemplo</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
A continuación creamos el archivo index.jsp que va a ser la vista de nuestra aplicación web, como se puede observar en la línea 3 importamos la etiquetas de struts y utilizamos el prefijo “s” para incrustar los componentes en el archivo, el resto de los detalles se explican en el archivo.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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=ISO-8859-1"></meta>
<title>@SOTTO</title>
<link href="estilos.css" rel="stylesheet" type="text/css"></link>
</head>
<body>
<div>
<a id="titulo1">@SOTTO</a> <a id="titulo2">www.asotto.blogspot.com </a>
</div>
<%-- Declaramos un formulario de struts que va a usar la accion que definimos
para que haga el ingreso de datos
--%>
<s:form action="IngresarTrabajador">
<%-- los campos tienen los mismos nombres que los atributos de la clase ControladorTrabajador --%>
<s:textfield name="id" label="Id"></s:textfield>
<s:textfield name="nombre" label="Nombre"></s:textfield>
<s:select label="Departamento" name="departamento"
list="{'Taller', 'Oficina', 'Planta'}"></s:select>
<s:submit value="Ingresar"></s:submit>
</s:form>
<table>
<tr class="tencabezado">
<td>ID</td>
<td>NOMBRE</td>
<td>DEPARTAMENTO</td>
</tr>
<%-- este iterador sirve para llenar la tabla con los trabajadores
cuando se es llamada la accion Formulario
desde el navegador --%>
<s:iterator value="trabajadores">
<tr>
<td><s:property value="id" /></td>
<td><s:property value="nombre" /></td>
<td><s:property value="departamento" /></td>
</tr>
</s:iterator>
</table>
</body>
</html>
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!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=ISO-8859-1"></meta>
<title>@SOTTO</title>
<link href="estilos.css" rel="stylesheet" type="text/css"></link>
</head>
<body>
<div>
<a id="titulo1">@SOTTO</a> <a id="titulo2">www.asotto.blogspot.com </a>
</div>
<%-- Declaramos un formulario de struts que va a usar la accion que definimos
para que haga el ingreso de datos
--%>
<s:form action="IngresarTrabajador">
<%-- los campos tienen los mismos nombres que los atributos de la clase ControladorTrabajador --%>
<s:textfield name="id" label="Id"></s:textfield>
<s:textfield name="nombre" label="Nombre"></s:textfield>
<s:select label="Departamento" name="departamento"
list="{'Taller', 'Oficina', 'Planta'}"></s:select>
<s:submit value="Ingresar"></s:submit>
</s:form>
<table>
<tr class="tencabezado">
<td>ID</td>
<td>NOMBRE</td>
<td>DEPARTAMENTO</td>
</tr>
<%-- este iterador sirve para llenar la tabla con los trabajadores
cuando se es llamada la accion Formulario
desde el navegador --%>
<s:iterator value="trabajadores">
<tr>
<td><s:property value="id" /></td>
<td><s:property value="nombre" /></td>
<td><s:property value="departamento" /></td>
</tr>
</s:iterator>
</table>
</body>
</html>
Y para darle un poco de forma a la interfaz usamos esta hoja de estilos.
@charset "utf-8";
/* CSS Document */
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 11px;
}
#titulo1 {
font-family: Verdana, Geneva, sans-serif;
font-size: 24px;
color: #333;
}
.tencabezado {
background-color: #09C;
color: #FFF;
font-style: normal;
font-weight: bold;
}
td {
width: 200px;
}
#titulo2 {
font-size: 14px;
color: #099;
font-style: italic;
}
/* CSS Document */
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 11px;
}
#titulo1 {
font-family: Verdana, Geneva, sans-serif;
font-size: 24px;
color: #333;
}
.tencabezado {
background-color: #09C;
color: #FFF;
font-style: normal;
font-weight: bold;
}
td {
width: 200px;
}
#titulo2 {
font-size: 14px;
color: #099;
font-style: italic;
}
- El archivo desplegable en el servidor(.war) :
- El comprimido zip en:
Con este tutorial espero que puedan ser entendidas algunas de las capacidades que tiene el framework Spring.

Man, muy buen ejemplo!
ResponderSuprimirEn lo personal si quieres velocidad y usar tecnologia equivalentes, te recomiendo usar Spring Roo! Ademas con el ide de spring que estas usando, resulta mas sencillo, pues viene integrado para que el AOP funcione!
A mi me encanta Struts y trabaje con el, por mas de 7 anos, tanto en la version 1.0, 1.1, 1.2 y 2.X
Tambien he trabajado con SpringMvc 2.x y 3.x
Pero te recomiendo hechar un vistaso a Apache Stripes, si yo se un framework mas, pero es tan sencillo y poco intrusivo que la verdad lo quiero mucho! Ademas ocupa muy poca configuracion o casi nada!
Ah para la base de datos, DDLUtil te puede servir, genera a partir de un XML, el sql necesario para diferentes servidores y puede usar liquibase, para gestionar los cambios en tu base de datos!
Un saludo,
J
Saludos.... Pura vida, muchas gracias.... Si la verdad que las herramientas en java permiten gran flexibilidad, voy a probarlo... Otro framework que me encanta para la capa de navegador es icefaces....
ResponderSuprimirYo quede curado con los esquemas MVP, asi que face, muy bonito pero de lejos! y me parece que el mecanismo de server push, lo sacaron aparte, asi que....
ResponderSuprimirOtra cosa que podes usar, es Maven, supongo que ya lo debes conocer, sirve para manejar el ciclo de vida del proyecto, entre un monton de cosas mas
ResponderSuprimirhttp://jsanca.ticoblogger.com/search/label/maven
Al final podras encontrar un articulo que escribi, sobre introduccion a Maven y segui escribiendo! ayuda aprender, a que otros aprendan y de memoria de largo plaza!
claro lo he escuchado maneja las dependencias del proyecto y lo configura, lo independiza a uno de andar buscando librerias por todo lado... muchas gracias voy a probarlo para ver que tal es para eclipse... Pero en curva de aprendiza jsf y icefaces es menos empinada... Saludos
ResponderSuprimirhttp://apps.facebook.com/herolegend/?ftype=flyfish&uid=100001743240536
ResponderSuprimir