Back-End

17 out, 2013

O que são variáveis Matrix para Spring 3.2? – Parte 02: o código

Publicidade

Meu último artigo sobre o suporte do Spring para variáveis Matrix se concentrou em explicar o que elas eram e por que você gostaria de usá-las. Depois de ter resolvido o que e o porquê, este artigo é sobre como e como usá-las. Eu também dei vários exemplos de Matrix URIs, e parece boa ideia demonstrar algum código que processa algumas delas.

Os exemplos foram os seguintes:

http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.40,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07

http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.90,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07/account;name=roger;number=105;location=stoke-on-trent,uk

Como seria de esperar, ao escrever um código para lidar com variáveis Matrix, os caras do Spring estão construindo sobre o framework Spring MVC existente, introduzindo a nova anotação @MatrixVariable. Isso é usado para anotar os argumentos do método do manipulador para que o Spring possa injetar os bits relevantes da matrix URI. @MatrixVariable tem quatro argumentos: value, defaultValue, pathVar e required, todos totalmente explicados nos javadocs do Spring.

Então vamos ao código… Se você se lembrar do meu último artigo sobre esse assunto, o cenário que eu escolhi foi um que lida com o processamento de um monte de preços das ações/ações e o exemplo de aplicativo, disponível no Github, leva uma matrix URI, o corta e o adiciona a um Model para um JSP para exibir.

Ao escrever o código, a primeira coisa a fazer é criar um novo controller para processar os URIs…

@Controller
@RequestMapping(value = "/matrixvars")
public class MatrixVariableController {

  private static final Logger logger = LoggerFactory.getLogger(MatrixVariableController.class);
}

No código, eu adicionei uma anotação @RequestMapping no nível da classe, que contém a primeira parte dos meus URIs: matrixvars. Isso é uma coisa útil para fazer, uma vez que direciona todos os URIs que contêm o valor ‘matrixvar’ como o primeiro elemento do caminho para esse controller e poupa um monte de duplicação.

A próxima coisa a fazer é adicionar algum código a essa classe que lida com o primeiro URI:

http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.40,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07

O primeiro método do manipulador da requisição é:

  @RequestMapping(value = "/{stocks}", method = RequestMethod.GET)
  public String showPortfolioValues(@MatrixVariable Map<String, List<String>> matrixVars, Model model) {

    logger.info("Storing {} Values which are: {}", new Object[] { matrixVars.size(), matrixVars });

    List<List<String>> outlist = map2List(matrixVars);
    model.addAttribute("stocks", outlist);

    return "stocks";
  }

  private List<List<String>> map2List(Map<String, List<String>> stocksMap) {

    List<List<String>> outlist = new ArrayList<List<String>>();

    Collection<Entry<String, List<String>>> stocksSet = stocksMap.entrySet();

    for (Entry<String, List<String>> entry : stocksSet) {

      List<String> rowList = new ArrayList<String>();

      String name = entry.getKey();
      rowList.add(name);

      List<String> stock = entry.getValue();
      rowList.addAll(stock);
      outlist.add(rowList);
    }

    return outlist;
  }

Olhando para a anotação @RequestMapping, você pode ver que eu lhe atribuí um valor de /{stocks}. Isso, quando combinado com a anotação @RequestMapping no nível da classe anotação, vai instruir o Spring a mapear todas as solicitações correspondentes a esse método. O texto dentro das chaves, {stocks}, indica que essa parte do URI pode ser analisada e injetada no argumento do método apropriado.

Em seguida, dê uma olhada na anotação @MatrixVariable. Isso fica perfeitamente na frente do argumento em que eu quero que os dados de estoque injetado; no entanto, a coisa um pouco complicada aqui é conseguir o tipo de argumento certo. Se você pegar o errado, então simplesmente vai obter um ClassCastException quando tentar usar seus dados. Quando o dado de entrada é da forma:

A=B,C,D

ou

A=B,C,D;W=X,Y,Z

…então o tipo é Map<String,List<String>>, em que as teclas são A e W e os seus respectivos valores são B, C, D e X, Y, Z.

Assim, dado o URI acima, o argumento map conterá ….

{BT.A=[276.70, +10.40, +3.91], AZN=[236.00, +103.00, +3.29], SBRY=[375.50, +7.60, +2]}

Essa é a parte mais importante, o restante do método é muito simples, já que simplesmente converte o mapa da entrada em uma lista e a adiciona para o modelo para o JSP (não mostrado aqui) exibir. Note que esse não é um código muito útil, por isso não preste muita atenção a ele, e eu não gosto de incorporar coleções dentro de coleções – não parece uma boa ideia.

Seguindo em frente, agora eu vou dar uma olhada no próximo URI. Repare que eu, propositalmente, o fiz semelhante ao primeiro, com a única diferença sendo a adição de detalhes da conta do usuário:

http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.90,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07/account;name=roger;number=105;location=stoke-on-trent,uk

Esse URI é mapeado com o seguinte método:

  @RequestMapping(value = "/{stocks}/{account}", method = RequestMethod.GET)
  public String showPortfolioValuesWithAccountInfo(@MatrixVariable(pathVar = "stocks") Map<String, List<String>> stocks,
      @MatrixVariable(pathVar = "account") Map<String, List<String>> accounts, Model model) {

    List<List<String>> stocksView = map2List(stocks);
    model.addAttribute("stocks", stocksView);

    List<List<String>> accountDetails = map2List(accounts);
    model.addAttribute("accountDetails", accountDetails);

    return "stocks";
  }

Nesse caso, a descrição completa do caminho é /matrixvars/{stocks}/{account}. Eu acho que isso simplesmente diz ao Spring para se preocupar com /matrixvars, seguido por um ‘/’, seguido por qualquer coisa, seguido por um ‘/’, seguido por qualquer coisa, quando se faz o mapeamento.

Nesse caso, existem duas anotações @MatrixVariable às quais eu adicionei o argumento pathVar da anotação fornecendo valores stocks e accounts. Esse rótulo perfeito onde os valores das variáveis Matrix precisam injetar os argumentos do método.

O último ponto a lembrar é que as variáveis Matrix são incrivelmente flexíveis; há mais três argumentos para a anotação @MatrixVaraible que eu não considerei aqui; no entanto, o procedimento geral é o mesmo em todos os casos: pegue o URI e descubra o que as diferentes variáveis Matrix são, projete um manipulador de solicitação e mapeie as variáveis Matrix do URI a seus argumentos métodos – tendo o cuidado de garantir que você obtenha o tipo de argumento correto.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://www.captaindebug.com/2013/04/just-what-are-spring-32-matrix_15.html