読者です 読者をやめる 読者になる 読者になる

ぺーぺーSEのブログ

備忘録・メモ用サイト。

SpringMVCのアノテーションと非同期実行と試験

SpringMVCのアノテーション

  • @Controller
    • MVCのコントローラとなるクラスに付与する
  • @RestController
    • Restfulサービスを構築する際のMVCコントローラクラスに付与する
    • @Controllerと@ResponseBodyを付与したサイト同等
  • @RequestMapping
    • 特定の「URIvalue)、「HTTPメソッドmethod)」、「HTTPヘッダ(headers)」、「リクエストパラメータ(params)」を処理するメソッドに付与
    • 例)headersがAND表記の場合
      • @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET, headers={"Accept=application/*","Content-Type=text/*"})
    • 例)headersがOR表記の場合
      • @RequestMapping(headers="Accept=application/json,application/xml")
      • paramesの記法はheadersに同じ
    • また、「consumes(クライアントから送付されたメディアタイプを指定)」、「produces(クライアントへ返すメディアタイプを指定)」も指定できる
    • 例)JSONで受けてJSONで返す場合
      • @RequestMapping(consumes="application/json", produces="application/json")
  • @RequestParam
  • @PathVariable
    • URIのPathParamとしてメソッド引数に注入できる
    • 例)「@RequestMapping(value="/owners/{ownerId}")」がメソッドに付与されている場合
      • public String findOwner(@PathVariable("ownerId") String ownerId) {
  • @RequestHeader
    • 特定のHTTPヘッダをメソッド引数に注入できる
  • @RequestBody
    • HTTPリクエストボディをメソッド引数に注入できる
  • @ResponseBody
    • オブジェクトをHTTPレスポンスのボディとして返却できる
  • @ResponseStatus
    • メソッドに付与してHTTPレスポンスのステータスを指定できる
    • 例)
      • @ResponseStatus(value = HttpStatus.BAD_RESUEST)
  • @ExceptionHandler
    • 同一コントローラ内で発生した例外を処理するメソッドに付与する
    • 例)SampleExceptionを処理するメソッドに付与する場合
      • @ExceptionHandler(SampleException.class)
  • @CookieValue
  • @InitBinder
  • @ModelAttribute

※@InitBinderと@ModelAttributeについてはまだよくわからん。下記参照。
https://sites.google.com/site/soracane/home/springnitsuite/spring-mvc/04-ji-ben-gai-nian-controllerno-chu-lifuro

@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  // POST /pizzas/bake?temp=400
  @RequestMapping(value = "/bake", method = POST)
  public void bake(@RequestParam Integer temp) {
    ...
  }
}
@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  // POST /pizzas/bake/400
  @RequestMapping(value = "/bake/{temp}", method = POST)
  public void bake(@PathVariable Integer temp) {
    ...
  }
}
@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  // GET /pizzas
  @RequestMapping(method = GET, produces = "application/json")
  public @ResponseBody List<Pizza> list() {
    ...
  }
}
@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  // GET /pizzas
  @RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE )
  public @ResponseBody List<Pizza> list() {
    ...
  }
}
@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  // GET /pizzas
  @ResponseStatus(HttpStatus.CREATED)
  @RequestMapping(method = PUT, consumes = "application/json" )
  public void create(@RequestBody Pizza pizza) {
    ...
  }
}
@Controller
public class PizzaController {

  @RequestMapping(method = RequestMethod.GET )
  public String validateForm(@ModelAttribute("userDetails") UserDetails details) {
    ...
  }
  
  @ModelAttribute("userDetails")
  public UserDetails getUserDetails(HttpServletRequest request) {
    UserDetails user = new UserDetails();
    user.setFirstName(request.getParameter("firstName"));
    return user;
  }
}
  • コントローラクラスのメソッドにて引数に指定可能な型:
    • Servlet API(HttpServletRequest, HttpServletResponse, HttpSession)
    • Spring framework API(WebRequest, NativeWebRequest, HttpEntity)
    • java.util.Locale
    • java.io.InputStream, java.io.Reader
    • java.io.OutputSterem, java.io.Writer
    • java.security.Principle
    • java.util.Map, Model, ModelMap
    • Errors, BindingResult
  • コントローラクラスのメソッドにて返り値に指定可能な型:
    • ModelAndView, Model, java.util.Map, View
    • String
    • void
    • HttpEntity, ResponseEntity

★SpringMVCのControllerでURLを厳密に判定する
http://d.hatena.ne.jp/eiryu9/20130120/1358651987

SpringMVCの非同期実行


Async MVC Proccessing: Callable

@Controller
@RequestMapping("/pizzas")
public class PizzaController {

  @RequestMapping(value = "/orders", method = POST )
  @ResponseBody
  public Callable<String> upload(MultipartFile file) {
    return new Callable<Pizza>() {
      public Pizza call() throws Exception {
        ...
        return pizza;
      }
    }
  }
}

Async MVC Proccessing: DeferredResult(延期された結果)

@RequestMapping(value = "/orders", method = POST )
@ResponseBody
public DeferredResult quotes() {
  DeferredResult deferredResult = new DeferredResult();
  // deferredResultにQueueやMapをaddする
  return deferredResult;
}
// 他のスレッドで返り値をDeferredResultにsetする
deferredResult.set(data);

Async MVC Proccessing: AsyncTask

@RequestMapping(name = "/upload", method = RequestMethod.POST )
public AsyncTask<Foo> processUpload(MultipartFile file) {
  TaskExecutor asyncTaskExecutor = new AsyncTaskExecutor(...);
  return new AsyncTask<Foo>(
    1000L,                    // timewout
    asyncTaskExecutor,        // thread pool
    new Callable<Foo>(){...}  // thread
  );
}


SpringMVC UTのざっくりした流れ

  1. JUnitコードのランナーとしてSpringJUnit4ClassRunnerを使えば、DIコンテナが勝手にいい感じで起動してくれる。
  2. HttpServletRequest、HttpServletResponseのモックをインスタンス化する。
  3. モックのrequestにテスト対象のURIやパラメータをセット
  4. そのrequestオブジェクトをリクエストハンドラに渡すと疑似リクエストが発生し、コントローラクラスに渡される。
  5. コントローラの該当メソッドが戻り値として返すModelAndViewオブジェクトにレスポンス情報が入っている。
  6. このレスポンス情報をAssertすればよい。

参考:
Spring MVCのススメ
http://d.hatena.ne.jp/ryoasai/20101121/1290317629