由于Spring 4.1的Java 8的的java.util.Optional
,容器对象可能会或可能不包含非空值,支持与@RequestParam
, @RequestHeader
和@MatrixVariable
。 使用Java 8的java.util.Optional
请确保参数永远不会为null
。
请求参数
在此示例中,我们将使用@RequestParam
将java.time.LocalDate
绑定为java.util.Optional
:
@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();}
}
在Spring 4.1之前,我们会遇到一个例外,即找不到匹配的编辑器或转换策略。 从Spring 4.1开始,这不再是问题。 为了验证绑定是否正常工作,我们可以创建一个简单的集成测试:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class SampleSomeControllerTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();}// ...}
在第一个测试中,我们将检查绑定是否正常工作以及是否返回了正确的结果:
@Test
public void bindsNonNullLocalDateAsRequestParam() throws Exception {mockMvc.perform(get("/o/r").param("ld", "2020-01-01")).andExpect(content().string("ld: 2020-01-01"));
}
在下一个测试中,我们将不传递ld
参数:
@Test
public void bindsNoLocalDateAsRequestParam() throws Exception {mockMvc.perform(get("/o/r")).andExpect(content().string("ld: "));
}
两个测试都应该是绿色的!
请求标题
同样,我们可以将@RequestHeader
绑定到java.util.Optional
:
@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();
}
和测试:
@Test
public void bindsNonNullCustomHeader() throws Exception {mockMvc.perform(get("/o/h").header("Custom-Header", "Value")).andExpect(content().string("Custom-Header: Value"));
}@Test
public void noCustomHeaderGiven() throws Exception {mockMvc.perform(get("/o/h").header("Custom-Header", "")).andExpect(content().string("Custom-Header: "));
}
矩阵变量
在Spring 3.2中@MatrixVariable
注释指示方法参数应绑定到路径段内的名称/值对:
@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调用上述方法。 让我们为此做一个测试:
@Test
public void bindsNonNullMatrixVariables() throws Exception {mockMvc.perform(get("/o/m/42;p=4;q=2")).andExpect(content().string("p: 4, q: 2"));
}
不幸的是,该测试将失败,因为默认情况下,Spring MVC中禁用了对@MatrixVariable
批注的支持。 为了启用它,我们需要调整配置并将RequestMappingHandlerMapping
的removeSemicolonContent
属性设置为false
。 默认情况下,它设置为true
。 我已经用WebMvcConfigurerAdapter
完成了,如下所示:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}
}
现在所有测试都通过了! 请在这里找到本文的源代码: https : //github.com/kolorobot/spring41-samples
翻译自: https://www.javacodegeeks.com/2014/07/spring-4-1-and-java-8-java-util-optional.html