
Начиная с Spring 4.1 Java 8 java.util.Optional , объект-контейнер, который может содержать или не содержать ненулевое значение, поддерживается с помощью @RequestParam , @RequestHeader и @MatrixVariable . При использовании Java 8 java.util.Optional вы убедитесь, что ваши параметры никогда не равны null .
Параметры запроса
В этом примере мы java.time.LocalDate как java.util.Optional используя @RequestParam :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@RestController@RequestMapping("o")public class SampleController { @RequestMapping(value = "r", produces = "text/plain") public String requestParamAsOptional( @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) @RequestParam(value = "ld") Optional<LocalDate> localDate) { StringBuilder result = new StringBuilder("ld: "); localDate.ifPresent(value -> result.append(value.toString())); return result.toString(); }} |
До весны 4.1 мы получали исключение, что не было найдено ни одного подходящего редактора или стратегии конвертации. С весны 4.1 это больше не проблема. Чтобы убедиться, что привязка работает правильно, мы можем создать простой интеграционный тест:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes = Application.class)@WebAppConfigurationpublic class SampleSomeControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setUp() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } // ...} |
В первом тесте мы проверим, правильно ли работает привязка и возвращается ли правильный результат:
|
1
2
3
4
5
|
@Testpublic void bindsNonNullLocalDateAsRequestParam() throws Exception { mockMvc.perform(get("/o/r").param("ld", "2020-01-01")) .andExpect(content().string("ld: 2020-01-01"));} |
В следующем тесте мы не будем передавать параметр ld :
|
1
2
3
4
5
|
@Testpublic void bindsNoLocalDateAsRequestParam() throws Exception { mockMvc.perform(get("/o/r")) .andExpect(content().string("ld: "));} |
Оба теста должны быть зелеными!
Заголовки запроса
Точно так же мы можем связать @RequestHeader с java.util.Optional :
|
1
2
3
4
5
6
7
8
9
|
@RequestMapping(value = "h", produces = "text/plain")public String requestHeaderAsOptional( @RequestHeader(value = "Custom-Header") Optional<String> header) { StringBuilder result = new StringBuilder("Custom-Header: "); header.ifPresent(value -> result.append(value)); return result.toString();} |
И тесты:
|
01
02
03
04
05
06
07
08
09
10
11
|
@Testpublic void bindsNonNullCustomHeader() throws Exception { mockMvc.perform(get("/o/h").header("Custom-Header", "Value")) .andExpect(content().string("Custom-Header: Value"));}@Testpublic void noCustomHeaderGiven() throws Exception { mockMvc.perform(get("/o/h").header("Custom-Header", "")) .andExpect(content().string("Custom-Header: "));} |
Матричные переменные
Представленная в Spring 3.2 аннотация @MatrixVariable указывает, что параметр метода должен быть связан с парой имя-значение в сегменте пути:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@RequestMapping(value = "m/{id}", produces = "text/plain")public String execute(@PathVariable Integer id, @MatrixVariable Optional<Integer> p, @MatrixVariable Optional<Integer> q) { StringBuilder result = new StringBuilder(); result.append("p: "); p.ifPresent(value -> result.append(value)); result.append(", q: "); q.ifPresent(value -> result.append(value)); return result.toString();} |
Вышеуказанный метод может быть вызван через /o/m/42;p=4;q=2 url. Давайте создадим тест для этого:
|
1
2
3
4
5
|
@Testpublic void bindsNonNullMatrixVariables() throws Exception { mockMvc.perform(get("/o/m/42;p=4;q=2")) .andExpect(content().string("p: 4, q: 2"));} |
К сожалению, тест не @MatrixVariable , потому что поддержка аннотации @MatrixVariable по умолчанию отключена в Spring MVC . Чтобы включить его, нам нужно настроить конфигурацию и установить для свойства removeSemicolonContent RequestMappingHandlerMapping значение false . По умолчанию установлено значение true . Я сделал с WebMvcConfigurerAdapter как WebMvcConfigurerAdapter ниже:
|
1
2
3
4
5
6
7
8
9
|
@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); urlPathHelper.setRemoveSemicolonContent(false); configurer.setUrlPathHelper(urlPathHelper); }} |
И теперь все испытания проходят! Пожалуйста, найдите исходный код этой статьи здесь: https://github.com/kolorobot/spring41-samples
| Ссылка: | Spring 4.1 и Java 8: java.util.Опционально от нашего партнера JCG Рафаля Боровца в блоге Codeleak.pl . |