日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

springboot返回modelandview 找不到视图_SpringBoot错误处理机制及原理

發布時間:2024/10/8 javascript 72 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot返回modelandview 找不到视图_SpringBoot错误处理机制及原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SpringBoot錯誤信息處理機制

★ 在一個web項目中,總需要對一些錯誤進行界面或者json數據返回,已實現更好的用戶體驗,SpringBoot中提供了對于錯誤處理的自動配置

ErrorMvcAutoConfiguration這個類存放了所有關于錯誤信息的自動配置。

1. SpringBoot處理錯誤請求的流程

訪問步驟:

  • 首先客戶端訪問了錯誤界面。例:404或者500
  • SpringBoot注冊錯誤請求/error。通過ErrorPageCustomizer組件實現
  • 通過BasicErrorController處理/error,對錯誤信息進行了自適應處理,瀏覽器會響應一個界面,其他端會響應一個json數據
  • 如果響應一個界面,通過DefaultErrorViewResolver類來進行具體的解析。可以通過模板引擎解析也可以解析靜態資源文件,如果兩者都不存在則直接返回默認的錯誤JSON或者錯誤View
  • 通過DefaultErrorAttributes來添加具體的錯誤信息

源代碼

//錯誤信息的自動配置 public class ErrorMvcAutoConfiguration {//響應具體的錯誤信息@Beanpublic DefaultErrorAttributes errorAttributes() {return}//處理錯誤請求@Beanpublic BasicErrorController basicErrorController() {return }//注冊錯誤界面@Beanpublic ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() {return } //注冊錯誤界面,錯誤界面的路徑為/error private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {//服務器基本配置private final ServerProperties properties;public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {//獲取服務器配置中的錯誤路徑/errorErrorPage errorPage = new ErrorPage(this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath()));//注冊錯誤界面errorPageRegistry.addErrorPages(new ErrorPage[]{errorPage});} //this.properties.getError() public class ServerProperties{//錯誤信息的配置文件private final ErrorProperties error = new ErrorProperties(); }//getPath public class ErrorProperties {@Value("${error.path:/error}")private String path = "/error"; //處理/error請求,從配置文件中取出請求的路徑 @RequestMapping({"${server.error.path:${error.path:/error}}"}) public class BasicErrorController extends AbstractErrorController {//瀏覽器行為,通過請求頭來判斷,瀏覽器返回一個視圖@RequestMapping(produces = {"text/html"}public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = this.getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));response.setStatus(status.value());ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);return modelAndView != null ? modelAndView : new ModelAndView("error", model);}//其他客戶端行為處理,返回一個JSON數據@RequestMappingpublic ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {HttpStatus status = this.getStatus(request);if (status == HttpStatus.NO_CONTENT) {return new ResponseEntity(status);} else {Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));return new ResponseEntity(body, status);}} //添加錯誤信息 public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver, Ordered {public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {Map<String, Object> errorAttributes = new LinkedHashMap();errorAttributes.put("timestamp", new Date());this.addStatus(errorAttributes, webRequest);this.addErrorDetails(errorAttributes, webRequest, includeStackTrace);this.addPath(errorAttributes, webRequest);return errorAttributes;}

2. 響應一個視圖

步驟:

  • 客戶端出現錯誤
  • SpringBoot創建錯誤請求/error
  • BasicErrorController處理請求
@RequestMapping(produces = {"text/html"})public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = this.getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));response.setStatus(status.value());//解析錯誤界面,返回一個ModelAndView,調用父類AbstractErrorController的方法ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);return modelAndView != null ? modelAndView : new ModelAndView("error", model);} public abstract class AbstractErrorController{private final List<ErrorViewResolver> errorViewResolvers;protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {Iterator var5 = this.errorViewResolvers.iterator();//遍歷所有的錯誤視圖解析器ModelAndView modelAndView;do {if (!var5.hasNext()) {return null;}ErrorViewResolver resolver = (ErrorViewResolver)var5.next();//調用視圖解析器的方法,modelAndView = resolver.resolveErrorView(request, status, model);} while(modelAndView == null);return modelAndView;} } public interface ErrorViewResolver {ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model); }
  • 處理具體的視圖跳轉
//處理視圖跳轉 public DefaultErrorViewResolver{public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {//將狀態碼作為視圖名稱傳入解析ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);}return modelAndView;} //視圖名稱為error文件夾下的400.html等狀態碼文件private ModelAndView resolve(String viewName, Map<String, Object> model) {String errorViewName = "error/" + viewName;//是否存在模板引擎進行解析TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);//存在則返回解析以后的數據,不存在調用resolveResource方法進行解析return provider != null ? new ModelAndView(errorViewName, model) : this.resolveResource(errorViewName, model);} //如果靜態資源文件中存在,返回靜態文件下的,如果不存在返回SpringBoot默認的private ModelAndView resolveResource(String viewName, Map<String, Object> model) {String[] var3 = this.resourceProperties.getStaticLocations();int var4 = var3.length;for(int var5 = 0; var5 < var4; ++var5) {String location = var3[var5];try {Resource resource = this.applicationContext.getResource(location);resource = resource.createRelative(viewName + ".html");if (resource.exists()) {return new ModelAndView(new DefaultErrorViewResolver.HtmlResourceView(resource), model);}} catch (Exception var8) {}}return null;}

應用:

  • 在模板引擎文件下創建error文件夾,里面放置各種狀態碼的視圖文件,模板引擎會解析
  • 在靜態資源下常見error文件夾,里面放置各種狀態碼的視圖文件,模板引擎不會解析
  • 如果沒有狀態碼文件,則返回springBoot默認界面視圖

3.響應一個json數據

在BasicErrorController處理/error請求的時候不適用瀏覽器默認請求

@RequestMappingpublic ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {HttpStatus status = this.getStatus(request);if (status == HttpStatus.NO_CONTENT) {return new ResponseEntity(status);} else {//調用父類的方法獲取所有的錯誤屬性Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));return new ResponseEntity(body, status);}} 父類方法: protected Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {WebRequest webRequest = new ServletWebRequest(request);//調用ErrorAttributes接口的getErrorAttributes方法,return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace);} 添加錯誤信息 public class DefaultErrorAttributes{public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {Map<String, Object> errorAttributes = new LinkedHashMap();errorAttributes.put("timestamp", new Date());this.addStatus(errorAttributes, webRequest);this.addErrorDetails(errorAttributes, webRequest, includeStackTrace);this.addPath(errorAttributes, webRequest);return errorAttributes;}

返回的json數據有:

  • status
  • error
  • exception
  • message
  • trace
  • path

可以通過模板引擎獲取這些值

4.自定義異常返回自定義的異常數據

4.1@ControllerAdvice注解

★ SpringMVC提供的注解,可以用來定義全局異常,全局數據綁定,全局數據預處理

@ControllerAdivice定義全局的異常處理

  • 通過@ExceptionHandler(XXXException.class)執行該方法需要處理什么異常,然后返回什么數據或者視圖
//json數據返回 ,處理自定義用戶不存在異常@ResponseBody@ExceptionHandler(UserException.class)public Map<String,String> userExceptionMethod(UserException us){Map<String,String> map = new HashMap<>();map.put("message",us.getMessage());return map ;}

@ControllerAdvice定義全局數據

  • 通過@ModelAttribute(Name="key")定義全局數據的key
  • 默認方法的返回值的名稱作為鍵
  • 在Controller中通過Model獲取對應的key的值
@ControllerAdvice public MyConfig{@ModelAttribute(name = "key")public Map<String,String> defineAttr(){Map<String,String> map = new HashMap<>();map.put("message","幻聽");map.put("update","許嵩");return map ;}@Controller public UserController{@GetMapping("/hello")public Map<String, Object> hello(Model model){Map<String, Object> asMap = model.asMap();System.out.println(asMap);//{key={message='上山',update='左手一式太極拳'}}return asMap ;} }

@ControllerAdvice處理預處理數據(當需要添加的實體,屬性名字相同的時候)

  • 在Controller的參數中添加ModelAttribute作為屬性賦值的前綴
  • 在ControllerAdvice修飾的類中,結合InitBinder來綁定對應的屬性(該屬性為ModelAttribite的value值
  • 在@InitBinder修飾的方法中通過WebDataBinder添加默認的前綴
@Getter@Setter public class Book {private String name ;private int age ;@Getter@Setter public class Music {private String name ;private String author ;//這種方式的處理,spring無法判斷Name屬性給哪個bean賦值,所以需要通過別名的方式來進行賦值 @PostMapping("book")public String book(Book book , Music music){System.out.println(book);System.out.println(music);return "404" ;}//使用以下的方式 @PostMapping("/book")public String book(@ModelAttribute("b")Book book , @ModelAttribute("m")Music music){System.out.println(book);System.out.println(music);return "404" ;}public MyCOnfiguration{@InitBinder("b")public void b(WebDataBinder webDataBinder){webDataBinder.setFieldDefaultPrefix("b.");}@InitBinder("m")public void m(WebDataBinder webDataBinder){webDataBinder.setFieldDefaultPrefix("m.");} }

4.2自定義異常JSON

瀏覽器和其他客戶端都只能獲取json數據

@ControllerAdvice public class MyExceptionHandler {//處理UserException異常@ResponseBody@ExceptionHandler(UserException.class)public Map<String,String> userExceptionMethod(UserException us){Map<String,String> map = new HashMap<>();map.put("message",us.getMessage());map.put("status","500");return map ;}

4.2自定義異常返回一個視圖,擁有自適應效果

@ExceptionHandler(UserException.class)public String allException(UserException e,HttpServletRequest request){Map<String,String> map = new HashMap<>();map.put("message",e.getMessage());map.put("load","下山");request.setAttribute("myMessage",map);//設置狀態碼,SpringBoot通過java.servlet.error.status_code來設置狀態碼request.setAttribute("javax.servlet.error.status_code",400);return "forward:/error" ;}

當拋出UserException異常的時候,來到這個異常處理器,給這個請求中添加了數據,再轉發到這個error請求中,交給ErrorPageCustomizer處理,由于設置了請求狀態碼400則返回的視圖為400或4XX視圖,或者直接返回一個JSON數據

{"timestamp": "2020-02-19T04:17:43.394+0000","status": 400,"error": "Bad Request","message": "用戶名不存在異常","path": "/crud/user/login" }

  • 不足:JSON數據中沒有顯示我們自己定義的錯誤信息

4.3自定義錯誤信息

★ 前面提到SpringBoot對錯誤信息的定義存在于DefaultErrorAttributes類的getErrorAttributes中,我們可以直接繼承這個類,或者實現ErrorAttributes接口,然后將我們自己實現的錯誤處理器添加到容器中即可。

繼承DefaultErrorAttributes和實現ErrorAttributes接口的區別是,繼承以后仍然可以使用SpringBoot默認的錯誤信息,我們僅僅對該錯誤信息進行了增強;實現了ErrorAttributes接口,完全自定義錯誤信息

  • 實現ErrorAttributes接口
public class MyErrorHandler implements ErrorAttributes {public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {Map<String, Object> errorAttributes = new LinkedHashMap();errorAttributes.put("timestamp", new Date());errorAttributes.put("status",500);errorAttributes.put("message","用戶不存在異常");return errorAttributes;}@Overridepublic Throwable getError(WebRequest webRequest) {return null;}
  • 繼承DefaultErrorAttributes的方法
public class MyErrorHandler extends DefaultErrorAttributes {public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {//調用父類方法,直接在默認錯誤信息的基礎上添加Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest,includeStackTrace);errorAttributes.put("timestamp", new Date());errorAttributes.put("message","用戶不存在異常");return errorAttributes;}}
  • 將定義的錯誤信息器添加到容器中
    • 通過@Component組件直接將MyErrorHandler組件添加到容器中
    • 通過@Bean在配置類中將組件添加到容器中
@Beanpublic DefaultErrorAttributes getErrorHandler(){return new MyErrorHandler();}
  • 下面解決上一節中沒有出現我們自定義的異常信息
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest,includeStackTrace);errorAttributes.put("timestamp", new Date());errorAttributes.put("message","用戶不存在異常");//指定從哪個作用域中取值webRequest.getAttribute("myMessage", RequestAttributes.SCOPE_REQUEST);return errorAttributes;

將在異常處理器中定義的錯誤信息取出,然后添加到錯誤信息中。

總結

以上是生活随笔為你收集整理的springboot返回modelandview 找不到视图_SpringBoot错误处理机制及原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。