Spring 4.1與Java 8 java.util.Optional
在Spring 4.1中,利用Java 8的java.util.Optional,通過<code>@RequestParam</code>、<code>@RequestHeader</code>和<code>@MatrixVariable</code>三個注解,支持了僅包含非空(non-null)的容器對象。有了Java 8的java.util.Optional,你可以保證你的參數永遠不會為null。
Request Params (請求參數)
在這個例子中,我們將使用@RequestParam注解把java.time.LocalData綁定為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之前,可能會發生no matching editors or coversion strategy was found(找不到匹配的編輯或轉換策略)異常,這在Spring 4.1中不再是一個問題。為了驗證這個綁定能夠有效的運行,我們編寫了一個簡單的集成測試:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class SampleSomeControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public 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: "));
} 兩個測試都順利通過了!
Request Header (請求頭部)
類似的,我們可以把@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: "));
} Matrix Variables (數組變量)
在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();
} 以上的方法可以通過獲取url/o/m/42;p=4;q=2來調用。我們寫個例子測試一下:
@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,默認為true,設置為false。通過WebMvcConfigurerAdapter設置了這個屬性,就像下面這樣:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
} 現在,所有的測試都可以通過了。在這里你可以找到這篇文章的示例源碼(github)。
原文鏈接: javacodegeeks 翻譯: ImportNew.com - xiafei
譯文鏈接: http://www.importnew.com/13169.html