Статьи

Что такое матричные переменные Spring 3.2?

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

Примеры были:

1
2
3
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 основываются на существующей @MatrixVariable Spring MVC, вводя новую аннотацию @MatrixVariable . Это используется для аннотирования аргументов метода обработчика запросов, чтобы Spring мог вставлять соответствующие биты матрицы uri. @MatrixVariable имеет четыре аргумента: value , defaultValue , pathVar и required , и все они полностью объяснены в javadocs Springs .

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

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

1
2
3
4
5
6
@Controller
@RequestMapping(value = "/matrixvars")
public class MatrixVariableController {
  
  private static final Logger logger = LoggerFactory.getLogger(MatrixVariableController.class);
}

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

Следующее, что нужно сделать, это добавить некоторый код в этот класс, который имеет дело с первым URI:

1
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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  @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 будет @RequestMapping Spring на сопоставление любых соответствующих запросов этому методу. Текст внутри фигурных скобок {stocks} указывает, что эту часть URI можно проанализировать и вставить в соответствующий аргумент метода.

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

1
A=B,C,D

или же

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

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

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

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

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

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

1
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 сопоставлен следующему методу:

01
02
03
04
05
06
07
08
09
10
11
12
  @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 аннотации, предоставляющий значения stocks и accounts . Они аккуратно обозначают, где значения переменных матрицы нужно вводить в аргументы метода.

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

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