Статьи

Что такое матричные переменные Spring 3.2? — Часть 2. Кодекс

Мой последний блог, посвященный поддержке Spring для Matrix Variables, был сосредоточен на объяснении того, что они из себя представляют и почему вы хотите их использовать. Разобравшись, что и почему , этот блог посвящен тому, как и как вы их используете. Я также привел несколько примеров Matrix 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

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

Как и следовало ожидать, при написании кода для обработки матричных переменных ребята из Spring опираются на существующую инфраструктуру Spring MVC, вводя новую аннотацию @MatrixVariable. Это используется для аннотирования аргументов метода обработчика запросов, чтобы Spring мог вставлять соответствующие биты матрицы uri. @MatrixVariable имеет четыре аргумента: value, defaultValue, pathVar и required, и все они полностью объяснены в javadocs Springs .

И так к некоторому коду … Если вы помните в моем последнем блоге на эту тему, я выбрал сценарий, который имеет дело с обработкой множества цен на акции / акции, и пример приложения, доступного на Github , использует Matrix URI, разбирает его и добавляет в модель для отображения JSP.

При написании кода, первое, что нужно сделать, это создать новый контроллер для обработки URI …

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

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

В коде я добавил аннотацию @RequestMapping уровня класса, которая содержит первый блок моих URI: matrixvars. Это полезная вещь, так как она направляет все URI, которые содержат значение matrixvar, как первый элемент пути к этому контроллеру и экономит много дублирования.

Следующее, что нужно сделать, это добавить некоторый код в этот класс, который имеет дело с первым 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

Первый метод обработчика запроса:

@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;
  }

взглянув на аннотацию @RequestMapping, вы увидите, что я присвоил ей значение / {stocks}. В сочетании с аннотацией уровня @RequestMapping это будет указывать Spring на сопоставление любых соответствующих запросов этому методу. Текст внутри фигурных скобок {stocks} указывает, что эту часть URI можно проанализировать и вставить в соответствующий аргумент метода.

Далее взгляните на аннотацию @MatrixVariable. Это аккуратно перед аргументом, в который я хочу ввести данные о запасах; однако, немного хитрая вещь здесь — получить правильный тип аргумента. Если вы ошиблись, вы просто получите ClassCastException, когда попытаетесь использовать ваши данные. Когда входные данные имеют форму:

A=B,C,D

или же

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

… тогда тип — Map <String, List <String >>, где ключи — это A и W, а их соответствующие значения — B, C, D и X, Y, Z.

Следовательно, учитывая URI выше, аргумент карты будет содержать ….

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

С этим немного покончено, остальная часть метода очень прямолинейна, поскольку просто преобразует входную карту в список и добавляет ее в модель для отображения JSP (здесь не показано). Обратите внимание, что это не очень полезный код, поэтому не обращайте на него особого внимания, и, кроме того, я не люблю встраивать коллекции в коллекции — это не очень хорошая идея.

Двигаясь дальше, я сейчас посмотрю на следующий URI. Обратите внимание, что я намеренно сделал это похожим на первый, с единственным отличием — добавление данных учетной записи пользователя:

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

Этот URI сопоставлен следующему методу:

@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";
  }

В этом случае полное описание пути — / matrixvars / {stocks} / {account}. Я предполагаю, что это просто говорит Spring искать / matrixvars, за которым следует ‘/’, за которым следует что-либо, за которым следует ‘/’, а затем что-нибудь, когда он выполняет свое отображение.

В этом случае есть две аннотации @MatrixVariable, к которым я добавил аргумент pathVar аннотации, предоставляющий значения акций и счетов. Они аккуратно обозначают, где значения переменных матрицы нужно вводить в аргументы метода.

И последний момент, о котором следует помнить, это то, что переменные матрицы очень гибкие есть еще три аргумента к аннотации @MatrixVaraible, которые я здесь не рассматривал; тем не менее, общая процедура одинакова в каждом случае: возьмите URI, выясните, каковы различные матричные переменные, спроектируйте обработчик запроса и сопоставьте матричные переменные URI с аргументами ваших методов — заботясь о том, чтобы вы получили тип аргумента верный.


Полный пример кода для этого блога доступен на Github: https://github.com/roghughe/captaindebug/tree/master/spring-3.2