springMVC中404错误的拦截

SpringMVC统一错误处理

该功能可以直接通过SpringMVC的@RestControllerAdvice注解搭配@ExceptionHandler来处理。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RestControllerAdvice
public class ExceptionResponseAdvice {

@ExceptionHandler(IndexOutOfBoundsException.class)
public Exception handleException(Exception exception){
System.out.println("数组越界错误!");
//handle Exception
return exception;
}

@ExceptionHandler(ClassNotFoundException.class)
public Exception handleException(Exception exception){
System.out.println("类未找到错判!");
//handle Exception
return exception;
}

@ExceptionHandler(Throwable.class)
public Exception handleException(Exception exception){
System.out.println("兜底所有错误!");
//handle Exception
return exception;
}
}

springMVC统一返回结构

同样使用@RestControllerAdvice可以用来统一数据的返回结构。不过我们需要实现ResponseBodyAdvice接口。才能劫持方法返回的数据,然后进行重写其中的方法。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@RestControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {

ObjectMapper mapper = new ObjectMapper();

@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}

@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//处理返回值是String的状况
//处理字符串类型数据
if(o instanceof String){
try {
return mapper.writeValueAsString(Result.data(o));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}

// 处理错误
if(o instanceof Exception){
return Result.getResult((Exception) o);
}

return o instanceof Result ? o : Result.data(o);
}
}

这里还有一个坑,就是json化和String类型的冲突,即如果Controller返回的是一个String。不加这一句的话会报错:

1
class priv.mw.utils.Result cannot be cast to class java.lang.String (priv.mw.utils.Result is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @5049b1e5; java.lang.String is in module java.base of loader 'bootstrap')

即没办法将Result类型转化为String。其本质原因在于由于返回的是String,所以会匹配到StringHttpMessageConverter,因为他在所有Converter的前面。但由于我们在切面中将类型改成了Result,所以就会报错。

但实际上我们需要的是MappingJackson2HttpMessageConverter

所以目前的解决办法有两种:

  • 在转换之前就将String转化为JSON字符串。
  • MappingJackson2HttpMessageConverter 放在所有converter的首位。

第一种就是就是上面的写法。

第二种可以通过配置来实现:

  • XML方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <mvc:annotation-driven>
    <mvc:message-converters>
    <!-- 将MappingJackson2HttpMessageConverter移到前面,处理ResponseBodyAdvice的String异常的问题-->
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="defaultCharset" value="UTF-8"/>
    </bean>
    </mvc:message-converters>
    </mvc:annotation-driven>
    • Class方式

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      import org.springframework.context.annotation.Configuration;
      import org.springframework.http.converter.HttpMessageConverter;
      import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

      import java.util.List;

      @Configuration
      public class WebConfiguration implements WebMvcConfigurer {

      @Override
      public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
      converters.add(0, new MappingJackson2HttpMessageConverter());
      }
      }

还有一点值得注意的是:实际上错误处理是在ResponseBodyAdvice中,即统一结构返回中来处理。因为实际上我们需要统一返回结构,对于错误,需要判断错误类型来返回对应的数据。所以在这里处理是更加方便的。

漏掉的404

虽然上面的做到了统一错误处理,但是404地址错误仍然没办法被劫持到。

目前的做法是,实现一个能够劫持所有请求地址的controller,因为其在springMVC中,泛匹配优先级最低。所以可以这样实现。

1
2
3
4
5
6
7
@RestController
public class Error {
@RequestMapping("/**")
public String NotFound() throws ClientException {
throw new ClientException("请求地址出错!");
}
}

后期看能不能有更优的处理方法。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :