回答:
Spring 3.0以降では、@ResponseStatus
アノテーション付きで宣言された例外をスローすることもできます。
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
@Controller
public class SomeController {
@RequestMapping.....
public void handleCall() {
if (isFound()) {
// whatever
}
else {
throw new ResourceNotFoundException();
}
}
}
@ResponseStatus
、強く型付けされた、名前の付いた例外クラスの束全体を定義し、それぞれが独自のを持つことだと思います@ResponseStatus
。このようにして、コントローラーコードをHTTPステータスコードの詳細から切り離します。
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
は、空の実装でオーバーライドすることをお勧めします。
Spring 5.0以降では、必ずしも追加の例外を作成する必要はありません。
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
また、1つの組み込みの例外で複数のシナリオをカバーでき、より詳細に制御できます。
続きを見る:
メソッドのシグニチャーをHttpServletResponse
パラメーターとして受け入れるように書き換えて、呼び出しできるようsetStatus(int)
にします。
setStatus(int)
javadocは次のように述べています。このメソッドを使用してエラーコードを設定すると、コンテナのエラーページメカニズムはトリガーされません。エラーがあり、呼び出し元がWebアプリケーションで定義されたエラーページを呼び出したい場合は、sendError
代わりにを使用する必要があります。
Springによってデフォルトで提供される404には(だけでなく)例外があることを述べておきます。詳細については、Springのドキュメントを参照してください。したがって、独自の例外が必要ない場合は、次のようにするだけです。
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
、私の観点からはリクエスト処理はありません。注釈が付けられた独自の例外を使用する方が良い/よりクリーンだと思います@ResponseStatus(value = HttpStatus.NOT_FOUND)
か?
Spring 3.0.2以降、コントローラのメソッドの結果としてResponseEntity <T>を返すことができます。
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
if (isFound()) {
// do what you want
return new ResponseEntity<>(HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
(ResponseEntity <T>は@ResponseBodyアノテーションよりも柔軟です- 別の質問を参照してください)
@ControllerAdviceを使用してExceptionsを処理できます。@ ControllerAdvice注釈付きクラスのデフォルトの動作は、すべての既知のコントローラーを支援します。
そのため、コントローラが404エラーをスローしたときに呼び出されます。
次のように:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
次のように、この404レスポンスエラーをweb.xmlにマッピングします。
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
お役に立てれば幸いです。
マークされた答えは正しいですが、例外なくこれを達成する方法があります。サービスはOptional<T>
検索されたオブジェクトを返し、これがHttpStatus.OK
見つかった場合はマップされ、空の場合は404にマップされます。
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
return service.find(param).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
@Service
public class Service{
public Optional<Object> find(String param){
if(!found()){
return Optional.empty();
}
...
return Optional.of(data);
}
}
このようにHttpClientErrorExceptionをスローすることをお勧めします
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
これは、サーブレット出力ストリームに何かが書き込まれる前にのみ実行できることを覚えておく必要があります。
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
これは少し遅れますが、Spring Data RESTを使用している場合は、すでに存在します。org.springframework.data.rest.webmvc.ResourceNotFoundException
これも@ResponseStatus
アノテーションを使用します。カスタムランタイム例外を作成する必要はもうありません。
また、コントローラから404ステータスを返したい場合は、これを行うだけです
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
これを行うと、コントローラーから404を返したい場合に404エラーを受け取ります。
単純に、web.xmlを使用してエラーコードと404エラーページを追加できます。ただし、404エラーページがWEB-INFの下に配置されていないことを確認してください。
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
これが最も簡単な方法ですが、これにはいくつかの制限があります。このページに他のページを追加したのと同じスタイルを追加したいとします。このようにして、それを行うことはできません。あなたは使用する必要があります@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
、コントローラーコードからそれを考慮します。これで、外部からの応答は、どのコントローラーにもヒットしなかった通常の404と何ら変わりません。
設定でweb.xmlを構成する
<error-page>
<error-code>500</error-code>
<location>/error/500</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
新しいコントローラーを作成する
/**
* Error Controller. handles the calls for 404, 500 and 401 HTTP Status codes.
*/
@Controller
@RequestMapping(value = ErrorController.ERROR_URL, produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public class ErrorController {
/**
* The constant ERROR_URL.
*/
public static final String ERROR_URL = "/error";
/**
* The constant TILE_ERROR.
*/
public static final String TILE_ERROR = "error.page";
/**
* Page Not Found.
*
* @return Home Page
*/
@RequestMapping(value = "/404", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView notFound() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current.");
return model;
}
/**
* Error page.
*
* @return the model and view
*/
@RequestMapping(value = "/500", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView errorPage() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current, due to the recent site redesign.");
return model;
}
}
同じことを行う少なくとも10の方法があることは常に良いことだからです。
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Something {
@RequestMapping("/path")
public ModelAndView somethingPath() {
return new ModelAndView("/", HttpStatus.NOT_FOUND);
}
}