Vytváranie funkčných servletov prináša mnohé problémy a úlohy, s ktorými sa musí vývojár spoľahlivo vysporiadať. Často sú to rôzne prekážky, s ktorými nie je možné počítať vopred. Inokedy môžu spôsobiť vrásky na čele veľmi špecifické požiadavky zákazníka, ktoré nie vždy sú priamočiare. Jednou z často sa opakujúcich úloh programátora je spracovanie, respektíve parsing parametrov.

Ak píšete servlety, alebo sa zaujímate o tento seriál, iste ste si všimli, aké ťažkopádne až otravné môže byť pravidelné spracovanie request parametrov, špeciálne vtedy, ak potrebujete čisto textové reťazce konvertovať na iný natívne podporovaný dátový formát jazyka Java. Napríklad môže ísť o parameter predstavujúci číselnú hodnotu v textovej podobe, ktorý ale potrebujete konvertovať na skutočné číslo. Neskôr vás napadne, že súčasťou transformačného mechanizmu by mala byť aj kontrola, či požadovaný parameter skutočne existuje, a ak áno, či nie je vo forme, ktorú nie je možné konvertovať. Časť programu využívajúca štandardné servlet API a spĺňajúca vyššie uvedené požiadavky, by mohla vyzerať nasledovne:

int count;
String param = request.getParameter(„count“);
if (param == null || param.length() == 0) {
 /* metóda zodpovedná sa spracovanie parametra v prípade,
  že parameter neexistuje alebo má nulovú dĺžku */

 handleNoCount();
}
else {
 try {
  count = Integer.parseInt(param);
 }
 catch (NumberFormatException e) {
 /* metóda sa vykoná v prípade, že parameter
  nie je možné konvertovať na Integer */

  handleMalformedCount();
 }
}

Je vám tento kód povedomý? Určite ste sa s jeho variantou už stretli. Napriek tomu si trúfam povedať, že nie je príliš elegantný. Hotová katastrofa môže byť, ak takýchto parametrov treba spracovať viac naraz. Java je objektový jazyk a preto ako okamžité riešenie sa ponúka vytvoriť si vlastnú triedu, ktorej objekt sa postará o spracovanie problematických parametrov. Teda využijeme princíp „napíš raz, použi kedykoľvek„. Nazvime si túto triedu ParameterParser, jej výpis nasleduje nižšie.

ParameterParser.java:

import java.io.*;
import javax.servlet.*;
public class ParameterParser {
 private ServletRequest req;
 public ParameterParser(ServletRequest request) {
  this.req = request;
 }
 public String getStringParameter(String name)
                        throws ParameterNotFoundException {
  String value = req.getParameterValue(name);
  if (value == null)
   throw new ParameterNotFoundException(name + “ not found“);
  else if (value.length() == 0)
   throw new ParameterNotFoundException(name + “ was empty“);
  else return value;
 }
 public String getStringParameter(String name, String def) {
  try { return getStringParameter(name); }
  catch (Exception e) { return def; }
 }
 public boolean getBooleanParameter(String name)
                         throws ParameterNotFoundException {
 return new Boolean(getStringParameter(name)).booleanValue();
 }
 public boolean getBooleanParameter(String name, boolean def) {
  try { return getBooleanParameter(name); }
  catch (Exception e) { return def; }
 }
 public byte getByteParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return Byte.parseByte(getStringParameter(name));
 }
 public byte getByteParameter(String name, byte def) {
  try { return getByteParameter(name); }
  catch (Exception e) { return def; }
 }
 public char getCharParameter(String name)
                         throws ParameterNotFoundException {
  String param = getStringParameter(name);
  if (param.length() == 0)
  throw new ParameterNotFoundException(name + “ is empty string“);
  else
   return (param.charAt(0));
 }
 public char getCharParameter(String name, char def) {
  try { return getCharParameter(name); }
  catch (Exception e) { return def; }
 }
 public double getDoubleParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return new Double(getStringParameter(name)).doubleValue();
 }
 public double getDoubleParameter(String name, double def) {
  try { return getDoubleParameter(name); }
  catch (Exception e) { return def; }
 }
 public float getFloatParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return new Float(getStringParameter(name)).floatValue();
 }
 public float getFloatParameter(String name, float def) {
  try { return getFloatParameter(name); }
  catch (Exception e) { return def; }
 }
 public int getIntParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return Integer.parseInt(getStringParameter(name));
 }
 public int getIntParameter(String name, int def) {
  try { return getIntParameter(name); }
  catch (Exception e) { return def; }
 }
 public long getLongParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return Long.parseLong(getStringParameter(name));
 }
 public long getLongParameter(String name, long def) {
  try { return getLongParameter(name); }
  catch (Exception e) { return def; }
 }
 public short getShortParameter(String name)
  throws ParameterNotFoundException, NumberFormatException {
  return Short.parseShort(getStringParameter(name));
 }
 public short getShortParameter(String name, short def) {
  try { return getShortParameter(name); }
  catch (Exception e) { return def; }
 }
}

Trieda ParameterParser obsahuje viac ako tucet metód, zodpovedných za prevod request parametrov na niektorý z primitívnych dátových typov jazyka Java. Obsahuje tiež dve metódy getStringParameter(), ktoré využijete v prípade, že potrebujete vrátiť parametre v „surovom“ stave, ako textové reťazce. Trieda je teda značne univerzálna, ale nič vám nebráni upraviť si ju podľa vlastných potrieb. Všimnite si však, že jednotlivé metódy triedy nepočítajú s možnosťou, že jeden parameter obsahuje viac hodnôt. V prípade, že by taká situácia nastala, bolo by nutné triedu vhodne upraviť. Nasleduje výpis pomocnej triedy ParameterNotFoundException.

ParameterNotFoundException.java:

public class ParameterNotFoundException extends Exception {
 public ParameterNotFoundException() {
  super();
 }
 public ParameterNotFoundException(String s) {
  super(s);
 }
}

Táto trieda je veľmi jednoduchá až primitívna a určite nepotrebuje vysvetlenie. Pozrime sa teda na to, ako by vyzeral náš kód, s ktorým sme tento článok začínali, v prípade, že využijeme triedu ParameterParser:

int count;
ParameterParser parser = new ParameterParser(req);
try {
 count = parser.getIntParameter(„count“);
}
catch (NumberFormatException e) {
 handleMalformedCount();
}
catch (ParameterNotFoundException e) {
 handleNoCount();
}

Metóda getIntParameter() vráti hodnotu parametra konvertovanú na integer. V prípade, že parameter nie je možné konvertovať z dôvodu nepoužiteľného formátu, metóda vyhodí výnimku NumberFormatException. Ak parameter, respektíve jeho hodnota nie sú súčasťou požiadavky, metóda vráti výnimku ParameterNotFoundException. Ak stačí, aby servlet vrátil prednastavenú hodnotu v prípade, ak vznikne nejaký problém pri spracovaní parametrov, uvedený kód je možné ešte viac zjednodušiť:

ParameterParser parser = new ParameterParser(req);
int count = parser.getIntParameter(„count“, 0);

Táto druhá verzia metódy getIntParameter() akceptuje okrem názvu parametra aj číselnú hodnotu, ktorá bude vrátená na miesto vyhodenia niektorej výnimky. Na záver si môžete stiahnuť súbory s príkladom.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět