Bagaimana cara mendapatkan musim semi pengontrol 3.0 untuk memicu 404?
Saya memiliki pengontrol dengan @RequestMapping(value = "/**", method = RequestMethod.GET)
dan untuk beberapa URL mengakses pengontrol, saya ingin wadah muncul dengan 404.
Bagaimana cara mendapatkan musim semi pengontrol 3.0 untuk memicu 404?
Saya memiliki pengontrol dengan @RequestMapping(value = "/**", method = RequestMethod.GET)
dan untuk beberapa URL mengakses pengontrol, saya ingin wadah muncul dengan 404.
Jawaban:
Sejak Spring 3.0 Anda juga dapat melemparkan Pengecualian yang dinyatakan dengan @ResponseStatus
anotasi:
@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
adalah bahwa Anda mendefinisikan sejumlah besar kelas pengecualian yang diketik dengan baik, masing-masing dengan kelasnya sendiri @ResponseStatus
. Dengan begitu, Anda memisahkan kode pengontrol dari detail kode status HTTP.
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
dengan implementasi kosong.
Mulai dari Spring 5.0, Anda tidak perlu membuat pengecualian tambahan:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
Selain itu, Anda dapat membahas beberapa skenario dengan satu, pengecualian bawaan dan Anda memiliki kontrol lebih.
Lihat lebih lanjut:
Tulis ulang tanda tangan metode Anda sehingga diterima HttpServletResponse
sebagai parameter, sehingga Anda dapat meneleponsetStatus(int)
.
setStatus(int)
javadoc menyatakan sebagai berikut: Jika metode ini digunakan untuk mengatur kode kesalahan, maka mekanisme halaman kesalahan penampung tidak akan dipicu. Jika ada kesalahan dan penelepon ingin meminta halaman kesalahan yang ditentukan dalam aplikasi web, maka sendError
harus digunakan sebagai gantinya.
Saya ingin menyebutkan bahwa ada pengecualian (tidak hanya) untuk 404 secara default disediakan oleh Spring. Lihat dokumentasi Spring untuk detailnya. Jadi, jika Anda tidak membutuhkan pengecualian Anda sendiri, Anda bisa melakukan ini:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
tidak ada penanganan permintaan dari sudut pandang saya. Apakah menurut Anda lebih baik / bersih menggunakan Pengecualian Anda sendiri yang dijelaskan dengan @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
Sejak Spring 3.0.2 Anda dapat mengembalikan ResponseEntity <T> sebagai hasil dari metode pengontrol:
@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> lebih fleksibel daripada penjelasan @ResponseBody - lihat pertanyaan lain )
Anda dapat menggunakan @ControllerAdvice untuk menangani Pengecualian Anda, Perilaku default kelas penjelasan @ControllerAdvice akan membantu semua Pengendali yang dikenal.
sehingga akan dipanggil ketika Kontroler yang Anda miliki memiliki 404 kesalahan.
seperti berikut ini:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
dan petakan kesalahan respons 404 ini di web.xml Anda, seperti berikut ini:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
Semoga Itu Membantu.
Jika metode pengontrol Anda untuk sesuatu seperti penanganan file maka ResponseEntity
sangat berguna:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
Meskipun jawaban yang ditandai sudah benar, ada cara untuk mencapainya tanpa kecuali. Layanan ini mengembalikan Optional<T>
objek yang dicari dan ini dipetakan ke HttpStatus.OK
jika ditemukan dan ke 404 jika kosong.
@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);
}
}
Saya sarankan untuk melempar HttpClientErrorException , seperti ini
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
Anda harus ingat bahwa ini dapat dilakukan hanya sebelum sesuatu ditulis ke servlet output stream.
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
Ini agak terlambat, tetapi jika Anda menggunakan Spring Data REST maka sudah ada org.springframework.data.rest.webmvc.ResourceNotFoundException
Ini juga menggunakan @ResponseStatus
anotasi. Tidak perlu lagi membuat pengecualian runtime khusus.
Juga jika Anda ingin mengembalikan status 404 dari pengontrol Anda, Anda hanya perlu melakukan ini
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
Dengan melakukan ini, Anda akan menerima kesalahan 404 jika Anda ingin mengembalikan 404 dari controller Anda.
Cukup Anda dapat menggunakan web.xml untuk menambahkan kode kesalahan dan 404 halaman kesalahan. Tetapi pastikan halaman kesalahan 404 tidak boleh ditemukan di bawah WEB-INF.
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
Ini adalah cara paling sederhana untuk melakukannya tetapi ini memiliki beberapa keterbatasan. Misalkan jika Anda ingin menambahkan gaya yang sama untuk halaman ini yang Anda tambahkan halaman lain. Dengan cara ini Anda tidak bisa melakukan itu. Anda harus menggunakan@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
dari kode pengontrol. Sekarang dari luar responnya tidak berbeda dengan 404 normal yang tidak mengenai controller apa pun.
Konfigurasikan web.xml dengan pengaturan
<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>
Buat pengontrol baru
/**
* 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;
}
}
Karena itu selalu baik untuk memiliki setidaknya sepuluh cara melakukan hal yang sama:
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);
}
}