0% encontró este documento útil (0 votos)
41 vistas

RESUMEN JAVA ENTREVISTAS v2

El documento describe conceptos básicos de Java como JVM, modificadores de acceso, tipos de datos, estructuras de control, excepciones, herencia, encapsulación, polimorfismo y otros. Explica cada concepto con definiciones, ejemplos y detalles importantes.

Cargado por

Lisset Ramirez
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
41 vistas

RESUMEN JAVA ENTREVISTAS v2

El documento describe conceptos básicos de Java como JVM, modificadores de acceso, tipos de datos, estructuras de control, excepciones, herencia, encapsulación, polimorfismo y otros. Explica cada concepto con definiciones, ejemplos y detalles importantes.

Cargado por

Lisset Ramirez
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 12

• JVM/JRE/JDK (Java Virtual Machine/Java Runtime Ejemplo:

Environment/Java Development Kit): for (int i = 0; i < 5; i++) {


Concepto: La JVM es una máquina virtual que ejecuta programas System.out.println("Iteración " + i);
escritos en Java. El JRE es un conjunto de herramientas necesarias }
para ejecutar aplicaciones Java. El JDK es un conjunto completo de
herramientas para desarrollar aplicaciones Java. • Casting entre tipos objeto:
Lo más importante: La JVM es crucial porque permite la portabilidad Concepto: El casting entre tipos de objetos en Java convierte un
del código Java en diferentes plataformas. objeto de un tipo a otro.
Ejemplo: Al escribir y compilar un programa Java en un sistema Lo más importante: Puede haber casting explícito (downcasting) y
operativo, se puede ejecutar en cualquier sistema que tenga una casting implícito (upcasting).
JVM compatible. - El casting implícito ocurre cuando se convierte un subtipo
en un supertipo.
• Modificadores de acceso: - El casting explícito se utiliza cuando se convierte un
Concepto: Los modificadores de acceso en Java controlan la supertipo en un subtipo.
visibilidad de clases, variables, métodos y constructores.
Lo más importante: Los modificadores de acceso más comunes son
public, protected, default (sin modificador) y private.
▪ public: Accesible desde cualquier clase.
▪ protected: Accesible dentro del mismo paquete o subclases.
▪ default: Accesible dentro del mismo paquete.
▪ private: Accesible solo dentro de la misma clase.
Ejemplo:
public class Ejemplo {
private int variablePrivada;
public void metodoPublico() {
// Código aquí
}
}

• Tipos de datos:
Concepto: Los tipos de datos en Java definen el tipo de valores que
pueden ser almacenados y manipulados en una variable
Lo más importante: Java tiene tipos de datos primitivos (8) (byte,
short, int, long, float, double, char y boolean) y tipos de datos de
objeto (como String, Integer, etc.).
Los tipos de datos primitivos almacenan valores directamente,
mientras que los tipos de datos de objeto almacenan referencias a
objetos en la memoria.
Es importante entender los límites y el almacenamiento de los tipos
de datos primitivos para evitar desbordamientos y errores de
precisión.
Ejemplo:
int entero = 10;
double decimal = 3.14;
String texto = "Hola mundo";
Ejemplo:
• Estructuras repetitivas: Object objeto = "Hola";
Concepto: Las estructuras repetitivas en Java permiten ejecutar un String cadena = (String) objeto;
bloque de código varias veces.
Lo más importante: Las estructuras repetitivas más comunes son for, • Operador instanceof:
while y do-while. Concepto: El operador instanceof en Java se utiliza para verificar si
▪ for: Se utiliza cuando se conoce el número de iteraciones. Es útil un objeto es una instancia de una clase, subclase o interfaz.
para iterar sobre una secuencia o colección de elementos. Lo más importante: Devuelve true si el objeto es una instancia de la
▪ while: Se utiliza cuando la condición de bucle se evalúa antes clase especificada, de lo contrario, devuelve false.
de cada iteración. Puede no ejecutarse si la condición Ejemplo:
inicialmente es falsa. Object objeto = "Hola";
▪ do-while: Similar a while, pero garantiza que el bloque de if (objeto instanceof String) {
código se ejecute al menos una vez antes de evaluar la System.out.println("El objeto es una instancia de String");
condición. }
• Error vs. Excepción: System.out.println("El perro ladra");
Concepto: En Java, un error es una situación grave que no debería }
ser manejada en tiempo de ejecución, mientras que una excepción }
es una situación excepcional que puede ser manejada en tiempo de
ejecución. Uso de Herencia:
Lo más importante: Los errores son irreparables y generalmente se Teoría: La herencia es un concepto en el que una clase (subclase)
deben a problemas fuera del control del programador, mientras que puede heredar atributos y métodos de otra clase (superclase).
las excepciones son eventos inesperados que pueden y deben ser Lo más importante: Permite la reutilización de código y la creación
manejados. de jerarquías de clases.
Ejemplo: Un error de OutOfMemoryError ocurre cuando no hay Ejemplo:
suficiente memoria disponible para ejecutar una aplicación, class Vehiculo {
mientras que una excepción NullPointerException ocurre cuando se void conducir() {
intenta acceder a un objeto nulo. Las excepciones en Java se pueden System.out.println("Conduciendo el vehículo");
manejar utilizando bloques try-catch }
}
• Propagación de excepciones vs. Lanzamiento de
excepción: class Coche extends Vehiculo {
Concepto: La propagación de excepciones en Java es el proceso de // Hereda el método conducir de la clase Vehiculo
pasar una excepción de un método a su llamador, mientras que el }
lanzamiento de excepción es el proceso de generar manualmente
una excepción. Uso de Encapsulación:
Lo más importante: Las excepciones pueden propagarse Teoría: La encapsulación es el mecanismo de ocultar los detalles de
automáticamente a través de las llamadas de método en Java, o implementación de una clase y restringir el acceso directo a los
pueden ser lanzadas explícitamente con la palabra clave throw. campos de datos.
Ejemplo: Lo más importante: Se utiliza para garantizar la coherencia de los
public void metodo1() throws Exception { datos y para proteger los datos sensibles de modificaciones no
// deseadas.
Overloading (Sobrecarga): Ejemplo:
Teoría: Overloading se refiere a la capacidad de definir varios class Persona {
métodos en una clase con el mismo nombre pero diferentes tipos de private String nombre;
parámetros o número de parámetros. private int edad;
Lo más importante: Los métodos sobrecargados deben diferir en su // Métodos getter/ setter para acceder a los campos encapsulados
firma, es decir, en el número o tipo de parámetros. public String getNombre() {
Ejemplo: return nombre;
class Calculadora { }
int sumar(int a, int b) { public void setNombre(String nombre) {
return a + b; this.nombre = nombre;
} }
// Otros métodos de la clase...
double sumar(double a, double b) { }
return a + b;
} Uso de Polimorfismo:
} Teoría: El polimorfismo se refiere a la capacidad de un objeto de
tomar muchas formas. En Java, se logra mediante la sobrecarga y la
Overriding (Sobreescritura): sobreescritura.
Teoría: Overriding se refiere a la capacidad de una subclase de Lo más importante: Permite tratar a objetos de diferentes clases de
proporcionar una implementación específica de un método que ya manera uniforme a través de una interfaz común.
está definido en su superclase. Ejemplo:
Lo más importante: El método en la subclase debe tener la misma class Figura {
firma que el método en la superclase. void dibujar() {
Ejemplo: System.out.println("Dibujando una figura");
class Animal { }
void sonido() { }
System.out.println("Animal hace un sonido"); class Circulo extends Figura {
} @Override
} void dibujar() {
System.out.println("Dibujando un círculo");
class Perro extends Animal { }
@Override }
void sonido() {
class Cuadrado extends Figura { abiertas para la extensión pero cerradas para la
@Override modificación. Ejemplo en Spring Boot:
void dibujar() { En una aplicación de gestión de productos, se pueden agregar
System.out.println("Dibujando un cuadrado"); nuevos tipos de productos sin modificar el código existente. Por
} ejemplo, podemos tener una interfaz ProductService y
} diferentes implementaciones para manejar diferentes tipos de
productos.
Uso de Abstracción: @Service
Teoría: La abstracción es un principio de diseño que se centra en los public interface ProductService {
aspectos esenciales de un objeto y oculta los detalles innecesarios. void addProduct(Product product);
Lo más importante: Permite modelar entidades del mundo real de }
manera más precisa y simplifica la complejidad del sistema.
Ejemplo: @Service
abstract class Animal { public class ElectronicProductService implements
abstract void sonido(); // Método abstracto que define el sonido ProductService {
del animal @Override
} public void addProduct(Product product) {
class Perro extends Animal { // Lógica para agregar un producto electrónico
@Override }
void sonido() { }
System.out.println("El perro ladra");
} @Service
} public class ClothingProductService implements ProductService
{
Uso de Generics <T>: @Override
Teoría: Los generics en Java permiten crear clases, interfaces y public void addProduct(Product product) {
métodos que funcionan con tipos específicos (parametrizados) que // Lógica para agregar un producto de ropa
se determinan en el momento de la compilación. }
Lo más importante: Proporcionan seguridad de tipo en tiempo de }
compilación y evitan la necesidad de realizar casting. Importancia: Facilita la extensión y mantenimiento del sistema
Ejemplo: sin modificar el código existente.
class Contenedor<T> { Beneficios:
Mejora la modularidad y reutilización del código.
Principios SOLID: Reduce el riesgo de introducir errores en el código existente.
SRP (Principio de responsabilidad única): Una clase debe tener
una única razón para cambiar. Es decir, cada clase debe tener una LSP (Principio de sustitución de Liskov): Los objetos de un
sola responsabilidad. Ejemplo en Spring Boot: programa deben ser reemplazables por instancias de sus
Supongamos que tenemos una clase UserService que se encarga subtipos sin afectar la corrección del programa.
de gestionar la lógica de negocio relacionada con los usuarios,
como la autenticación, el registro y la actualización de datos. ISP (Principio de segregación de la interfaz): Los clientes no deben
@Service verse obligados a depender de interfaces que no utilizan.
public class UserService {
@Autowired DIP (Principio de inversión de dependencias): Los módulos de alto
private UserRepository userRepository; nivel no deben depender de módulos de bajo nivel. Ambos deben
public void registerUser(User user) { depender de abstracciones. Se basa en el uso de interfaces o
// Lógica para registrar un usuario clases abstractas para definir contratos entre componentes del
} sistema.
public void updateUser(User user) {
// Lógica para actualizar un usuario Patrón de Diseño Fábrica/Factory:
} Teoría: El patrón de diseño Fábrica proporciona una interfaz para
// Otros métodos relacionados con la gestión de usuarios crear objetos de un tipo, pero permite a las subclases alterar el tipo
} de objetos que se crearán.
Importancia: Al tener una sola responsabilidad, la clase Lo más importante: Separación de la creación de objetos de su uso.
UserService es más fácil de entender, mantener y probar. Ejemplo: Una interfaz Shape con implementaciones Circle y Square.
Beneficios: La fábrica ShapeFactory devuelve instancias de estas clases según el
Facilita la evolución y mantenimiento del código. tipo solicitado.
Mejora la cohesión y modularidad del sistema. ¿Qué es el Patron Factory? - Arquitectura Java

OCP (Principio de abierto/cerrado): Las entidades de


software (clases, módulos, funciones, etc.) deben estar
Patrón de Diseño Fachada/Facade: Lo más importante: Flexibilidad en la elección del algoritmo en
Teoría: Proporciona una interfaz unificada para un conjunto de tiempo de ejecución.
interfaces en un subsistema. Simplifica y oculta la complejidad de un Ejemplo: Un sistema de pago en línea que puede tener diferentes
sistema más grande. estrategias de pago como tarjeta de crédito, PayPal, etc. Cada
Lo más importante: Abstracción de la complejidad del sistema. estrategia implementa un algoritmo de procesamiento de pagos.
Ejemplo: Un servicio de correo electrónico puede tener métodos
como enviarCorreoElectrónico y adjuntarArchivo, que internamente DEFAULT METHOD IN INTERFACE:
manejan la complejidad de enviar un correo electrónico. Teoría:
Patrón de diseño Facade en Java - Home (gustavopeiretti.com) Los métodos predeterminados en interfaces Java permiten agregar
nuevas funcionalidades a las interfaces sin romper la compatibilidad
Patrón de Diseño Singleton: con las clases que las implementan. Estos métodos tienen una
Teoría: Garantiza que una clase solo tenga una instancia y implementación predeterminada en la interfaz y pueden ser
proporciona un punto de acceso global a esa instancia. sobrescritos por las clases que la implementan si lo desean.
Lo más importante: Restricción de instanciación a una sola instancia. Lo más importante:
Ejemplo: Una clase Logger que controla el registro de eventos en una Los métodos predeterminados en interfaces permiten la extensión
aplicación. de interfaces sin romper la compatibilidad con las implementaciones
Singleton – Patrones de diseño en JAVA existentes.
(programandoenjava.com) Son útiles para proporcionar una implementación común para una
operación que se espera que esté presente en todas las
Patrón de Diseño MVC (Modelo-Vista-Controlador): implementaciones de la interfaz.
Teoría: Divide una aplicación en tres componentes: Modelo (datos y Ejemplo:
lógica de negocio), Vista (presentación de datos al usuario) y interface MyInterface {
Controlador (manejo de la interacción del usuario). default void defaultMethod() {
Lo más importante: Separación de responsabilidades para facilitar la System.out.println("Default method implementation");
modificación y el mantenimiento del código. }
Ejemplo: Un sistema de gestión de tareas donde el Modelo maneja }
las tareas, el Controlador maneja las acciones del usuario y la Vista
muestra las tareas en una interfaz de usuario. class MyClass implements MyInterface {
// No es necesario sobrescribir el método defaultMethod
Patrón de Diseño DI (Inyección de Dependencias): }
Teoría: Permite la creación de objetos con sus dependencias
proporcionadas externamente. Mejora la modularidad y facilita las public class Main {
pruebas unitarias. public static void main(String[] args) {
Lo más importante: Inversión del control de la creación de objetos. MyClass obj = new MyClass();
Ejemplo: Un objeto UserService que necesita un objeto obj.defaultMethod(); // Output: Default method
UserRepository. En lugar de crear directamente UserRepository, se implementation
pasa como dependencia al constructor de UserService. }
}
Patrón de Diseño DAO (Objeto de Acceso a Datos):
Teoría: Abstrae y encapsula todos los accesos a la base de datos. STATIC METHOD IN INTERFACE:
Proporciona una interfaz para interactuar con la base de datos sin Teoría:
exponer su complejidad. Los métodos estáticos en interfaces Java son métodos que pueden
Lo más importante: Separación de la lógica de negocio de la lógica ser llamados sin la necesidad de crear una instancia de la interfaz.
de acceso a datos. Estos métodos se pueden utilizar para proporcionar utilidades o
Ejemplo: Una interfaz UserDAO con métodos como getUserByID, funciones relacionadas con la interfaz.
getAllUsers, etc., que ocultan la complejidad de la interacción con la Lo más importante:
base de datos. Los métodos estáticos en interfaces se pueden llamar directamente
desde la interfaz sin necesidad de una instancia.
Patrón de Diseño Repository: Son útiles para proporcionar funcionalidades comunes relacionadas
Teoría: Define un objeto que encapsula la lógica necesaria para con la interfaz.
recuperar datos y los pone a disposición de la capa de negocio. Ejemplo:
Lo más importante: Abstracción de la fuente de datos. interface MyInterface {
Ejemplo: Un repositorio UserRepository que proporciona métodos static void staticMethod() {
para interactuar con la base de datos de usuarios. System.out.println("Static method in interface");
}
Patrón de Diseño Strategy: }
Teoría: Define una familia de algoritmos, los encapsula y los hace
intercambiables. Permite que el algoritmo varíe public class Main {
independientemente de los clientes que lo utilizan. public static void main(String[] args) {
MyInterface.staticMethod(); // Output: Static method in PREDICATE:
interface Teoría:
} Predicate es una interfaz funcional que representa un predicado
} (una función booleana de un solo argumento). Se utiliza para realizar
operaciones de filtrado en colecciones de datos.
FUNCTIONAL INTERFACE:
Teoría:
Una interfaz funcional en Java es una interfaz que tiene exactamente Lo más importante:
un método abstracto. Estas interfaces se pueden utilizar como tipos Predicate tiene un método test que toma un argumento y devuelve
para referencias de métodos lambda o expresiones lambda. un valor booleano.
Lo más importante: Se utiliza comúnmente con las operaciones filter, anyMatch,
Las interfaces funcionales son esenciales para el uso de expresiones allMatch, etc., en la API de Streams.
lambda en Java. Ejemplo:
Pueden tener cualquier número de métodos predeterminados, import java.util.function.Predicate;
estáticos o abstractos, pero solo uno de ellos debe ser abstracto.
Ejemplo: public class Main {
@FunctionalInterface public static void main(String[] args) {
interface MyFunctionalInterface { Predicate<Integer> isPositive = num -> num > 0;
void myMethod(); System.out.println(isPositive.test(5)); // Output: true
} System.out.println(isPositive.test(-5)); // Output: false
}
public class Main { }
public static void main(String[] args) { FUNCTION:
MyFunctionalInterface obj = () -> System.out.println("Executing Teoría:
myMethod"); Function es una interfaz funcional que representa una función que
obj.myMethod(); // Output: Executing myMethod toma un argumento y produce un resultado. Es similar a una función
} matemática.
} Lo más importante:
LAMBDA EXPRESSIONS: Function tiene un método apply que toma un argumento y devuelve
Teoría: Las expresiones lambda en Java son funciones anónimas que un resultado.
permiten pasar comportamientos como argumentos de métodos o Se utiliza para transformar un objeto de un tipo en otro tipo, realizar
expresar instancias de interfaces funcionales de manera más cálculos, etc.
concisa. Ejemplo:
Lo más importante: import java.util.function.Function;
• Las expresiones lambda permiten escribir código de manera
más concisa y clara, especialmente cuando se trata de public class Main {
interfaces funcionales. public static void main(String[] args) {
• Son útiles para pasar comportamientos como argumentos Function<Integer, Integer> square = num -> num * num;
de métodos en una forma más compacta que las clases System.out.println(square.apply(5)); // Output: 25
anónimas. }
Ejemplo: }
interface MyInterface {
void myMethod(int num); CONSUMER:
} Teoría:
Consumer es una interfaz funcional que representa una operación
public class Main { que toma un argumento y no devuelve ningún resultado. Se utiliza
public static void main(String[] args) { para realizar acciones sobre el argumento sin devolver ningún valor.
MyInterface obj = (num) -> System.out.println("Number: " + Lo más importante:
num); Consumer tiene un método accept que toma un argumento y realiza
obj.myMethod(10); // Output: Number: 10 alguna operación sobre él.
} Se utiliza comúnmente en operaciones de procesamiento de datos,
} como imprimir valores, guardar en una base de datos, etc.
Ejemplo:
Referencia a métodos en programación funcional import java.util.function.Consumer;
Una lambda sigue siendo una función es decir un método por lo
tanto en programación funcional podemos sustituir una función public class Main {
lambda con un método tradicional por medio de la referencia a public static void main(String[] args) {
métodos usando el operador :: Consumer<String> printMessage = message ->
System.out.println("Message: " + message);
printMessage.accept("Hello, world!"); // Output: Message: }
Hello, world! STREAMS API:
} Teoría:
} Stream es//lista que una secuencia de elementos que admite
diferentes operaciones para realizar cálculos en esos elementos. La
API de Streams proporciona un conjunto de operaciones de alto nivel
para trabajar con colecciones de manera funcional.
La clase Stream es una especie de lista que puede tener elementos y
public static void consumerDemo() { se puede iterar la diferencia entre colecciones y Stream es que
Student student = new Student ("Juan Consumer", Stream es autoiterable.
9); Paralelizar un Stream en Java es aprovechar la capacidad de
Consumer<Student> studentConsumer = ejecución paralela para procesar los elementos de manera más
oneStudent -> System.out.println(oneStudent.toString()); eficiente. Cuando un Stream se ejecuta en paralelo, los elementos se
studentConsumer.accept(student); procesan simultáneamente en múltiples subprocesos, lo que puede
} mejorar el rendimiento en sistemas con múltiples núcleos de CPU.
Lo más importante:
Permite operaciones de filtrado, mapeo, reducción, ordenación, etc.,
SUPPLIER:
de manera declarativa.
Teoría:
Los streams pueden ser secuenciales o paralelos, lo que permite el
Supplier es una interfaz funcional que representa una función que no
procesamiento eficiente de grandes conjuntos de datos.
toma ningún argumento pero produce un resultado. Se utiliza para
Ejemplo:
generar o suministrar valores.
import java.util.Arrays;
Lo más importante:
import java.util.List;
Supplier tiene un método get que no toma ningún argumento y
devuelve un resultado.
public class Main {
Se utiliza para inicializar valores perezosamente, generar valores de
public static void main(String[] args) {
forma dinámica, etc.
List<String> words = Arrays.asList("hello", "world", "java",
Ejemplo:
"programming");
import java.util.function.Supplier;
// Filtrar palabras que tienen más de 4 caracteres y luego
public class Main {
imprimir
public static void main(String[] args) {
words.stream()
Supplier<String> getHello = () -> "Hello, world!";
.filter(word -> word.length() > 4)
System.out.println(getHello.get()); // Output: Hello, world!
.forEach(System.out::println);
}
}
}
}

METHOD REFERENCES:
Teoría:
List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);
Las referencias a métodos son una forma de referirse a un método
existente por su nombre. Proporcionan una forma concisa de
// Secuencial
expresar expresiones lambda que invocan un único método
numeros.stream().forEach(System.out::println);
existente.
Lo más importante:
// Paralelo
Se pueden utilizar para referenciar métodos estáticos, métodos de
numeros.parallelStream().forEach(System.out::println);
instancia y constructores.
Proporcionan un código más limpio y legible al reutilizar métodos
En Java, el método findAny() es parte de la interfaz Stream. Este
existentes.
método se utiliza para encontrar cualquier elemento dentro de un
Ejemplo:
flujo (stream) de elementos. La especificación de Java no garantiza
import java.util.function.Function;
qué elemento será devuelto; puede ser cualquier elemento del flujo,
dependiendo de la implementación y del estado interno del flujo.
public class Main {
public static String convertToUpper(String input) {
return input.toUpperCase();
CLASE OPTIONAL:
}
Teoría:
Optional es una clase introducida en Java 8 para representar un
public static void main(String[] args) {
contenedor que puede o no contener un valor. Se utiliza para evitar
Function<String, String> toUpperCase = Main::convertToUpper;
las NullPointerException y proporcionar una forma más clara de
System.out.println(toUpperCase.apply("hello")); // Output:
trabajar con valores potencialmente nulos.
HELLO
}
Optional nos proporciona otra manera de lidiar con este error
evitándonos cachar las excepciones (lo cual ahorra costo en
rendimiento) y en lugar de eso controlar la ausencia de valor
permitiéndonos si así fuera el caso elegir un valor alternativo o
simplemente realizar otra acción.
Lo más importante:
Se puede utilizar para evitar las comprobaciones de null.
Proporciona métodos como isPresent, orElse, orElseThrow para
trabajar de manera segura con valores opcionales.
Ejemplo:

import java.util.Optional;

public class Main {


public static void main(String[] args) {
String name = null;
Optional<String> optionalName = Optional.ofNullable(name);

// Si el nombre está presente, lo imprime; de lo contrario,


imprime "Name is not present"
optionalName.ifPresentOrElse(System.out::println, () ->
System.out.println("Name is not present"));
}
}
FLATMAP
La programación funcional ofrece un alto grado de abstracción, ya
Flatmap es la combinación de las operaciones Map y Flat lo que
que está basada en el concepto matemático y el principio de función.
significa que primero hace una operación a sus elementos y luego la
Cuando se aplica de forma correcta, este tipo de programación crea
aplana. Para entenderlo mejor vamos al siguiente ejemplo .
un código muy preciso. A partir de tantas unidades pequeñas,
reutilizables y altamente especializadas como sea posible, se crea un
programa para la solución de una tarea sustancialmente mayor.
Recuerda que la programación funcional se trata de ocuparnos mas
en que se va a realizar mas que en como realizarlo.
SPRING SECURITY
FlatMap es una función que recibe una entrada y devuelve varias
JSON WEB TOKENS
salidas para esa entrada . Esa es la diferencia con Map que tiene una
El usuario inicia sesión en lgin, envia por POST el username y
entrada y devuelve una única salida.
password y esto llega al servidor.
El servidor mediante Spring Security con un filtro que puede llamarse
por ejemplo jwtAuthenticationFilter, va a interceptar esta ruta url y
el post. Va a validar las credeniales en base de datos.
Autenticado? No : error credenciales: 401 no autorizado
Si Crea un Jwt con una llave Secreta y claims
Retorna el token jwt al cliente: 200 ok
Y asi podrá navegar a los recursos protegidos con ese token
generado.

HTTPS

ACCEDIENDO A UN RECURSO PROTEGIDO


El usuario accede a un recurso Request HTTP y envía el Jwt en las
headers Http: Authorization
Se verifica la firma del token en el spring security, otro filtro.
JwtValidationFilter, que no haya expirado que no haya sido alterado
Es válido el token? No: acceso denegado 403 Forbidden
Si: se obtiene los datos del usuario desde los claims del token.
Luego se Autentica, se verifica los permisos y roles.
Tiene permisos? NO: acceso denegado 403 Forbidden
SI: Accede al servicio API REST, retorna respuesta al cliente,200 ok

Son cancelables
Pueden ser finito o infinito.

Patrón SAGA
El Patrón SAGA aplicado a microservicios nos ayuda a garantizar la integridad
en transaccione distribuidas repartidas entre microservicios.

El Patrón SAGA divide esta transacción distribuida en transacciones locales.

El Patrón SAGA puede aplicarse de 2 formas (subpatrones)


PROGRAMACIÓN REACTIVA WEBFLUX
Paradigma de programación que se centra en manejar flujos de Patrón SAGA mediante coreografía
datos asincrónicos y eventos en tiempo real. Patrón SAGA mediante orquestación
Combina las mejores ideas del patrón Observer, Iterator y la
programación funcional. Patrón SAGA mediante coreografía
Subject, Publisher o observable: Eventos o cambios, flujo de datos
continuo. En este caso cada transacción local publica un evento cuando el
trabajo se ha concluido. La siguiente transacción local recibe el
evento y hace su tarea. El trabajo finaliza cuando todas las
transacciones locales se concluyen:

Cada servicio debe conocer e implementar cómo responder a ciertos


estados.

Las ventajas de este método es que es fácil de implementar y los


endpoints están poco acoplados, por el contrario puede volverse
complicado cuando crecen el número de transacciones y pueden
crearse dependencias cíclicas entre servicios.

Patrón SAGA mediante orquestación

Para implementar este patrón es necesario un proceso o servicio


encargado de la coordinación (el llamada Orquestador o Manager)
de todo el proceso.

Si alguna transacción falla el orquestador es el responsable del


rollback de las transacciones previas ejecutadas.
Este método tiene la ventaja de ser más sencillo de entender y
mantener y además su complejidad no crece cuando crece el número
de transacciones. Por otro lado la lógica de negocio está
implementada en el orquestador y la disponibilidad y escalabilidad
depende de este.

Por suerte existen bastantes frameworks y librerías que nos ayudan


a implementar este patrón, como:

Axon que es un framework y server creado específicamente para


manejar microservicios

Tipos de CQRS
CQRS Básico: En su forma más simple, CQRS implica simplemente
separar los modelos de lectura y escritura en tu aplicación. Las
operaciones de lectura consultan un modelo que está optimizado
para consultas rápidas y eficientes, mientras que las operaciones de
escritura actualizan un modelo que está optimizado para la
O Motores BPM como Camunda que por su ligereza son validación y la consistencia de las transacciones.
perfectamente válidos para hacer esta orquestación, podéis verlo en CQRS con Event Sourcing: En este enfoque, además de separar los
este ejemplo: modelos de lectura y escritura, también se utiliza el patrón de Event
Sourcing. Con Event Sourcing, en lugar de almacenar el estado actual
de tus datos, almacenas una secuencia de eventos que representan
cambios en tus datos a lo largo del tiempo. Esto puede hacer que sea
más fácil mantener la consistencia entre tus modelos de lectura y
escritura, y también puede proporcionar beneficios adicionales,
como la capacidad de "rebobinar" tus datos a un estado anterior.
Ventajas
Optimización independiente: Al separar las operaciones de lectura y
escritura, puedes optimizar cada una de ellas de manera
independiente. Por ejemplo, puedes optimizar el modelo de lectura
para consultas rápidas y eficientes, mientras que el modelo de
escritura puede estar optimizado para la validación y la consistencia
de las transacciones.
Escalabilidad: CQRS puede ayudar a mejorar la escalabilidad de tu
PATRON CQRS aplicación. Si tienes una carga de trabajo con muchas más lecturas
que escrituras (o viceversa), puedes escalar los modelos de lectura y
CQRS significa Command Query Responsibility Segregation escritura de forma independiente para satisfacer tus necesidades.
(Segregación de Responsabilidades de Comandos y Consultas). Es un Flexibilidad: CQRS te permite cambiar el modelo de lectura y
patrón de diseño de software que separa las operaciones de lectura escritura de forma independiente. Esto puede ser útil si necesitas
(consultas) y escritura (comandos) en diferentes modelos. cambiar la forma en que manejas las consultas o las actualizaciones,
En un sistema tradicional, utilizamos el mismo modelo de dominio pero no quieres afectar la otra parte de tu aplicación.
para leer y actualizar la base de datos. Pero en el patrón CQRS, Seguridad: Puedes aplicar diferentes políticas de seguridad a las
separamos estos dos aspectos en diferentes modelos. Esto permite operaciones de lectura y escritura. Por ejemplo, puedes permitir a
optimizar cada modelo para la tarea que realiza, lo que puede ciertos usuarios realizar consultas pero no actualizaciones.
resultar en un rendimiento mejorado, una mayor escalabilidad y una Complejidad reducida: Al dividir el sistema en dos partes más
mayor flexibilidad. pequeñas y más manejables, puedes reducir la complejidad de cada
Por ejemplo, el modelo de escritura puede estar optimizado para la parte.
validación de reglas de negocio y la consistencia de transacciones, Desventajas
mientras que el modelo de lectura puede estar optimizado para la Complejidad adicional: CQRS puede añadir una capa de complejidad
eficiencia de las consultas y la presentación de datos. a tu aplicación. Tienes que mantener dos modelos diferentes y
asegurarte de que estén sincronizados. Esto puede hacer que el
Es importante tener en cuenta que CQRS es un patrón avanzado y código sea más difícil de entender y mantener.
puede añadir complejidad a la aplicación. Por lo tanto, debe Consistencia eventual: Como las operaciones de lectura y escritura
utilizarse cuando el beneficio que aporta supera el costo de esa están separadas, puedes terminar con una consistencia eventual,
complejidad adicional. donde los datos leídos pueden no reflejar las últimas escrituras
inmediatamente. Esto puede ser confuso para los usuarios si no se Contenedorización: Docker utiliza contenedores para empaquetar y
maneja correctamente. distribuir aplicaciones junto con sus dependencias y bibliotecas, pero
Dificultad de prueba: Probar un sistema CQRS puede ser más difícil comparten el mismo kernel del sistema operativo anfitrión.
debido a la necesidad de coordinar y verificar el comportamiento
entre los modelos de lectura y escritura. Sistema Operativo Base Compartido: Todos los contenedores Docker
Costo de desarrollo y mantenimiento: Implementar CQRS puede comparten el mismo kernel del sistema operativo anfitrión, lo que
requerir más tiempo y esfuerzo que un enfoque tradicional. También reduce la sobrecarga en comparación con las máquinas virtuales.
puede aumentar los costos de mantenimiento a largo plazo.
No es adecuado para todas las aplicaciones: CQRS puede ser útil en Uso de Recursos: Los contenedores son más ligeros en términos de
aplicaciones con requisitos complejos de dominio o donde las recursos en comparación con las máquinas virtuales, ya que no
operaciones de lectura y escritura tienen diferentes necesidades de necesitan cargar un sistema operativo completo para cada
escalabilidad. Sin embargo, para aplicaciones más simples, puede ser contenedor.
excesivo y no proporcionar beneficios significativos.
Caso Práctico - API Customers Tiempo de Arranque: Los contenedores Docker son más rápidos de
Problema: arrancar en comparación con las máquinas virtuales, ya que no
Dependencia de consumidores (30) para hacer las pruebas de necesitan cargar un sistema operativo completo.
cambio y regresión, son bastantes y el tiempo que se toman en
probar es de 1 mes aproximadamente. Aislamiento: Los contenedores Docker proporcionan un nivel de
Solución: aislamiento más bajo en comparación con las máquinas virtuales, ya
Implementar el CQRS Básico. que comparten el mismo kernel del sistema operativo anfitrión,
Separar el microservicio customers en 2: aunque siguen ofreciendo un alto grado de aislamiento de recursos.
customers-quey: Agrupa los endpoints de consulta (29
consumidores). En resumen, Docker se centra en la contenedorización de
customers-command: Agrupa los endpoints que persisten en la aplicaciones, lo que permite un despliegue rápido y portátil de
BBDD, actualización y creación (10 consumidores). aplicaciones junto con sus dependencias, mientras que las máquinas
virtuales proporcionan un aislamiento más completo y la capacidad
de ejecutar múltiples sistemas operativos completos en un mismo
hardware físico.

DOCKER PARA EL DESPLIEGUE DE APLICACIONES


Docker es un software para la gestión de contenedores.

Una forma de empaquetar software en un formato que incluye todo


lo necesario para hacerlo funcionar y se ejecuta aislado del resto de
la máquina
• Tiene dos conceptos muy relacionados:
– La imagen, que es un paquete ejecutable que incluye todo lo
necesario para ejecutar un software
– El contenedor, que es la instancia en ejecución de una imagen, es
decir, lo que la imagen

¿Y esto no es lo mismo que una máquina virtual?


MICROSERVICIOS
Necesitamos
• Registry: Registrar y descubrir los microservicios
• Config: Configuración centralizada de los microservicios
• Load Balancer: para realizar un balanceo de carga de los
microservicios
• Circuit Breaker: Para Manejar la tolerancia a fallos de los
microservicios
• Api Gate Way: Un api gateway para tener un único acceso
a los microservicios
• Log Center: para guardar en un punto centralizado los logs

¿Qué son los microservicios y cuáles son sus ventajas?

Los microservicios son una arquitectura de desarrollo de software


que estructura una aplicación como un conjunto de pequeños
servicios independientes, cada uno ejecutándose en su propio
proceso y comunicándose mediante mecanismos ligeros, como
HTTP o mensajería. Algunas ventajas son: Las transacciones distribuidas pueden ser complicadas en
Escalabilidad independiente. microservicios debido a la naturaleza distribuida de la arquitectura.
Facilitan la implementación y el despliegue continuos. Se pueden utilizar técnicas como Sagas, donde cada servicio ejecuta
Mejora de la resiliencia. una parte de la transacción y se comunica con otros servicios para
Facilitan la adopción de tecnologías y lenguajes específicos para coordinar la transacción completa. También se pueden usar
cada servicio. patrones como el Compensating Transaction o el Event Sourcing
para manejar situaciones donde una transacción debe deshacerse o
¿Cuál es la diferencia entre arquitectura monolítica y arquitectura revertirse.
basada en microservicios?
¿Qué es la escalabilidad horizontal y vertical y cuándo se utilizaría
En una arquitectura monolítica, toda la aplicación se desarrolla, cada una en microservicios?
despliega y escala como una única unidad. En cambio, en una
arquitectura basada en microservicios, la aplicación se descompone La escalabilidad horizontal implica agregar más instancias de un
en pequeños servicios independientes que se pueden desarrollar, servicio para manejar una carga de trabajo creciente, mientras que
desplegar y escalar de forma independiente. la escalabilidad vertical implica mejorar los recursos de una
instancia existente (por ejemplo, agregar más CPU o memoria). En
microservicios, la escalabilidad horizontal suele ser preferida ya que
permite escalar cada servicio de forma independiente y
proporciona una mayor flexibilidad.

JUNIT

Gateway: el cual sirve como api Gateway como una única puerta de
enlace para acceder
Ribbon: Permite manejar el balanceo de carga de los microservicios
Eureka Server: Permite registrar los microservicios y el
descubrimiento
Hystrix: permite implementar el patrón circuit breaker para la
tolerancia a fallos
Spring Config: Sirve para implementar una configuración
centralizada de los microservicios.
Logging: Log centralizado

¿Cuál es la diferencia entre una API Gateway y un Service Mesh?

Una API Gateway es un punto de entrada único para todas las


solicitudes de clientes hacia los microservicios. Proporciona
funciones como enrutamiento, autenticación, autorización y
equilibrio de carga. Un Service Mesh es una capa de infraestructura
dedicada a facilitar la comunicación, el monitoreo y la
administración entre los microservicios. Se ocupa de tareas como la
gestión del tráfico, la seguridad y el descubrimiento de servicios.

¿Qué es la autenticación y autorización en microservicios?

La autenticación es el proceso de verificar la identidad de un


usuario o servicio, mientras que la autorización es el proceso de
determinar si un usuario o servicio tiene permiso para realizar una
determinada acción. En microservicios, la autenticación y la
autorización se pueden gestionar de manera centralizada (por
ejemplo, utilizando OAuth o JWT) o distribuida (cada servicio se
encarga de su propia autenticación y autorización).

¿Cómo se manejan las transacciones en microservicios?

También podría gustarte