Spring Boot项目跳转到/error接口,比如遇到404等HTTP状态码

本文详细解析了SpringBoot应用中,当出现404、500等错误时,如何默认跳转到BasicErrorController的/error接口。讲解了在Tomcat容器中错误处理的流程,并指出可以通过继承BasicErrorController或实现ErrorController接口来自定义错误信息。同时,指出了ErrorController和@ControllerAdvice在异常处理上的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot、SpringCloud、SpringMVC项目,使用tomcat容器,在404、500等错误之后,默认跳转到了BasicErrorController类的/error接口。

BasicErrorController.java

 

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {

	private final ErrorProperties errorProperties;

	@RequestMapping
	@ResponseBody
	public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
		Map<String, Object> body = getErrorAttributes(request,
				isIncludeStackTrace(request, MediaType.ALL));
		HttpStatus status = getStatus(request);
		return new ResponseEntity<>(body, status);
	}

	@RequestMapping(produces = "text/html")
	public ModelAndView errorHtml(HttpServletRequest request,
			HttpServletResponse response) {
		HttpStatus status = getStatus(request);
		Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
				request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
		response.setStatus(status.value());
		ModelAndView modelAndView = resolveErrorView(request, response, status, model);
		return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
	}

    // 省略其余方法
}

如果请求头里的accept如果是text/html,那么走errorHtml()方法。

如果不是,则走error()方法。

具体是在哪里设置跳转到${server.error.path:${error.path:/error}} 这个请求路径的,不同的容器不大一样。

如果是tomcat,那么是在StandardHostValve.java的status方法里设置的:

    /**
     * Handle the HTTP status code (and corresponding message) generated
     * while processing the specified Request to produce the specified
     * Response.  Any exceptions that occur during generation of the error
     * report are logged and swallowed.
     *
     * @param request The request being processed
     * @param response The response being generated
     */
    private void status(Request request, Response response) {

如果根据HTTP状态码(比如404)没有找到配置的错误页面,那么使用状态码0来查找配置的错误页面,默认值为/error。

设置完跳转信息之后,通过SpringMVC的DispatcherServlet的doDispatch方法来分发请求,从而将请求转发到了文章开头说到的BasicErrorController里。需要注意的是,转发前和转发后,使用的是同一个线程,可以使用线程局部变量ThreadLocal传递数据,但是最后一定要清除。

实际项目中,可以写一个类来继承BasicErrorController,覆盖error方法,设置自定义的信息,或者直接实现ErrorController接口,比如:   

@Controller
public class MyErrorController extends BasicErrorController {

    private static Log log = LogFactory.getLog(MyErrorController.class);

    public MyErrorController(ServerProperties serverProperties) {
        super(new DefaultErrorAttributes(), serverProperties.getError());
    }

    /**
     * 覆盖默认的Json响应
     */
    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
		// 获取原始的错误信息
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);

        
        Map<String, Object> result = new HashMap<>();
        String code = null;
        String message = null;
        Object data = null;
        
		// 设置自定义的错误信息,或者从ThreadLocal等获取错误信息
		
        result.put("code", code);
        result.put("message", message);
        result.put("data", data);
        cleanAllCache();
        return new ResponseEntity<Map<String, Object>>(result, status);
    }


}

 说到异常,那么很有必要提到SpringBoot的全局异常处理,这个另起一篇文章吧。

说明:

        ErrorController接口可以处理所有的异常,包括未进入控制器(controller)之前的异常

        而注解@ControllerAdvice方式只能处理控制器抛出的异常。此时请求已经进入控制器中。因此无法拦截404、401等错误。

        如果ErrorController和@ControllerAdvice同时存在,那么@ControllerAdvice优先处理,@ControllerAdvice处理不了的才会到ErrorController处理。

备注:

SpringBoot错误处理官方文档:Spring Boot Reference Documentation

Spring Boot项目中,创建登录界面通常涉及到前端UI(HTML, CSS, JavaScript)和后端Java代码的结合。这里简要概述一个基本的登录页面实现步骤: 1. **HTML登录表单**: 前端使用HTML创建一个简单的登录表单,包含用户名(username)输入框和密码(password)输入框,以及提交按钮。示例代码: ```html <!-- login.html --> <form th:action="@{/login}" th:method="post"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username" required /> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password" required /> </div> <button type="submit">Login</button> </form> ``` 2. **Thymeleaf或FreeMarker等模板引擎**: 如果你使用Spring Boot的Thymeleaf作为视图技术,表单会通过Thymeleaf的模板语法与后端交互。 3. **后端Java控制器**: 后端`LoginController.java`可能像这样处理登录请求: ```java import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { @PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password, Model model) { // 检查用户名和密码 boolean isLoggedIn = checkCredentials(username, password); if (isLoggedIn) { return "redirect:/dashboard"; // 登录成功,跳转到主页 } else { model.addAttribute("error", "Invalid credentials"); // 显示错误消息 return "login"; // 重定向回登录页面 } } private boolean checkCredentials(String username, String password) { // 这里只是一个示例,实际应用中从数据库或认证服务验证 return username.equals("admin") && password.equals("password"); } } ``` 4. **Spring Security集成(可选)**: 如果需要更高级的安全管理,你可以集成Spring Security,它可以帮助你处理认证和授权。 相关问题: 1. 如何在Spring Boot中配置Thymeleaf作为默认视图引擎? 2. Spring Security如何进行用户认证? 3. Spring Boot中如何避免SQL注入或XSS攻击?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值