簡介###
客戶端兩個,針對兩類用戶辙浑,渲染的H5頁面各有不同激涤,報錯處理頁面也存在區(qū)別;將所有服務放置同一個Web項目例衍,需要在報錯的時候指向不同的錯誤頁面昔期;
最開始的想法是通過區(qū)分服務路徑,最終證明此方法可行佛玄,如下是實現(xiàn)步驟硼一。
啟動類定義EmbeddedServletContainerCustomizer對象###
這里定義的error page 路徑與MainsiteErrorController相關聯(lián);
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(){
return new EmbeddedServletContainerCustomizer(){
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"));
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"));
container.addErrorPages(new ErrorPage(java.lang.Throwable.class,"/error/500"));
}
};
}
實現(xiàn)ErrorController接口###
@Controller
@RequestMapping(value = "error")
@EnableConfigurationProperties({ ServerProperties.class })
public class MainsiteErrorController implements ErrorController {
private static final String REQUEST_PATH_KEY = "path";
private static final Logger logger = LoggerFactory.getLogger(MainsiteErrorController.class);
private ErrorAttributes errorAttributes;
@Autowired
private ServerProperties serverProperties;
/**
* 初始化ExceptionController
*
* @param errorAttributes
*/
@Autowired
public MainsiteErrorController(ErrorAttributes errorAttributes) {
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
this.errorAttributes = errorAttributes;
}
/**
* 定義404的ModelAndView
*
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html", value = "404")
public ModelAndView errorHtml404(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
return new ModelAndView(this.getTerminalErrorPageByRequestURL(model, "404"), model);
}
/**
* 定義404的JSON數(shù)據(jù)
*
* @param request
* @return
*/
@RequestMapping(value = "404")
@ResponseBody
public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
/**
* 定義500的ModelAndView
*
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html", value = "500")
public ModelAndView errorHtml500(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
return new ModelAndView(this.getTerminalErrorPageByRequestURL(model, "500"), model);
}
/**
* 定義500的錯誤JSON信息
*
* @param request
* @return
*/
@RequestMapping(value = "500")
@ResponseBody
public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
}
/**
* Determine if the stacktrace attribute should be included.
*
* @param request
* the source request
* @param produces
* the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace();
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
return true;
}
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
return getTraceParameter(request);
}
return false;
}
/**
* 獲取錯誤的信息
*
* @param request
* @param includeStackTrace
* @return
*/
private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
return this.errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
}
/**
* 是否包含trace
*
* @param request
* @return
*/
private boolean getTraceParameter(HttpServletRequest request) {
String parameter = request.getParameter("trace");
if (parameter == null) {
return false;
}
return !"false".equals(parameter.toLowerCase());
}
/**
* 獲取錯誤編碼
*
* @param request
* @return
*/
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception ex) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
private String getTerminalErrorPageByRequestURL(Map<String, Object> model, String errorCode) {
String path = ((String) model.get(REQUEST_PATH_KEY));
String terminalErrorPage = path.startsWith(GenericConstants.STUDENT_TERMINAL_TYPE)
? GenericConstants.STUDENT_TERMINAL_TYPE.concat("/").concat(errorCode) : errorCode;
terminalErrorPage = "errorpage/" + terminalErrorPage;
logger.debug("errorPage -> {}", terminalErrorPage);
return terminalErrorPage;
}
/**
* 實現(xiàn)錯誤路徑,暫時無用
*
* @see ExceptionMvcAutoConfiguration#containerCustomizer()
* @return
*/
@Override
public String getErrorPath() {
return "";
}
}
其中較為關鍵的方法是getTerminalErrorPageByRequestURL方法梦抢,該方法會根據(jù)請求的path找到各客戶端請求前綴(通過前綴區(qū)分提供給不同客戶端的服務般贼,以此報錯時指向不同的錯誤頁面)
這是基于Thymeleaf+SpringBoot實現(xiàn)的網(wǎng)站http://www.hqast.com/