Results demonstrate

Let’s take a look at Springboot’s default

Browser access

Client access

Highlight!!

But the vast majority of the company’s code is not adaptive processing, a large part of the reason is that you search the Internet for Springboot global exception handling, is to find such a piece of code!

@ControllerAdvice
public class MyControllerAdvice {
 
 
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    publicResponseEntity<? > errorHandler(Exception ex) {// Handle exceptions}}Copy the code

It is highly recommended that you use your own search engine first, and then take a look at your own company code to see if it looks like this before you go down.

Of course, a lot of you might say, well, we already have a pretty good convention with the client, that there’s only GOING to be JSON, there’s not going to be a scene that returns HTML. So, it’s actually ok not to do this adaptation. But if you are an infrastructure student, you must do this function, because you are connected with the business department of the whole company, Springboot can do, you do similar basic components, if the function is worse than Springboot, how do you let the business students think?

Of course, for most of you, it’s ok not to do it.

But you’re missing out on a great learning opportunity. What learning opportunities? Because a lot of students usually say that the interview makes the rocket, the work encountered do not understand the question baidu or Google a good. This one, however, is not so searchable. That is to say, the vast majority of people are oriented to search engine programming, when the search engine can not solve the problem, is to reflect your value, cherish.

I don’t think it is important to do this function or not. This precious opportunity to practice problem-solving ability is really rare. After all, it is true that most functions can be solved simply by searching or asking in the communication group.

Adaptive principle

Many students said, since the search, the decisive wave of source code to go. However, Springboot source so much, where to start? That’s the point! At this time, we can go through the official documents.

27.1.9 Error Handling

Spring Boot provides an /error mapping by default that handles all errors in a sensible way, And it is registered as a ‘global’ error page in the servlet container. For machine clients it will produce a JSON response with details of the error, The HTTP status and the exception message. For browser clients there is a ‘whitelabel’ error view that renders the same Data in HTML format (to customize it just add a View that high similarity to ‘error’). To replace the default behaviour completely you can implement ErrorController and register a bean definition of that type, or simply add a bean of type ErrorAttributes to use the existing mechanism but replace the contents.

Some students said, can’t read English? Let me pick five key words for you. They are all primary school words. As long as you can graduate from primary school, I think you can understand them.

clients JSON browser HTML ErrorController

Fat toward small voice force force: here specially emphasize, do not say to read official document is the optimal solution to the problem. Still the same words, old drivers are to see the dishes to eat, there are many routines to solve the problem, time is limited, I will not list all routines one by one (in fact, afraid of routines all tell you, you take off!) Just get to the point.

From the documents and English words in primary school, we targeted ErrorController and showed you the key code

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

	@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);
	}

	@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 newResponseEntity<Map<String, Object>>(body, status); }}Copy the code

From here, we can roughly guess that to do an adaptive global exception handling, the theory goes like this.

@ControllerAdvice
public class MyExceptionHandler  {

    @ExceptionHandler(Exception.class)
    public String handleExceptionHtml(Exception e, HttpServletRequest httpServletRequest) {
        // Do your own processing here, for example
        httpServletRequest.setAttribute("Welcome to follow wechat official account"."The fat." ");
        return "forward:/error"; }}Copy the code

Sure enough, a wave was tested and found to be true. Of course, specific how to define this error interface and so on, a search on the Internet, so these are not the focus of fat. So this adaptive global anomaly seems to be delectable?

Have a problem

Now that we know how adaptive global exception handling works, it’s easy to figure out how to bug it. For example, if you have an exception in your interceptor.

@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
                throw new RuntimeException("Here we pretend to throw a fat exception.");
                //return true;
            }

            @Override
            public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}@Override
            public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}}); }}Copy the code

StackOverflowError.

Because the interceptor gets an exception, it falls into your global exception handler, and then your global exception handler, it goes forward again, it goes into the interceptor, and then it loops.

So how to solve this problem? We are going to see the trick, at this time, I am going to demonstrate several common not elegant, but usually we are easy to do writing method.

Write the configuration to death

registry.addInterceptor(new HandlerInterceptor() {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        throw new RuntimeException("Here we pretend to throw a fat exception.");
        //return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}@Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}).excludePathPatterns("/error");
Copy the code

We learn from

@RequestMapping("${server.error.path:${error.path:/error}}")
Copy the code

Error. Path is configurable, and many of you are using excludePathPatterns with /error, so it’s ok to keep using the default. Once you configure error.

Hidden rules

This unspoken rule problem is the most common problem most students write code. If you think about it, your adaptive global exception is resolved, but the effect is that every interceptor has a configuration like excludePathPatterns. For the user, this is a kind of unspoken rule, which must be configured with some configuration. Moreover, for the new colleague, he does not know this kind of unspoken rule at all. Once the code of the unspoken rule is many, it is difficult to maintain later.

Expand the thinking

So what does unspoken code look like?

Of course, most of the time, we have to hide the rules! For example, big data students require that the logs sent must have an application name. For the business side, the application name must be configured. So, how do you let your colleagues on the business side know this unspoken rule? Of course, many students say, well, just tell your colleagues to add some parameters. You can’t even remember chao’s daily tweets. Can you be sure everyone at work remembers them?

To sum up, we encounter such problems as follows:

1. We need to make some uncharted parameters for the interceptor, such as the one in this paper. How to make uncharted parameters elegant?

2. For example, interceptors have order requirements. For example, if the basic framework defines a traceInterceptor interceptor, the interceptor must come first. So the question is, how do you make sure this is the first one. I’ll use @order to control it. That I also write a interceptor like you, called feichaoInterceptor, code and you are exactly the same, since the same, how do you ensure that you are better than mine before?

3. How to sneak into a scene where rules must be hidden while resisting?

For these questions, we will answer them next time.