Home>

Because of the New Year,The project team doesn't have many tasks,I have nothing to do with a restful call in spring. I found that spring has become so powerful.The programmer no longer needs to care about data conversion and invocation in the process of writing the interface.Just focus on the business.Below I summarize the steps and problems encountered in the research process.

step:

1.git clonehttps://github.com/spring-guides/gs-rest-service.gitDownload the source code from the spring official website

2. Perform maven compilation (gradle also works)

3.Run and access

4, the results can be converted to json objects returned to the page

At this time, I was thinking about how to make the requested data automatically converted to a java object. Through Google, I found that in fact spring has provided the httpmessageconverter converter, and by default it is loaded with mappingjackson2httpmessageconverter (json ~ object conversion class). Just configure @requestbody greeting gree to use it.

The controller layer code is as follows:

@requestmapping (value="/greeting", method=requestmethod.post, consumes="application/json")
  public @responsebody greeting greeting (@requestbody greeting gree) {
    system.out.println (gree.getcontent ());
    return gree;
  }

At this time I call it through Google's plugin (postman),Life and death call was unsuccessful!

Analyze and solve problems:

At this time, I feel that the cause of the problem may be in the following areas:

1. Mappingjackson2httpmessageconverter is not loaded by default (I don't know the specific loading method)

2, mappingjackson2httpmessageconverter does not work after loading (I do n’t know why it does n’t work)

In fact, the reason why it doesn't work in the end is that I believe too much about the spring source code (the object does not provide a set method). With these two questions, a large number of online searchers could not find the corresponding results.There is no way to find the root cause of the problem,Look at the spring source code.

For the first question:

Step 1:Manually override the load type converter

@configuration
  @enablewebmvc
public class webconfiguration extends webmvcconfigureradapter {
  public void configuremessageconverters (list<httpmessageconverter<?>>messageconverters) {
    system.out.println ("init convert is start !!!!!");
    stringhttpmessageconverter stringconverter=new stringhttpmessageconverter ();
    stringconverter.setwriteacceptcharset (false);
    messageconverters.add (new mappingjackson2httpmessageconverter ());
    system.out.println ("init convert is stop !!!!!");
  }
}

Test found that it still can not be used,It is even more unclear why.You can only see how Spring loads type converters by default.It was found in webmvcconfigurationsupport that the method adddefaulthttpmessageconverters (the keyword httpmessageconverter was searched to find the place of use and found through judgment and tracking) as follows:

@suppresswarnings ("deprecation")
  protected final void adddefaulthttpmessageconverters (list<httpmessageconverter<?>>messageconverters) {
    stringhttpmessageconverter stringconverter=new stringhttpmessageconverter ();
    stringconverter.setwriteacceptcharset (false);
    messageconverters.add (new bytearrayhttpmessageconverter ());
    messageconverters.add (stringconverter);
    messageconverters.add (new resourcehttpmessageconverter ());
    messageconverters.add (new sourcehttpmessageconverter<source>());
    messageconverters.add (new allencompassingformhttpmessageconverter ());
    if (romepresent) {
      messageconverters.add (new atomfeedhttpmessageconverter ());
      messageconverters.add (new rsschannelhttpmessageconverter ());
    }
    if (jaxb2present) {
      messageconverters.add (new jaxb2rootelementhttpmessageconverter ());
    }
    if (jackson2present) {
      messageconverters.add (new mappingjackson2httpmessageconverter ());
    }
    else if (jacksonpresent) {
      messageconverters.add (new org.springframework.http.converter.json.mappingjacksonhttpmessageconverter ());
    }
  }

The corresponding default converter has been loaded.Breakpoint debugging shows that the default configuration is fine.

It can only be explained that it is caused by the second problem,But I don't know why it caused this problem (json data problem,Or other problems), without knowing the problem,You can only see the request.How the converter works.Because I do n’t know much about spring,So I don't know its principle.In this case, the corresponding use place can only be found according to the (httpmessageconverter) key class.Judge and debug with experience.It was found that the readwithmessageconverters method in abstractmessageconvertermethodargumentresolver is a processing method for requesting type conversion.

protected<t>object readwithmessageconverters (httpinputmessage inputmessage,      methodparameter methodparam, type targettype) throws ioexception, httpmediatypenotsupportedexception {
    mediatype contenttype;
    try {
      contenttype=inputmessage.getheaders (). getcontenttype ();
    }
    catch (invalidmediatypeexception ex) {
      throw new httpmediatypenotsupportedexception (ex.getmessage ());
    }
    if (contenttype == null) {
      contenttype=mediatype.application_octet_stream;
    }
    class<?>contextclass=methodparam.getcontainingclass ();
    class<t>targetclass=(class<t>) resolvabletype.fortype (targettype,        resolvabletype.formethodparameter (methodparam)). resolve ();
    for (httpmessageconverter<?>converter:this.messageconverters) {
      if (converter instanceof generichttpmessageconverter) {
        generichttpmessageconverter<?>genericconverter=(generichttpmessageconverter<?>) converter;
        if (genericconverter.canread (targettype, contextclass, contenttype)) {
          if (logger.isdebugenabled ()) {
            logger.debug ("reading [" + targettype + "] as \" "+
                contenttype + "\" using ["+ converter +"] ");
          }
          return genericconverter.read (targettype, contextclass, inputmessage);
        }
      }
      if (targetclass!=null) {
        if (converter.canread (targetclass, contenttype)) {
          if (logger.isdebugenabled ()) {
            logger.debug ("reading [" + targetclass.getname () + "] as \" "+
                contenttype + "\" using ["+ converter +"] ");
          }
          return ((httpmessageconverter<t>) converter) .read (targetclass, inputmessage);
        }
      }
    }
    throw new httpmediatypenotsupportedexception (contenttype, allsupportedmediatypes);
  }

At this time, it was found that the corresponding type message converter mappingjackson2httpmessageconverter had actually been found according to the canread method of httpmessageconverter, and conversion had begun.It just throws a runtime exception.Because the exception is not output in the console.I found through breakpoint debugging that the readjavatype method of mappingjackson2httpmessageconverter throws a runtime exception,Through the source code, it is found that the underlying layer is operated by Jackson's objectmapper.code show as below:

try {
      return this.objectmapper.readvalue (inputmessage.getbody (), javatype);
    }
    catch (ioexception ex) {
      throw new httpmessagenotreadableexception ("could not read json:" + ex.getmessage (), ex);
    }

If I just take the code and run it in the main method,Or not,At this point I will be able to locate the problem.If it were not for the wrong type,If it were not entered incorrectly.Close inspection revealed no problem with the json data,Can also be converted using jsonobject.At this time, it can only be judged that there is a problem with the incoming javatype.If I open and find that the object (greeting) does not have a set method, I think it is because this jakson does not work (the principle is not clear). If so, I provided the set method to this object, and then run it.I went around and finally solved the problem,But through this question made me more clear about the restful working mechanism of spring.

  • Previous Use PHP script in WordPress to determine what country your visitors are from
  • Next Summary of php array function array_key_exists ()