preface

I have a friend who yesterday hooked up with a front-end engineer and got the hell out of him. You know, since the front and back end separation, code gurus like me, who have always been proud of Being Java engineers, have had their backs cut in half and have since been labeled “Java server engineers”, “Java backend engineers” and so on. At the same time, front-end dad is more and more, also let us write an interface are treading on thin ice. So what happened?


after

Comb out, the general process is like this drop:

1) My friend is a Java engineer. He has been working in the company for four months and has only been a full-time employee for one month. Now he is involved in an urgent project development. 2), he finished writing the interface, self-test no problem, and then released to the test environment, re-test no problem, Oak, output documents to the front end, ready for joint adjustment; 3) The front-end engineer is a father in his early thirties, who is obsessed with details and seldom talks hard. More than three years after joining the company, he has completed most of the front-end pages and data binding of the company. He is the front-end leader. 4) The whole morning passed, the simple interface was not completed, and even some unpleasant things happened between the two people; 5) The front-end dad thinks that the interface is ok under normal circumstances, but the status is not clear under abnormal circumstances, so he cannot give user friendly prompt according to the status value; 6), my friend to a short time, dare not angry dare not speak, fear pointed out that their interface custom return object, normal state return 200, abnormal will trigger global exception processing, return status 500, very clear and no problem in teh baby; 7), the front dad than a hissing, hum young man, you see on the way is shallow, and I have a leg…… I have tuned more interfaces than you have pulled SHI. Please sit back and take a look at the code. Is there a trycatch on the interface and then a custom response object is directly returned when catching an exception? 8), my friend was in a panic, there was something in the old silver coin, a front-end even knew how to write my Java code, hurried back to review the code, back and forth review and self-test several times, finally found the problem is not a problem; 9), the original interface returned a lot of business state, but HTTP state is always 200 success, but this on your front end have no impact? 10), front-end dad said it did not affect, but I just want to judge the HTTP status code, I have obsessive-compulsive disorder; 11), there was no way, after all, it was Dad. My friend later referred to the interface code in the project I was responsible for and successfully completed the joint adjustment work after that, but from then on, he labeled himself as a rookie in the heart of the front-end dad.


Problem reproduction

To save time, I recreated the problem directly using Renren-Fast as scaffolding.

First, we define a simple interface and use the custom response object R to return the interface try.. Catch, which returns R.ok() on success, or r.ror () with an error message on an exception. (PS: As an aside, I have changed companies over the years. In fact, I have seen many colleagues like to write this way, and I think there are many other companies as well.)

/** * Custom response object returns *@returnResults the * /
@GetMapping("getUserInfo")
@apiOperation (" Get user information ")
public R getUserInfo(a) {
   Map<String, Object> map = new HashMap<>();
   try {
      map.put("id"."1001");
      map.put("name"."Zhang");
      map.put("age"."33");
      map.put("address"."Savage Cave, Shennongjia, Hubei Province");
   } catch (Exception ex) {
      return R.error("Abnormal." + ex.getMessage());
   }
   return R.ok().put("data", map);
}
Copy the code

Use Postman to debug the interface.

Next, an exception occurs on the mock interface.

/** * Custom response object returns *@returnResults the * /
@GetMapping("getUserInfo")
@apiOperation (" Get user information ")
public R getUserInfo(a) {
   Map<String, Object> map = new HashMap<>();
   try {
      map.put("id"."1001");
      map.put("name"."Zhang");
      map.put("age"."33");
      map.put("address"."Savage Cave, Shennongjia, Hubei Province");
      // Simulate an exception
      int i = 1/0;
   } catch (Exception ex) {
      return R.error("Abnormal." + ex.getMessage());
   }
   return R.ok().put("data", map);
}
Copy the code

Postman returns 500, HTTP status 200, no problem.

What if I throw an exception

/** * Custom response object returns *@returnResults the * /
   @GetMapping("getUserInfo")
   @apiOperation (" Get user information ")
   public R getUserInfo(a) {
      Map<String, Object> map = new HashMap<>();
      try {
         map.put("id"."1001");
         map.put("name"."Zhang");
         map.put("age"."33");
         map.put("address"."Savage Cave, Shennongjia, Hubei Province");
         // Simulate an exception
         int i = 1/0;
      } catch (Exception ex) {
         Throw a runtime exception
         throw new RuntimeException(ex.getMessage());
      }
      return R.ok().put("data", map);
   }
Copy the code

Normally handled by the project’s global exception, the custom response object r.ror () is returned.

@ExceptionHandler(Exception.class)
public R handleException(Exception e){
   logger.error(e.getMessage(), e);
   return R.error();
}
Copy the code

Postman then checks the HTTP status, and sees that the interface business status returns 500 with an exception.

The code itself catches and returns a custom response. An HTTP status of 200 indicates that the interface connectivity is normal. A business status of 500 indicates that the business program is abnormal. In fact, most projects do this, and there is nothing wrong with it, but sometimes it can lead to a misunderstanding of the logic of the interface state by the front-end engineer. Furthermore, if you are writing an interface to another manufacturer, you are the provider and they are the consumer, and this can create problems for them. Generally speaking, experienced front-end engineers will make judgments as follows: 1) Judge the HTTP status first. If 200 is not displayed, a friendly prompt will be given. If successful, the service status of the interface will be judged. 2) Judge the business status of the interface. If 200 is returned, the data will be bound. If it is not 200, a friendly reminder will be given. Then, when the back-end engineer returns the custom response object, as shown in the sample and the global exception handling returned in the response object is a custom for example, means that our interface HTTP status is always 200 successfully, the front of this judgment was a complete failure, once online project specific situation, could cause an illusion. In addition, as mentioned above, you are providing interfaces to other companies, manufacturers or even third party components. If you write this way, the HTTP status will always be 200, which also has hidden dangers. For example, we need to write interfaces to XXLJOB for task scheduling in my first company. XXLJOB is used to check HTTP_STATUS. As a result, XXLJOB always returns 200 success to our interface, so it does not feedback any exception warning. As a result, this important scheduling task is invalid even though it is normally executed. The problem was discovered only when a pile of unreturned orders went unprocessed.


Optimization of processing

Displaying in fact itself is not a problem, most projects so write also can run on the normal online, only there is little probability of risk, when the project size is larger, there are a lot of uncertainty, the return status of the interface is the only rely on to logical processing consumption, therefore, my suggestion is the best at the same time, return to a more accurate HTTP status and interface state of the business. To handle this, wrap the ResponseEntity that comes with Spring-Web.

/** * Custom ResponseEntity returns (wrapper ResponseEntity) *@returnResults the * /
@GetMapping("getUserInfo2")
@apiOperation (" Get user information ")
public ResponseEntity<R> getUserInfo2(a) {
  Map<String, Object> map = new HashMap<>();
  try {
     map.put("id"."1001");
     map.put("name"."Zhang");
     map.put("age"."33");
     map.put("address"."Savage Cave, Shennongjia, Hubei Province");
     // Simulate an exception
     int i = 1/0;
  } catch (Exception ex) {
     / / return ResponseEntity. BadRequest (). The body (R.e rror (" exception: "+ ex. GetMessage ()));
     return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error("Abnormal." + ex.getMessage()));
  }
  return ResponseEntity.ok().body(R.ok().put("data", map));
}
Copy the code

Effect:

ResponseEntity encapsulates almost all of the HTTP state. The sample code above includes the commented out line. There are two ways to return the specific HTTP state to the front end. If you select a custom response object to return, put it inside the ResponseEntity body (ResponseEntity) to ensure that the interface returns both a specific HTTP state and a specific business state, and the front and back end engineers become a loving family.


conclusion

My final recommendation to everyone is as follows: 1) Designate ResponseEntity as the ResponseEntity for the entire project; 2) If you use a custom response object, you’d better use ResponseEntity as a wrapper; ResponseEntity (ResponseEntity) {ResponseEntity (ResponseEntity) {ResponseEntity (ResponseEntity) {ResponseEntity (ResponseEntity); With all kinds of new technologies emerging in an endless stream, don’t go too far in pursuit of powerful and popular technologies, but pay more attention to basic skills and coding details. Especially for those who have not yet worked and work for a long time, do not underestimate the ability to write interfaces, otherwise it will be despised by the company’s father.



I focus on sharing all kinds of technology, work fun and experience, like or harvest friends, don’t be mean to your a point like and collection oh ~~ can also check the personal home page to pay attention to the information inside oh ~~