2. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Arquitectura MVC
► Componentes clave
• Modelos: definen los mecanismos para la gestión de los datos en la aplicación.
• Vistas: definen el aspecto de la interfaz de usuario de la aplicación. Es el
código que nos permitirá renderizar los estados de nuestra aplicación en
HTML.
• Controladores: encargados de ofertar el catálogo de acciones que la
aplicación web es capaz de realizar.
Corresponden a la lógica de negocio implementada.
– Ejecuta lógica de negocio asociada y genera una respuesta (normalmente
una vista).
2
3. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Arquitectura MVC
► Ejemplo MVC para un Blog
• /inicio -> página donde se muestran las últimas entradas
3
5. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Crear un servidor Web http
► Modificamos el fichero main.js/app.js
• Los módulos se importan con la función require
• En la variable app creamos una nueva aplicación express
• app.listen indica el puerto en el que el servidor web escucha
• app.listen puede recibir como parámetro una función que se ejecuta cuando el
servidor está listo
5
var express = require('express');
var app = express();
app.listen(8080, function () {
console.log('Servidor listo');
});
6. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Ejecutar proyecto node JS
► El módulo express no está incluido en Node.js debemos instalarlo
► Abrir la consola de comandos cmd
• Acceder al directorio raíz del proyecto (carpeta raíz del proyecto)
• Ejecutar npm install express –save
• Una vez instalado podemos verlo
en el proyecto
6
7. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Procesar peticiones
► Procesar peticiones get (añadir evento get)
• Url donde se escucha
• Función que recibe una req – (request) y una res – (response)
• Request -> parámetros que nos envían
• Response -> respuesta que enviamos al cliente
7
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Petición respondida');
})
app.listen(8080, function () {
console.log("Servidor activo");
})
8. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Rutas
► Ruta con parámetro
• Los parámetros se recuperan con req.params.<nombre_de_parámetro>
► Procesar peticiones POST
8
app.post('/anuncios', function (req, res) {
res.send('Anuncios');
})
app.get('/anuncio/:id/detalles/', function (req, res) {
res.send('Detalles anuncio:'+req.params.id);
})
9. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Leer parámetros POST
► Vamos a realizar una petición POST contra anuncios
• Creamos un fichero prueba.html
• Fuera del proyecto en nuestro escritorio
• Lo abrimos con el navegador local
9
<form method="post" action="http://localhost:8080/anuncio">
Descripcion:<br>
<input type="text" name="descripcion"><br>
Precio:<br>
<input type="text" name="precio" ><br><br>
<input type="submit" value="Enviar">
</form>
10. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Leer parámetros POST
► Para leer parámetros POST (body) necesitamos importar el modulo body-
parser
• No es un modulo incluido en Node.js
• Abrimos la consola de comandos (cmd)
– Nos dirigimos al directorio raíz del proyecto
– Ejecutar npm install body-parser --save
10
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
11. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Leer parámetros POST
► Los parámetros post están en la variable
req.body.<nombre_del_parámetro>
► Probamos a lanzar la petición POST contra /anuncio
11
app.post('/anuncio', function (req, res) {
res.send('Anuncio Guardado:'+req.body.descripcion
+" precio: "+req.body.precio);
})
12. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Express - acceso a ficheros estáticos
► Dentro de la aplicación express podemos
facilitar el acceso a ficheros estáticos
• Páginas HTML, imágenes, vídeos, css.
► Creamos una carpeta public en el
proyecto (dentro de sources)
• Incluimos dentro una imagen y un fichero html
• Una carpeta img y un fichero logo.png
12
13. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Express - acceso a ficheros estáticos
► Para permitir el acceso a esos ficheros utilizamos el
express.static , indicando que permitimos el acceso
a todo lo contenido en la carpeta /public/
► http://localhost:8080/prueba.html
► http://localhost:8080/img/logo.png
13
var express = require('express');
var app = express();
app.use(express.static('public'));
app.listen(8080, function () {
console.log("Servidor activo");
})
15. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Plantillas
• Permiten definir la estructura de documento de salida en una plantilla
• Las plantillas son utilizadas generalmete para crear HTML
► Utilizaremos swig
• http://node-swig.github.io/swig-templates/docs/
15
16. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Swig es un módulo no incluido nativamente en Node.js
• Abrimos la consola de comandos, accedemos al directorio raíz del proyecto
• Ejecutamos el comando npm install swig –save, npm install swig@1.4.2 --
save
16
17. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Dentro del proyecto creamos el fichero anuncios.html
• Lo guardamos en la carpeta /plantillas (raíz de sources)
• Las plantillas no tienen que tener ninguna extensión específica (como en
twig)
► Anuncios.html recibirá dos parámetros vendedor y anuncios (lista)
17
<html>
<body>
<h1>{{ vendedor }}</h1>
<ul>
{% for anuncio in anuncios %}
<li>
{{ anuncio.descripcion }} - {{ anuncio.precio }}
</li>
{% endfor %}
</ul>
</body>
</html>
18. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Se pueden incluir muchas otras etiquetas, muchas de ellas son
similares a las de else if, for, block...
• http://node-swig.github.io/swig-templates/docs/
18
19. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Para poder utilizar swig importamos el módulo
• require(swig)
• Nos devuelve un objeto capaz de renderizar plantillas
19
var express = require('express');
var app = express();
var swig = require('swig');
app.listen(8080, function () {
console.log("Servidor activo");
})
20. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Creamos la estructura anuncio (emulada mediante funciones)
20
app.listen(8080, function () {
console.log("Servidor activo");
})
function Anuncio (descripcion, precio) {
this.descripcion = descripcion;
this.precio = precio;
}
21. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Vistas y plantillas
► Recogemos la petición /anuncios
21
app.get('/anuncios', function (req, res) {
var pro1 = new Anuncio("Nokia 230",56);
var pro2 = new Anuncio("Nokia 730",156);
var pro3 = new Anuncio("Nokia 635",173);
var anuncios = [pro1,pro2,pro3];
var respuesta = swig.renderFile('plantillas/anuncios.html', {
vendedor: 'Jordan',
anuncios: anuncios
});
res.send(respuesta);
})
23. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Bases de datos no relacionales (MongoDB)
► La información de almacena en documento siguiendo una estructura
BSON
• Formato similar al JSON pero más ligero
https://www.mongodb.com/json-and-bson
23
24. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Bases de datos no relacionales (MongoDB)
► Los documentos pueden contener atributos:
• Cadenas de texto, números, arrays de elementos, objetos (otros documentos),
booleanos, binarios, valores nulos, fechas, etc.
24
{
nombre: "Cambiar ordenadores",
equipos: 3,
direccion: "Piso1",
detalles: {
categoria: "mantenimiento",
coste: 4233
},
incidencias: [
{
descripcion: "Inicio sin problemas",
fecha:"23-06-2016"
},
{
descripcion: "Falta de material",
fecha:"24-06-2016"
},
]
}
25. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Bases de datos no relacionales (MongoDB)
► Estructura
• Dentro de un servidor MongoDB podemos tener varias Bases de datos
• Una colección se utiliza para agrupar datos (documentos)
– Similar a una tabla
– Pero no define ningún esquema fijo
o No hay un conjunto de atributos tipo que deban tener todos los
documentos
• Documento, contiene los datos, cada documento puede tener diferentes
atributos (incluso estando en la misma colección)
25
26. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Acceso a datos Mongo DB
► Mongo BD en la nube:
• https://cloud.mongodb.com
► Alternativa para conectarse a una BD mongo desde node.js
• Módulo mondogb
• Accedemos a la consola de comandos CMD al directorio de la aplicación
• Ejecutamos el comando npm install mongodb --save
26
27. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Acceso a datos Mongo DB
► Se debe incluir el uso del módulo require(‘mongodb’).
• En este ejemplo usaremos además:
– express.static (para fijar una carpeta estática)
– Módulo body-parser , para procesar post
27
var express = require('express');
var app = express();
app.use(express.static('public'));
var bodyParser = require('body-parser');
app.use(bodyParser());
// Cliente de Mongo
var MongoClient = require('mongodb').MongoClient;
28. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Acceso a datos Mongo DB
► Parte estática
• Creamos un directorio /public
• Dentro de el creamos formulario.html
28
<form method="post" action="anuncio">
Descripcion:<br>
<input type="text" name="descripcion"><br>
Precio:<br>
<input type="number" name="precio" ><br>
<input type="submit" value="Enviar">
</form>
29. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Bases de datos no relacionales (MongoDB)
► Descargamos el comunity server:
• https://www.mongodb.com/download-center
• Seguimos los pasos de instalación
► Creamos en nuestro disco la carpeta C:/data/db
• Es el directorio por defecto donde se guardarán los datos
► Una vez finalizada la ejecución agregamos al PATH la ruta:
C:Program FilesMongoDBServer3.2bin
• https://www.java.com/es/download/help/path.xml
29
30. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB
► Arrancamos el servidor Mongo DB
• Desde C:Program FilesMongoDBServer3.2bin
• Ejecutamos
mongod
• * Si falla, usar esta alternativa:
mongod --storageEngine=mmapv1
mongod --dbpath "C:data" --storageEngine=mmapv1
– Asegurarse de que el directorio dbpath es correcto
► Probamos a acceder a la URL: http://localhost:27017
30
31. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB
► POST : /anuncio, recibe los parámetros descripción y precio
• La función connect() establece conexión con la base de datos
• Recibe:
– La cadena de conexión
– Función de ejecución después de la conexión
31
app.post('/anuncio', function (req, res) {
// Abrir el cliente
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
});
})
32. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB
► Ejemplo, acceder a la colección de anuncios
• var collection = db.collection('anuncios')
• Sobre la colección se pueden realizar operaciones
– Insertar
– Eliminar
– Modificar
► Además del parámetro correspondiente
► Estas acciones reciben como parámetro una función
• La función se ejecuta cuando acaba de insertar, eliminar o modificar
32
33. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB
► Ejemplo
33
app.post('/anuncio', function (req, res) {
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
var collection = db.collection('anuncios');
var anuncio1 = new Anuncio(req.body.descripcion,
parseFloat(req.body.precio));
collection.insert(anuncio1, function (err, result) {
if (err) {
res.send("Error al insertar "+err);
} else {
res.send('Anuncio Insertado '+ result);
}
// Cerrar el cliente
db.close();
});
});
})
34. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB - Consultas
► Cuando tenemos la colección podemos hacer un find
• find({}) sin argumentos selecciona todos los registros de la colección
• El resultado del find se puede pasar a un array función toArray()
34
app.get('/anuncios', function (req, res) {
// Abrir el cliente
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
var collection = db.collection('anuncios');
collection.find({}).toArray(function(err, anuncios){
db.close();
res.send(anuncios);
});
}
);
})
35. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB - Consultas
► Para incluir un criterio de búsqueda se deben utilizar un filtro en el
find
• find({ precio : 1500 })
• find({ nombre : ‘jordan’ })
► El caso de la _id es especial
• Es un objeto no un tipo simple
• Hay que usar la función ObjectID
– Contenida en el módulo mongodb
35
var id = require('mongodb').ObjectID(req.params.id);
36. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
MongoDB - Consultas
► Ejemplo consulta por _id
36
app.get('/anuncio/:id', function (req, res) {
// Abrir el cliente
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
var collection = db.collection('anuncios');
// Transformar _id a Mongo ObjectID
var id = require('mongodb').ObjectID(req.params.id);
collection.find({ _id : id }).toArray(function(err, anuncios){
db.close();
res.send(anuncios);
});
});
})
37. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Mongo - Modificar
► Función update, parámetros:
• Selección: filtro de selección (para ver qué documento se va a modificar)
• Modificación: Nuevo documento a insertar en lugar del antiguo / atributos a
modificar en el documento $set
• Función : se ejecuta al acabar la consulta
37
collection.update({ _id : id }, anuncio1, <función> }
collection.update({ _id : id },
{$set: { descripcion : descripcion}}, <function>
38. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Mongo - Modificar
► Ejemplo
38
app.post('/anuncio/:id', function (req, res) {
// Abrir el cliente
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
var anuncio1 = new Anuncio(req.body.descripcion,
parseFloat(req.body.precio));
var collection = db.collection('anuncios');
// Transformar a Mongo ObjectID
var id = require('mongodb').ObjectID(req.params.id);
collection.update({ _id : id }, anuncio1, function (err, result) {
if (err) {
res.send("Error al modificar "+err)
} else {
res.send('Modificado '+ result);
}
db.close();
});
});
})
39. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Mongo - Eliminar
► Función remove, parámetros:
• Selección: filtro de selección (para ver qué documento se va a modificar)
• Función : se ejecuta al acabar la consulta
39
collection.remove({ _id: id }, <function> )
40. Diseño de arquitecturas basadas en cliente-servidor y protocolos de comunicación entre aplicaciones
Mongo - Eliminar
► Ejemplo
40
app.get('/anuncio/eliminar/:id', function (req, res) {
MongoClient.connect('mongodb://localhost:27017/anuncios',
function(err, db) {
var collection = db.collection('anuncios');
// Transformar a Mongo ObjectID
var id = require('mongodb').ObjectID(req.params.id);
collection.remove({ _id: id }, function (err, result) {
if (err) {
console.log("Error al eliminar "+err)
} else {
res.send("Anuncio Eliminado");
db.close();
}
});
});
})