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