BaseErrorController.java
package cn.home1.oss.lib.errorhandle.internal;
import cn.home1.oss.lib.errorhandle.api.HttpHeader;
import cn.home1.oss.lib.errorhandle.api.ResolvedError;
import cn.home1.oss.lib.errorhandle.api.StackTraceIndicator;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* override default BasicErrorController.
*
* {@link org.springframework.boot.autoconfigure.web.BasicErrorController}
*
* <p>
* see: ErrorMvcAutoConfiguration, BasicErrorController
* </p>
*/
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public abstract class BaseErrorController extends org.springframework.boot.autoconfigure.web.AbstractErrorController {
private final ErrorProperties errorProperties;
@Autowired
@Setter
private StackTraceIndicator traceIndicator;
protected BaseErrorController( //
final ExtendedErrorAttributes errorAttributes, //
final ErrorProperties errorProperties //
) {
super(errorAttributes);
Assert.notNull(errorProperties, "AppErrorProperties must not be null");
this.errorProperties = errorProperties;
}
protected ModelAndView errorHtml( //
final HttpServletRequest request, //
final HttpServletResponse response //
) {
final Map<String, Object> errorAttributes = getErrorAttributes( //
request, //
isIncludeStackTrace(request, MediaType.TEXT_HTML) //
);
final ResolvedError resolvedError = ResolvedError.fromErrorAttributes(errorAttributes);
final Integer status = resolvedError.getStatus();// this.getStatus(request)
response.setStatus(status);
// goto WhitelabelErrorViewConfiguration.defaultErrorView if not provided.
final ModelAndView mav = new ModelAndView("error", resolvedError.toErrorAttributes());
mav.addObject(ResolvedError.RESOLVED_ERROR_OBJECT, resolvedError);
return mav;
}
protected ResponseEntity<ResolvedError> error(final HttpServletRequest request, final HttpServletResponse response) {
final Map<String, Object> errorAttributes = getErrorAttributes( //
request, //
isIncludeStackTrace(request, MediaType.ALL) //
);
final ResolvedError body = ResolvedError.fromErrorAttributes(errorAttributes);
final HttpStatus status = body.getHttpStatus();// this.getStatus(request);
copyHeaders(body, response);
return new ResponseEntity<>(body, status);
}
/**
* copy ResolvedError的header到response.
*
* @param source source
* @param response response
*/
private void copyHeaders(final ResolvedError source, final HttpServletResponse response) {
if (source != null && source.getHeaders() != null) {
for (final HttpHeader header : source.getHeaders()) {
for (final String value : header.getValues()) {
response.addHeader(header.getName(), value);
}
}
}
}
protected boolean isIncludeStackTrace(final HttpServletRequest request, final MediaType produces) {
return this.traceIndicator.stackTrace(request, null);
}
@Override
public String getErrorPath() {
return this.errorProperties.getPath();
}
public static class RestfulErrorController extends BaseErrorController {
public RestfulErrorController( //
final ExtendedErrorAttributes errorAttributes, //
final ErrorProperties errorProperties //
) {
super(errorAttributes, errorProperties);
}
@RequestMapping
@ResponseBody
public ResponseEntity<ResolvedError> error(final HttpServletRequest request, final HttpServletResponse response) {
return super.error(request, response);
}
}
public static class TemplateErrorController extends BaseErrorController {
public TemplateErrorController( //
final ExtendedErrorAttributes errorAttributes, //
final ErrorProperties errorProperties //
) {
super(errorAttributes, errorProperties);
}
@RequestMapping
public ModelAndView errorHtml( //
final HttpServletRequest request, //
final HttpServletResponse response //
) {
return super.errorHtml(request, response);
}
}
public static class MixedErrorController extends BaseErrorController {
public MixedErrorController( //
final ExtendedErrorAttributes errorAttributes, //
final ErrorProperties errorProperties //
) {
super(errorAttributes, errorProperties);
}
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml( //
final HttpServletRequest request, //
final HttpServletResponse response //
) {
return super.errorHtml(request, response);
}
@RequestMapping
@ResponseBody
public ResponseEntity<ResolvedError> error(final HttpServletRequest request, final HttpServletResponse response) {
return super.error(request, response);
}
}
}