tema nº 8: control de ejecuciÓn y mantenimiento de sesiÓn

24
Desarrollo de Aplicaciones Web con J2EE Jaaaaaaaaaaaa Ing. Pablo Cesar Ttito C. [email protected] Desarrollo de Aplicaciones Web con J2EE

Upload: anyeni-garay

Post on 13-Jun-2015

84 views

Category:

Education


1 download

TRANSCRIPT

Page 1: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Jaaaaaaaaaaaa

Ing. Pablo Cesar Ttito [email protected]

Desarrollo de Aplicaciones Web con J2EE

Page 2: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Control de ejecución

- true y false- if - else- Iteración - do - while - for - El operador coma- Sintaxis foreach- return- break y continue- La despreciada instrucción "goto"- switch

Al igual que las criaturas sensibles, un programa debe manipular su mundo y tomar decisiones durante la ejecución. En Java, las decisiones se toman mediante las instrucciones de control de ejecución.

En este tema vamos a ver las instrucciones de control de ejecución.

TRUE Y FALSETodas las instrucciones condicionales utilizan la veracidad o la falsedad de una expresión condicional para seleccionar una ruta de ejecución. Es decir, se compararán una serie de valores mediante los operadores relacionales y dependiendo del resultado (true o false) la ejecución irá por un camino u otro.

IF - ELSEEsta instrucción es la forma más básica de controlar el flujo de un programa. La opción else es opcional, tendríamos:

if (expresión - booleana)   instrucción

o

if (expresión - booleana)   instrucción1else   instrucción2

Ing. Pablo Cesar Ttito [email protected]

Page 3: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

La expresión - booleana producirá un valor true o false. En el primer caso si es true, pasará a ejecutar la instrucción o instrucciones (si son varias, encerradas entre llaves {}) en caso contrario no hará nada. En el segundo caso si se cumple la expresión - booleana ejecutará la instrucción o instrucciones instrucción1, si no se cumple se ejecutará la instrucción o instrucciones instrucción2. Vamos a ver un ejemplo:

//: control/IfElse.javaimport static net.mindview.util.Print.*;

public class IfElse {  static int result = 0;  static void test(int testval, int target) {    if(testval > target)      result = +1;    else if(testval < target)      result = -1;    else      result = 0; // Match  }  public static void main(String[] args) {    test(10, 5);    print(result);    test(5, 10);    print(result);    test(5, 5);    print(result);  }} /* Output:1-10*//:~

En el método test() podemos ver una instrucción "else if" ya que dentro de un if puede haber varias comparaciones, el "else" final se ejecutaría en caso de que no se cumplieran ninguna de las condiciones anteriores.

ITERACIÓNPara los bucles de ejecución tenemos while, do - while y for, también llamadas instrucciones de iteración. Un bucle while sería:

while (expresión - booleana)   instrucción

La expresión - booleana se comprueba cuando la ejecución llega al bucle, en caso de que se cumpla, se ejecuta la o las instrucciones, cada vez que se ejecutan estas instrucciones se vuelve a comprobar si se sigue cumpliendo la expresión - booleana. Se ejecutan instrucciones mientras se cumpla la expresión - booleana. Vamos a ver un ejemplo, generamos números aleatorios hasta que se cumpla una determinada condición.

Ing. Pablo Cesar Ttito [email protected]

Page 4: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

//: control/WhileTest.java// Demonstrates the while loop.

public class WhileTest {  static boolean condition() {    boolean result = Math.random() < 0.99;    System.out.print(result + ", ");    return result;  }  public static void main(String[] args) {    while(condition())      System.out.println("Inside 'while'");    System.out.println("Exited 'while'");  }} /* (Execute to see output) *///:~

En el método condition() el método random() genera un valor double comprendido entre 0 y 1 (incluye 0, pero no 1). La variable result es el resultado de una operación de comparación < que genera un boolean. En main tenemos un bucle while que se va a repetir mientras la variable result del método condition() sea true. Si no lo véis claro con este ejercicio lo he modificado un poco para que veáis cuando se deja de cumplir que Math.random()<0.99:

//: control/WhileTest2.java// Demonstrates the while loop.

public class WhileTest2 {static boolean condition() {boolean result=true;double centinela=Math.random();System.out.println("Valor aleatorio: "+centinela);if (centinela<0.99)result=true;elseresult=false;System.out.print(result+", ");return result;}public static void main(String[] args) {while(condition())System.out.println("Inside 'while'");System.out.println("Exited 'while'");}} /* (Execute to see output) *///:~

Ing. Pablo Cesar Ttito [email protected]

Page 5: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

DO - WHILEEl bucle do - while tiene la forma:

do   instrucciónwhile (expresión - booleana)

Este bucle se ejecuta al menos una vez a diferencia del bucle while. La instrucción o instrucciones que están entre do y while se ejecutan una vez y posteriormente se evalúa la expresión - booleana, si es true se vuelven a ejecutar la instrucción o instrucciones y si es false salimos del bucle.

FOREs quizá el bucle más utilizado. Tiene la forma:

for (inicialización; expresión - booleana; paso)   Instrucción

Tenemos una inicialización de una variable que utilizaremos como centinela o contador. En la expresión - booleana comprobamos mediante una expresión condicional si esa variable ha alcanzado un valor determinado y el paso es el aumento o disminución que hacemos de la variable inicial. Cualquiera de las expresiones inicialización, expresión - booleana o paso puede estar vacía. La expresión - booleana se comprueba antes de cada iteración y la instrucción o instrucciones se ejecutarán mientras ésta sea true, cuando sea false saldremos del bucle. Cada vez que se ejecutan las instrucciones la variable de paso aumenta o disminuye. El bucle for se repite mientras se cumpla la expresión - booleana.Vamos a ver un ejemplo:

//: control/ListCharacters.java// Demonstrates "for" loop by listing// all the lowercase ASCII letters.

public class ListCharacters {  public static void main(String[] args) {    for(char c = 0; c < 128; c++)      if(Character.isLowerCase(c))        System.out.println("value: " + (int)c +          " character: " + c);  }} /* Output:value: 97 character: avalue: 98 character: bvalue: 99 character: cvalue: 100 character: dvalue: 101 character: evalue: 102 character: fvalue: 103 character: gvalue: 104 character: hvalue: 105 character: ivalue: 106 character: j...*///:~

Ing. Pablo Cesar Ttito [email protected]

Page 6: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Vemos que hay un bucle for en el que se inicializa la variable c, cuyo ámbito se restringe al bucle for. La expresión - booleana que se comprueba es c<128 y el paso es c++, la variable c aumenta en uno en cada iteración. Este bucle se repetirá 128 veces.Se utiliza la clase envoltorio java.lang.Character, que permite tratar una variable char como un objeto. El método Character.isLowerCase(c) comprueba si el carácter c es una letra minúscula.Mientras que en C las variables se definen al principio de un bloque para reservar la memoria necesaria, en Java se puede definir una variable en el lugar en que se necesite.

EL OPERADOR COMAEl operador coma sólo se utiliza en la expresión de control de un bucle for. Tanto en la parte de la inicialización como en la parte correspondiente al paso de la expresión de control, se pueden incluir instrucciones separadas por comas que serán evaluadas secuencialmente. Podemos definir dentro de la instrucción for múltiples variables, todas deben ser del mismo tipo:

//: control/CommaOperator.java

public class CommaOperator {  public static void main(String[] args) {    for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {      System.out.println("i = " + i + " j = " + j);    }  }} /* Output:i = 1 j = 11i = 2 j = 4i = 3 j = 6i = 4 j = 8*///:~

El int de la instrucción for es tanto para i como para j. La parte de la inicialización puede tener cualquier número de definiciones de un mismo tipo. Definir variables en una expresión de control está limitada a los bucles for. Tanto en la inicialización como en la parte de paso las instrucciones se evalúan secuencialmente.

SINTAXIS FOREACHSe trata de una sintaxis for nueva para utilizarla con matrices y contenedores (lo veremos más adelante). Con la sintaxis foreach (para todos) no es necesario crear una variable int para efectuar un recuento a través de una secuencia de elementos, el bucle for genera cada elemento automáticamente.En el siguiente ejemplo tenemos una matriz de float y queremos seleccionar cada elemento de la matriz:

//: control/ForEachFloat.javaimport java.util.*;

public class ForEachFloat {  public static void main(String[] args) {    Random rand = new Random(47);    float f[] = new float[10];    for(int i = 0; i < 10; i++)      f[i] = rand.nextFloat();    for(float x : f)      System.out.println(x);  }} /* Output:0.72711575

Ing. Pablo Cesar Ttito [email protected]

Page 7: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

0.399826350.53094540.05341220.160206560.577997570.188478650.41701370.516602040.73734957*///:~

La matriz se rellena con un antiguo bucle for. La sintaxis foreach es de la forma:

for (float x:f)

Mediante esta expresión definimos una variable x de tipo float y asignamos secuencialmente cualquier elemento de f a x.Cualquier método que devuelve una matriz es un buen candidato para emplearlo con la sintaxis foreach. Vamos a verlo con un ejemplo:

//: control/ForEachString.java

public class ForEachString {public static void main(String[] args) {for(char c : "An African Swallow".toCharArray() )System.out.print(c + " ");}} /* Output:A n   A f r i c a n   S w a l l o w*///:~

El método toCharArray() devuelve una matriz de char, como vemos la salida de este método puede ser utilizada con la sintaxis foreach.Esta sintaxis funciona con cualquier objeto de tipo Iterable (lo veremos más adelante).Muchas instrucciones for requieren ir paso a paso a través de una secuencia de valores enteros:

for (int i=0;i<100;i++)

Para este tipo de instrucciones la sintaxis foreach no funcionará a menos que creemos primero una matriz de valores int. Para simplificar esta tarea el autor ha creado un método range() en net.mindview.util.Range que genera y devuelve la matriz apropiada. La intención es que el método range() se utilice como importación de tipo static:

//: control/ForEachInt.javaimport static net.mindview.util.Range.*;import static net.mindview.util.Print.*;

public class ForEachInt {  public static void main(String[] args) {    for(int i : range(10)) // 0..9      printnb(i + " ");    print();    for(int i : range(5, 10)) // 5..9      printnb(i + " ");    print();

Ing. Pablo Cesar Ttito [email protected]

Page 8: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

    for(int i : range(5, 20, 3)) // 5..20 step 3      printnb(i + " ");    print();  }} /* Output:0 1 2 3 4 5 6 7 8 95 6 7 8 95 8 11 14 17*///:~

El método range() está sobrecargado por lo que se pueden utilizar diferentes listas de argumentos. La primera forma sobrecargada, range(10), empieza en 0 y genera valores hasta el extremo superior del rango sin incluir éste. La segunda forma, range(5,10), comienza con el primer valor y termina en el último valor menos 1. La tercera forma, range(5,20,3), incluye un valor de paso, realizándose los incrementos según este valor.El método range() permite la utilización de foreach en más lugares, sin embargo, es menos eficiente, por lo que si necesitamos utilizar el programa a la máxima velocidad, conviene que utilicemos un perfilador, que es una herramienta que mide el rendimiento del código.El método printnb() es equivalente a System.out.print, es decir, no genera un carácter de nueva línea, todo lo que escribe lo coloca en la misma línea.La sintaxis foreach ahorra tiempo a la hora de escribir código, facilita la lectura y comunica perfectamente qué es lo que estamos tratando de hacer (obtener cada elemento de la matriz), en lugar de cómo lo estamos haciendo (estoy creando un índice para poder utilizarlo con cada elemento de la matriz).

RETURNLa palabra clave return es un salto incondicional, es decir, es un salto en el flujo de ejecución que se produce sin realizar previamente comprobación alguna. Esta palabra clave tiene dos objetivos: especifica qué valor devolverá un método (si no es void) y hace que la ejecución salga del método actual devolviendo ese valor. Vamos a verlo con un ejemplo:

//: control/IfElse2.javaimport static net.mindview.util.Print.*;

public class IfElse2 {  static int test(int testval, int target) {    if(testval > target)      return +1;    else if(testval < target)      return -1;    else      return 0; // Match  }  public static void main(String[] args) {    print(test(10, 5));    print(test(5, 10));    print(test(5, 5));  }} /* Output:1-10*///:~

Ing. Pablo Cesar Ttito [email protected]

Page 9: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Cuando se ejecuta la instrucción return salimos del método.Si un método devuelve void y no se incluye return, habrá una instrucción return implícita al final de ese método, así pues no es necesario incluirla. Pero si el método va a devolver cualquier valor distinto de void, hay que asegurarse de que todas las rutas de ejecución devuelvan un valor.

BREAK Y CONTINUESe puede controlar el flujo de un bucle mediante break y continue. Break provoca la salida del bucle sin ejecutar el resto de instrucciones, mientras que continue detiene la ejecución de la iteración actual y vuelve al principio del bucle para comenzar con la siguiente iteración. Vamos a ver un ejemplo:

//: control/BreakAndContinue.java// Demonstrates break and continue keywords.import static net.mindview.util.Range.*;

public class BreakAndContinue {  public static void main(String[] args) {    for(int i = 0; i < 100; i++) {      if(i == 74) break; // Out of for loop      if(i % 9 != 0) continue; // Next iteration      System.out.print(i + " ");    }    System.out.println();    // Using foreach:    for(int i : range(100)) {      if(i == 74) break; // Out of for loop      if(i % 9 != 0) continue; // Next iteration      System.out.print(i + " ");    }    System.out.println();    int i = 0;    // An "infinite loop":    while(true) {      i++;      int j = i * 27;      if(j == 1269) break; // Out of loop      if(i % 10 != 0) continue; // Top of loop      System.out.print(i + " ");    }  }} /* Output:0 9 18 27 36 45 54 63 720 9 18 27 36 45 54 63 7210 20 30 40*///:~

Recuerda que el método range(100) devuelve una matriz de valores entre 0 y 99. Tanto en el primer bucle for, como en el segundo que utiliza foreach cuando el valor de i llega a 74 finaliza el bucle (break), no alcanza el 100. Y cuando el resto de la división entre i y 9 es diferente de 0 vuelve al principio del bucle (continue) y vemos que System.out.print(i+" "); ni siquiera se ejecuta, esta instrucción se ejecutará cuando i sea divisible por 9 (i%9==0). Luego tenemos un bucle while infinito del que salimos cuando j=1269 (break) y cuando el resto de dividir i por 10 es diferente de 0 volvemos al principio del bucle (continue). Las instrucciones que están por debajo de break y continue no se ejecutan.Un bucle infinito también se puede poner de la forma for(;;).

Ing. Pablo Cesar Ttito [email protected]

Page 10: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

LA INSTRUCCIÓN "GOTO"La instrucción goto ha estado presente en muchos lenguajes de programación desde el principio de la Informática. Goto representó el origen de las técnicas de control de programa en los lenguajes ensambladores: "Si se cumple A salta aquí, en caso contrario salta allí".Una instrucción goto es un salto en el nivel de código fuente, de ahí su mala reputación. ¿No hay una manera de reorganizar el código para que flujo de control no tenga que dar saltos? Edsger Dijkstra publicó el artículo "Goto considered harmful" en el que se cuestionó esta instrucción, desde entonces esta instrucción ha sido despreciada por muchos programadores.Sin embargo, el problema no es el uso del goto sino su abuso. En determinadas ocasiones incluso su uso es la mejor opción.Goto es una palabra reservada en Java pero no se utiliza. Hay dos instrucciones que se utilizan para salir de una iteración y que se asemejan a un salto, son break y continue. Estas instrucciones se asocian a goto porque utilizan la misma técnica: una etiqueta.Una etiqueta es un identificador seguido de dos puntos:

etiqueta1:

La etiqueta se coloca justo ntes de una instrucción de iteración. La única razón para utilizar una etiqueta es si vamos a anidar otra iteración o una instrucción switch (que veremos después). Si las etiquetas break y continue interrumpen el bucle actual, cuando se las usa como etiqueta interrumpen todos los bucles hasta el lugar donde la etiqueta se haya definido:

etiqueta1:iteración - externa{   iteración - interna{      //...      break; // (1)      //...      continue; // (2)      //...      continue etiqueta1; // (3)      //...      break etiqueta1; // (4)   }}

En (1) salimos de la iteración interna y acabamos en la externa. En (2) volvemos al principio de la iteración interna. En (3) nos salimos tanto de la iteración interna como de la externa y nos situamos en etiqueta1, a continuación continúa con la iteración pero comenzando por la iteración externa. En (4) nos salimos de las dos iteraciones, nos situamos en etiqueta1 pero no volvemos a entrar en la iteración, las dos iteraciones han finalizado. Veamos un ejemplo:

//: control/LabeledFor.java// For loops with "labeled break" and "labeled continue."import static net.mindview.util.Print.*;

public class LabeledFor {  public static void main(String[] args) {    int i = 0;    outer: // Can't have statements here    for(; true ;) { // infinite loop      inner: // Can't have statements here      for(; i < 10; i++) {        print("i = " + i);

Ing. Pablo Cesar Ttito [email protected]

Page 11: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

        if(i == 2) {          print("continue");          continue;        }        if(i == 3) {          print("break");          i++; // Otherwise i never               // gets incremented.          break;        }        if(i == 7) {          print("continue outer");          i++; // Otherwise i never               // gets incremented.          continue outer;        }        if(i == 8) {          print("break outer");          break outer;        }        for(int k = 0; k < 5; k++) {          if(k == 3) {            print("continue inner");            continue inner;          }        }      }    }    // Can't break or continue to labels here  }} /* Output:i = 0continue inneri = 1continue inneri = 2continuei = 3breaki = 4continue inneri = 5continue inneri = 6continue inneri = 7continue outeri = 8break outer*///:~

Ing. Pablo Cesar Ttito [email protected]

Page 12: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Si nos fijamos en el segundo bucle for, cuando i==2, volvemos al principio de este bucle (instrucción continue). Si i==3 nos salimos del bucle for (instrucción break), antes de salir tenemos que incrementar i ya que al salirnos con break de este bucle, la variable i no se incrementa y vamos a volver a entrar en este bucle for, porque el for que está por encima es infinito. Cuando i==7 volvemos al principio de los dos bucles (continue outer), es necesario también incrementar i, ya que el bucle for interior no realiza el incremento ya que con esta instrucción vamos al bucle for exterior. Cuando alcanzamos i==8 salimos de los dos bucles for (instrucción break outer), sin esta instrucción no habría manera de salir del bucle externo desde el bucle interno ya que el bucle externo es un bucle infinito.En aquellos casos en los que salir de un bucle implique salir de un método basta con ejecutar return.Vamos a ver un ejemplo de break y continue con un bucle while:

//: control/LabeledWhile.java

// While loops with "labeled break" and "labeled continue."

import static net.mindview.util.Print.*;

public class LabeledWhile {  public static void main(String[] args) {    int i = 0;    outer:    while(true) {      print("Outer while loop");      while(true) {        i++;        print("i = " + i);        if(i == 1) {          print("continue");          continue;        }        if(i == 3) {          print("continue outer");          continue outer;        }        if(i == 5) {          print("break");          break;        }        if(i == 7) {          print("break outer");          break outer;        }      }    }  }} /* Output:Outer while loopi = 1continuei = 2i = 3continue outerOuter while loopi = 4

Ing. Pablo Cesar Ttito [email protected]

Page 13: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

i = 5breakOuter while loopi = 6i = 7break outer*///:~

Cuando i==1 vuelve al principio del bucle while interior (instrucción continue). Si i==3 volvemos a la etiqueta outer (instrucción continue outer), a continuación entramos en los dos bucles while. Cuando i==5 nos salimos del bucle while interior (instrucción break). Si i==7 nos salimos del bucle while interior y exterior (instrucción break outer), es decir nos salimos de todos los bucles hasta el que tiene la etiqueta, incluyendo este último.En Java las etiquetas solo se utilizan si tenemos bucles anidados y queremos ejecutar las instrucciones break o continue a través de más de un nivel.

SWITCHEsta instrucción permite seleccionar entre diferentes fragmentos de código basándose en el valor de una expresión entera. Su forma es:

switch (selector - entero){   case valor - entero1 : instrucción; break;   case valor - entero2 : instrucción; break;   case valor - entero3 : instrucción; break;   case valor - entero4 : instrucción; break;   //...   default : instrucción;}

Selector - entero es una expresión que genera un valor entero. Switch compara selector - entero con cada valor - entero. Si hay coincidencia se ejecuta la correspondiente instrucción (una instrucción o varias). Si no hay ninguna coincidencia se ejecuta default.Cada case finaliza con una instrucción break, esto significa que cuando haya una coincidencia del selector - entero con el valor - entero, se ejecutará la instrucción correspondiente y la ejecución saldrá de switch. Sin embargo, la instrucción break es opcional. Si no se incluye se ejecutarán las instrucciones case situadas a continuación hasta que haya una instrucción break. Este comportamiento no es el deseado pero puede ser útil para programadores avanzados. La instrucción default no finaliza con break, aunque si lo consideramos oportuno lo podemos incluir.La instrucción switch permite realizar selecciones donde haya que elegir entre diversas rutas de ejecución, pero requiere de un selector que se evalúe para dar un valor entero como int o char. Si queremos emplear una cadena de caracteres o un número en coma flotante como selector no funcionará con switch. Vamos a ver un ejemplo en que se crean letras de manera aleatoria y se determina si son vocales o consonantes:

/: control/VowelsAndConsonants.java

// Demonstrates the switch statement.

import java.util.*;import static net.mindview.util.Print.*;

public class VowelsAndConsonants {public static void main(String[] args) {Random rand = new Random(47);for(int i = 0; i < 100; i++) {int c = rand.nextInt(26) + 'a';

Ing. Pablo Cesar Ttito [email protected]

Page 14: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

printnb((char)c + ", " + c + ": ");switch(c) {case 'a':case 'e':case 'i':case 'o':case 'u': print("vowel");break;case 'y':case 'w': print("Sometimes a vowel");break;default:  print("consonant");}}}} /* Output:y, 121: Sometimes a voweln, 110: consonantz, 122: consonantb, 98: consonantr, 114: consonantn, 110: consonanty, 121: Sometimes a vowelg, 103: consonantc, 99: consonantf, 102: consonanto, 111: vowelw, 119: Sometimes a vowelz, 122: consonant...*///:~

Ámbito de los datosÁmbito es el contexto que tiene un nombre dentro de un programa. El ámbito determina en qué partes del programa una entidad puede ser usada.Esto sirve para que se pueda volver a definir una variable con un mismo nombre en diferentes partes del programa sin que haya conflictos entre ellos.Si una variable es declarada dentro de un bloque (método/función/procedimiento), ésta será válida solo dentro de ese bloque y se destruirá al terminar el bloque. Adicionalmente, la variable no podrá verse ni usarse fuera del bloque (en el exterior del bloque). La variable dentro del bloque es una variable local y solo tiene alcance dentro del bloque que se creó y sus bloques hijos, pero no en bloques hermanos ni padres, una variable definida fuera de cualquier bloque es una variable global y cualquier bloque puede acceder a ella y modificarla.En el caso de programación orientada a objetos (POO), una variable global dentro de una clase es llamada variable de instancia, y cada objeto creado con esa clase tiene una. Adicionalmente existen variables globales que son comunes a un todos los objetos creados con una clase y son llamadas variables de clase.Hay dos tipos de alcances, el estático que también es llamado lexicográfico, donde el alcance se determina en tiempo de compilación, mientras que las variables de alcance dinámico se verificara en el hilo de ejecución.

Ing. Pablo Cesar Ttito [email protected]

Page 15: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Ámbito de páginaEl último ámbito, el ámbito página, tiene que ver exclusivamente con páginas JSP. Objetos con ámbito página se almacenan en la instancia de javax.servlet.jsp.PageContext asociada a cada página y son accesibles sólo dentro de la página JSP en el que fueron creados. Una vez que la respuesta se envía al cliente o la página remite a otros recursos, los objetos ya no estarán disponibles.

Cada página JSP tiene implícita una referencia a un objeto llamado pageContext que se pueden utilizar para almacenar y recuperar objetos de ámbito página.Tienen los mismos métodos getAttribute () y setAttribute () de otros ámbitos, y funcionan de la misma manera.

Ámbito de petición ( Request scope )Cada vez que un cliente emite una solicitud HTTP, el servidor crea un objeto que implementa la interfaz javax.servlet.http.HttpServletRequest.Entre otras cosas, este objeto contiene una colección de pares de atributos clave / valor que se puede utilizar para almacenar los objetos que cuya vida coincidirá con la vida de la solicitud.La clave de cada par es una cadena, y el valor puede ser cualquier tipo de objeto. Los métodos para almacenar y recuperar objetos en su ámbito de aplicación a partir de la solicitud son los siguientes: public void setAttribute (String nombre, objeto obj); Objeto público getAttribute (String nombre); Los atributos de una solicitud pueden ser eliminados mediante el método removeAttribute (), sin embargo, dado que el alcance de estos atributos está ligada a la de la solicitud, realmente su uso no es tan importante como lo es para otros ámbitos. Una vez que el servidor realiza una solicitud y una respuesta devuelve al cliente, la solicitud y de sus atributos ya no están disponibles para el cliente y puede ser eliminados por el recolector de basura de la JVM. Los Struts, por ejemplo, proporcionan un marco para permitir almacenar objetos JavaBeans en una solicitud, a fin de que puedan ser utilizados por los componentes de presentación, tales como las páginas JSP. Esto hace que sea mucho más fácil de acceder a los datos JavaBeans, sin tener que preocuparse más tarde por hacer un mantenimiento de limpieza de los objetos.Rara vez hay una necesidad de eliminar los objetos de alcance de solicitud, el contenedor web se encarga de eso. Los objetos almacenados en la solicitud son visibles sólo a los recursos que tienen acceso a esa petición. Una vez que la respuesta ha sido devuelta al cliente, la visibilidad desaparece y los objetos también.Objetos que se almacenan en una solicitud no son visibles para cualquier otra solicitud del cliente.

Ámbito de sesión( session scope )El siguiente nivel de visibilidad es el período de sesiones. El contenedor web crea un objeto que implementa la interfaz javax.servlet.http.HttpSession para identificar a un usuario a través de múltiples solicitudes de página. El cuándo una sesión se crea depende de la aplicación y el contenedor aplicación. La sesión del usuario se mantendrá por un período de tiempo relacionado con la frecuencia con que el usuario hace peticiones. El

Ing. Pablo Cesar Ttito [email protected]

Page 16: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

periodo de inactividad es configurable a través del descriptor de aplicación. También se puede destruir la sesión prematuramente llamando al método invalidate (). La sesión también permite definir una colección de objetos que se almacenan en base a un esquema de pares clave / valor como en el ámbito de la solicitud. La única diferencia entre éste y el proporcionado por la solicitud es la duración de los objetos. Los objetos de sesión existen a través de múltiples de solicitudes del cliente.Los Struts utilizan ampliamente los objetos de sesión. Un ejemplo son los objetos asociados al usuario visibles desde todo el framework.Los objetos almacenados en una sesión de usuario no son visibles para los usuarios con una sesión diferente.El contenedor web no proporciona la sincronización de los objetos almacenados en las distintas sesiones que pueda haber y es responsabilidad del desarrollador la protección de los recursos.

Ámbito de aplicación

Un mayor nivel de visibilidad y duración tienen los objetos almacenados en el ámbito de aplicación. Objetos de ámbito de aplicación son visibles a todos los clientes y los hilos de la aplicación web. Estos viven hasta que sean 'eliminados explícitamente' o hasta que se termine la aplicación. El servlet crea un contenedor de objetos, con interfaz javax.servlet.ServletContext para cada aplicación Web que está instalado en el contenedor. Más allá del alcance de la solicitud y el período de sesiones de objetos, la aplicación permite a los objetos ServletContext ser almacenados y recuperados por la aplicación completa y persistir durante la vida útil de las solicitud.Una aplicación que utilice el framework Struts debe almacenar JavaBeans visibles para todos los usuarios. Normalmente, los objetos son almacenados en este ámbito durante la aplicación de inicio y permanecer allí hasta que la aplicación termine.

Uso de la sesiónEn JSP las acciones que se pueden realizar sobre las sesiones se llevan a cabo mediante la interface HttpSession y los métodos que implementa. Esta interfaz está incluida dentro delpaquete javax.servlet.http y es utilizada por el contenedor de páginas JSP para crear una sesión entre el servidor y el cliente.Para obtener la sesión de un usuario se utiliza el método getSession() que devuelve una interfaz de tipo HttpSession.<%HttpSession sesion=request.getSession();%>Una vez creado el objeto de tipo sesión es posible acceder a una serie de datos sobre la misma. Uno de estos datos es idSession que devuelve un identificador único asociado a una sesión:<%HttpSession sesion=request.getSession(); out.println(“IdSesion: ”+sesion.getId());%>Cada intérprete de JSP generará un identificador diferente. Así en el caso del servidor Jakarta-Tomacat3.2.3, el resultado sería similar a:

Ing. Pablo Cesar Ttito [email protected]

Page 17: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Todas las sesiones que se crean tienen asociado un identificador (id) que es posible conocer a través del método getId ().

Es posible conocer el momento en el que se creó la sesión:

<%@page import=”java.util.*” session=”true” %><%HttpSession sesion=request.getSession(); out.println(“Creación: “+sesion.getCreationTime()); Date momento=new Date(sesion.getCreationTime()); out.println(“<BR>Creación: “+momento);%>

En el primer caso se muestra el dato tal cual lo devuelve el método getCreationTime (), que es una fecha en formato long, mientras que en el segundo caso se formatea para que tenga un aspecto más común.

Ing. Pablo Cesar Ttito [email protected]

Page 18: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

A través del método getCreationTime () es posible conocer la Fecha y la hora en que se creó la sesión.También se puede conocer la fecha y hora de la última vez que el cliente accedió al servidor con el que se creó la sesión, utilizando el método getLastAccesedTime():

<%Date acceso=new Date(sesion.getLastAccessedTime()); out.println(“Último acceso: “+acceso+”<br>”);%>

Teniendo en cuenta el momento en el que se creó la sesión y la última vez que se accedió al servidor, se puede conocer el tiempo que lleva el cliente conectado al servidor, o lo que es lo mismo el tiempo que lleva el usuario navegando por la páginas JSP:

<%long longDuracion=sesion.getLastAccessedTime() sesion.getCreationTime();Date duracion=new Date(longDuracion); out.println(“Duracion:“+duracion.getMinutes()+”min.”+duracion.getSeconds()+”seg”);%>

Ing. Pablo Cesar Ttito [email protected]

Page 19: TEMA Nº 8: CONTROL DE EJECUCIÓN Y MANTENIMIENTO DE SESIÓN

Desarrollo de Aplicaciones Web con J2EE

Utilizando el momento en el que se creó la sesión y la última vez accedió se puede llegar a saber el tiempo que ha estado el usuario visitando nuestras páginas web.La interfaz HttpSession ofrece el método isNew() mediante el cual es posible saber si la sesión creada es nueva o se está tomando de una previamente creada:

<%HttpSession sesion=request.getSession(); out.println(“nueva: “+sesion.isNew());%>

Si se ejecuta el ejemplo la primera vez el método devolverá true, ya que previamente no había ninguna sesión y ha sido creada en ese instante. Si se recarga la página devolverá false ya que la sesión ya ha sido creada.Las sesiones no necesitan ningún tipo de mantenimiento, una vez creadas no es necesario utilizarlas de forma obligatoria o tener que refrescar los datos asociados a las mismas, se deben ver como una variable más con la diferencia que pueden ser utilizadas en cualquier página independientemente del lugar en el que hayan sido creadas.

Cookies persistentesLas cookies persistentes se almacenan durante un tiempo establecido por el servidor Web cuando éste pasa la cookie a Internet Explorer. Estas cookies se utilizan para almacenar información de estado entre las visitas a un sitio. 

Las cookies por sesión almacenan información de estado únicamente dentro de una sesión. Estas cookies sólo se almacenan en caché mientras un usuario visita el servidor Web que emite la cookie por sesión y se eliminan de la caché cuando el usuario cierra la sesión. 

Las páginas Active Server (ASP) que se ejecutan en Microsoft Internet Information Server 3.0 o posterior utilizan con frecuencia cookies por sesión. Estas cookies almacenan información de la sesión mientras el usuario examina varias páginas ASP de un sitio. 

Ing. Pablo Cesar Ttito [email protected]