Spring 4.1與Java 8 java.util.Optional

jopen 10年前發布 | 19K 次閱讀 Java 8 Java開發

在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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!