Spring MVC【六】异常处理&请求转发与重定向

目录

前言

一、Controller类层级异常处理:@ExceptionHandler

二、全局的异常处理

1.@ControllerAdvice

2.XML配置异常处理

3.自定义全局异常处理器

三、Spring MVC的请求转发与重定向

1.返回String方式

2.返回ModelAndView类型

3.使用request和response对象


前言

在Web项目中,未处理的异常返回到前端的错误信息是状态码500的内部服务器错误。如下请求映射方法中的处理就会给前端返回一个500的错误:

@RequestMapping("errorHandler")
@ResponseBody
public void errorTest() {
    int i = 1 / 0;
}

以上的错误显示对于终端用户来说无法识别,很不友好。在一般的Web项目中的处理方式是通过try catch捕捉异常后转到自定义的错误页面。Spring MVC提供了更优雅的方式来处理异常,可以在Controller类层级进行处理,也可以在整个应用中进行全局的处理。

一、Controller类层级异常处理:@ExceptionHandler

@ExceptionHandler注解在某个Controller类的方法中使用时,用于处理该控制类中的处理器方法出现异常时的情况。使用起来也很简单,如下:

@ExceptionHandler
public ModelAndView exceptionHandler(Exception ex) {
    ModelAndView mv = new ModelAndView("error");
    mv.addObject("exception", ex);
    return mv;
}

@ExceptionHandler由ExceptionHandlerExceptionResolver处理器进行处理,这个处理是在DispatcherServlet中默认创建的。@ExceptionHandler默认会处理所有的异常,也可以指定处理指定类型的异常,例如:

@ExceptionHandler({ ArithmeticException.class })
//如果出现其他异常则不会走该注解的方法

@ExceptionHandler只能对当前Controller类的异常进行处理,如果整个应用的Controller异常需要统一处理。就需要在所有Controller中进行定义。虽然可以通过控制器基类的方式来解决这个问题,但这样Controller的定义会出现依赖,而且比较麻烦,此外还有可能存在有的Controller无法继承的状况。比较好的解决方式是使用全局的异常处理配置方式。

二、全局的异常处理

1.@ControllerAdvice

控制器切面注解(@ControllerAdvice)用在类中时,该注解可以作为全局的异常处理类,在类中用@ExceptionHandler注解的方法可以处理所有Controller发生的异常。示例如下:

@ControllerAdvice // 控制器切面注解
public class MyControllerAdvice {

	@ExceptionHandler(Exception.class)
	public ModelAndView exceptionHandler(Exception ex) { // 异常处理方法
		ModelAndView mv = new ModelAndView();
		mv.addObject("exception", ex);
		return mv;
	}
}

在实际开发中,@ControllerAdvice注解类中有多个@ExceptionHandler注解的方法,对应处理不同类型的异常处理。@ControllerAdvice是控制器的切面注解,内部使用的是AOP技术。

2.XML配置异常处理

除了使用注解之外,也可以在XML配置文件中配置SimpleMappingExceptionResolver类型的异常处理器Bean。如下:

<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="defaultErrorView">	<!-- 异常处理视图名 -->
        <value>error</value>
    </property>
    <property name="defaultStatusCode">	<!-- 异常状态码 -->
        <value>500</value>
    </property>
    <property name="warnLogCategory">	<!-- 日志分类 -->
        <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>
    </property>
    <!--异常处理页面用来获取异常信息的变量名,默认为exception-->
    <property name="exceptionAttribute" value="ex"/>
</bean>

3.自定义全局异常处理器

实现Spring的异常处理接口HandlerExceptionResolver自定义全局异常处理器。

public class MyExceptionResolver implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		ModelAndView mv = new ModelAndView();
		if (ex instanceof MyException) {
			MyException myException = (MyException) ex;
			// 处理特殊的异常……
		} else {
			// 其他异常均使用相同的处理方法
			mv.addObject("exception", ex);
			mv.setViewName("error");
		}
		return mv;
	}

}

然后需要在配置文件中配置该Bean

<bean class="com.mec.springmvc.model.MyExceptionResolver"></bean>

三、Spring MVC的请求转发与重定向

请求和重定向都是Web中资源跳转的方式,只不过请求的转发是用户只发起了一次请求,它是服务器从一个资源跳转到另外一个资源,request对象还是原来的没有变,浏览器地址栏不发生变化。重定向是浏览器发起一次请求,服务器给浏览器回馈一个重定向的资源地址,浏览器对这个回馈的地址发起一个新的请求,故重定向相当于是浏览器发起了两个请求。在Spring MVC中有如下几种方式来实现请求的转发与重定向。

1.返回String方式

请求映射方法返回String类型,这种方式有个前提条件就是,当前的的Controller类不能被@RestController注解,还有请求映射方法不能被@ResponseBody注解,这都会被Spring MVC认为你想返回一个JSON字符串。

进行请求的转发与重定向时可以利用forwardredirect实现,如下:

@RequestMapping("/toforward01")    
public String toForward01() {
    return "forward:/toforward02";
}

@RequestMapping("/toforward02")
public String toForward02() {
    return "forward:/WEB-INF/hello.jsp";
}

上述两个方法,当浏览器访问/toforward01,则请求先被转发到/toforward02处理,再由/toforward02转发到WEB-INF目录下的hello.jsp中。

但是由于我已经配置了视图解析器,视图解析器默认处理的就是请求的转发,配置如下:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 视图前缀 -->
    <property name="prefix" value="/WEB-INF/"></property>
    <!-- 视图后缀 -->
    <property name="suffix" value=".jsp"></property>
</bean>	

故在toForward02()方法中可以直接返回视图名称(hello),Spring MVC会自行加上配置的前缀和后缀,将请求转发至该视图,修改后的方法如下:

@RequestMapping("/toforward02")
public String toForward02() {    
    return "hello";
}

对于请求的重定向,可以使用redirect来实现,如下将请求重定向至page.html页面:

@RequestMapping("/toRedirect")
public String toRedirect() {
    return "redirect:/html/page.html";
}

对于请求的重定向需要注意的是:

  • 不能重定向至WEB-INF目录下的资源,因为重定向相当于浏览器发起了两次请求,第二次请求的就是重定向的location,浏览器是不能直接访问WEB-INF下的资源的,所以如果直接重定向至WEB-INF下的资源,相当于浏览器直接访问该资源,则会返回404错误。
  • 即使配置了视图解析器,"redirect"也不能省略,这不是请求的转发,视图解析器默认是对请求转发的处理,这一点根据地址栏变化就可以看出来。

2.返回ModelAndView类型

该方式与返回String的方式差不多,这两个原理是一样的,返回String在框架内部也会解析为ModelAndView类型,将该String作为视图名。如下:

@RequestMapping("/toforward01")
public ModelAndView toForward01() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("forward:/toforward02");
    return mv;
}

@RequestMapping("/toforward02")
public ModelAndView toForward02() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("hello");
    return mv;
}

@RequestMapping("/toRedirect")
public ModelAndView toRedirect() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("redirect:/index.jsp");
    return mv;
}

3.使用request和response对象

请求映射方法入参可以携带HttpServletRequest和HttpServletResponse对象,那么利用这两个对象使用原生方式也可以进行请求的转发与重定向,如下:

@RequestMapping("/toforward01")
public void toForward01(HttpServletRequest request, HttpServletResponse response) throws Exception {
    request.getRequestDispatcher("/toforward02").forward(request, response);
}

@RequestMapping("/toforward02")
public void toForward02(HttpServletRequest request, HttpServletResponse response) throws Exception {
    request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
}

@RequestMapping("/toRedirect")
public void toRedirect(HttpServletResponse response) throws IOException {
    response.sendRedirect("html/page.html");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 中,可以使用重定向和转发来进行请求的跳转。下面是设定重定向和转发的几种方式: 1. 重定向: - 使用 `RedirectView` 类:可以在控制器方法中返回一个 `RedirectView` 对象,设置重定向的目标 URL。 - 使用 `RedirectAttributes` 类:可以在控制器方法中将重定向的目标 URL 添加到 `RedirectAttributes` 对象中,并使用 `redirect:` 前缀来指示重定向。 2. 转发: - 使用 `ModelAndView` 类:可以在控制器方法中返回一个 `ModelAndView` 对象,设置转发的视图名称。 - 使用 `forward:` 前缀:可以在控制器方法中使用 `return "forward:/path"` 的方式来指示转发到指定的路径。 下面是一个示例,展示如何在控制器方法中设定重定向和转发: ```java @Controller public class MyController { @GetMapping("/redirect") public RedirectView redirectToUrl() { RedirectView redirectView = new RedirectView(); redirectView.setUrl("https://www.example.com"); return redirectView; } @GetMapping("/redirectWithAttributes") public String redirectWithAttributes(RedirectAttributes attributes) { attributes.addAttribute("param", "value"); return "redirect:/targetUrl"; } @GetMapping("/forward") public ModelAndView forwardToView() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("forward:/targetView"); return modelAndView; } } ``` 上述代码中,`/redirect` 路径的请求会被重定向到 `https://www.example.com`,`/redirectWithAttributes` 路径的请求会带着参数重定向到 `/targetUrl`,`/forward` 路径的请求会被转发到 `targetView` 视图。 需要注意的是,在设定重定向和转发时,可以使用绝对路径或相对路径,具体根据需求来确定。同时,还可以在路径中使用占位符和路径参数来实现动态的跳转。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值