Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Notes on how to use message converters HttpMessageConverter and @ ResponseBody in SpringMVC

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Editor to share with you how to use the message converter HttpMessageConverter and @ ResponseBody notes in SpringMVC, I believe most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article, let's learn about it!

Phenomenon

The demo used in this article is based on maven and is based on the example of getting started with blog.

Let's first take a look at the corresponding phenomenon. The key configurations in our configuration file *-dispatcher.xml here are as follows:

(view configuration omitted)

The following dependencies are required in pom (Spring dependencies and other dependencies are not shown):

Org.codehaus.jackson jackson-core-asl 1.9.13 org.codehaus.jackson jackson-mapper-asl 1.9.13

This dependency is a dependency on json serialization.

Ok . Let's add a method to Controller:

@ RequestMapping ("/ xmlOrJson") @ ResponseBody public Map

Direct access address:

As we see, just a few lines of configuration. After using the @ ResponseBody annotation, the objects returned by Controller are automatically converted into the corresponding json data, so here we have to sigh at the power of SpringMVC.

We don't seem to see a specific configuration either. the only thing we see is a configuration in *-dispatcher.xml: mvc:annotation-driven/. In fact, it is this configuration that causes the automatic conversion of java objects to json objects.

So how does spring realize the automatic conversion from java objects to json objects? Why is it converted to json data? what should I do if I want to convert it to xml data?

Source code analysis

* * the spring version used in this article is 4.0.2. **

Before we talk about the configuration of mvc:annotation-driven/, let's take a look at the message transformation mechanism of Spring. The @ ResponseBody annotation uses the message conversion mechanism to convert json data into json data through the json converter.

The HttpMessageConverter interface is the http message transformation interface provided by Spring. For more information about this, you can refer to the second link in the Resources, which is very clear.

Let's analyze the configuration of mvc:annotation-driven/:

The parsing class for this code in spring is:

In the 152line parse method of the AnnotationDrivenBeanDefinitionParser source code:

Many classes such as RequestMappingHandlerMapping,ConfigurableWebBindingInitializer,RequestMappingHandlerAdapter are instantiated respectively.

Among them, RequestMappingHandlerMapping and RequestMappingHandlerAdapter are more important.

RequestMappingHandlerMapping handles request mapping and handles the relationship between @ RequestMapping and the request address.

RequestMappingHandlerAdapter is the adapter for request processing, that is, the execution of the specific logic after the request, which is related to which class, which method and the converter and so on. This class is the focus of our talk, and its property messageConverters is the focus of this article.

Private method: getMessageConverters

From the code, we can set the logic of the messageConverters by RequestMappingHandlerAdapter:

1. If a mvc:annotation-driven node has a child node message-converters, then its converter attribute messageConverters also consists of these child nodes.

The child nodes of message-converters are configured as follows:

If the 2.message-converters child node does not exist or its attribute register-defaults is true, add other converters: ByteArrayHttpMessageConverter, StringHttpMessageConverter, ResourceHttpMessageConverter, etc.

We see a passage like this:

Where did these boolean attributes come from? they are static variables of AnnotationDrivenBeanDefinitionParser.

The isPresent method in ClassUtils is as follows:

Seeing here, the reader should understand why the corresponding jackson dependency needs to be added to the pom file at the beginning of this article, in order to make the json converter jackson one of the default converters.

Readers also understand the role of mvc:annotation-driven.

Let's take a look at how to convert java objects through a message converter.

When RequestMappingHandlerAdapter performs handle, it is delegated to the invokeAndHandle method of HandlerMethod (specifically handled by the subclass ServletInvocableHandlerMethod), which is transferred to HandlerMethodReturnValueHandlerComposite for processing.

HandlerMethodReturnValueHandlerComposite maintains a list of HandlerMethodReturnValueHandler. HandlerMethodReturnValueHandler is a policy interface that handles the return value, which is very important. For details on this interface, please refer to another blog post of the landlord: http://www.cnblogs.com/fangjian0423/p/springMVC-request-param-analysis.html. Then find the corresponding HandlerMethodReturnValueHandler to process the result value.

Finally find the Handler of RequestResponseBodyMethodProcessor (due to the use of the @ ResponseBody annotation).

The supportsReturnType method of RequestResponseBodyMethodProcessor:

Then use the handleReturnValue method to process:

We see that the converter is used here.

Specific conversion method:

As for why it is the Accept data of the request header, the reader can go into the debug getAcceptableMediaTypes method to see. I won't be wordy.

Ok . So far, we have gone through all the processes.

Now, looking back. Why did the initial demo output json data?

Let's analyze it.

Since we have only configured mvc:annotation-driven, we use the default converters of spring.

Obviously, we see two xml and one json converter. Whether it can be converted depends on whether the public boolean canWrite (Class clazz, MediaType mediaType) method of the HttpMessageConverter interface returns true.

Let's first analyze SourceHttpMessageConverter:

Its canWrite method is overridden by the parent class AbstractHttpMessageConverter.

It is found that there is no Map class in SUPPORTED_CLASSES (this article demo returns the Map class), so it is not supported.

Here's a look at Jaxb2RootElementHttpMessageConverter:

This class directly overrides the canWrite method.

XmlRootElement comments are required. Obviously, the Map class certainly does not.

Finally, the MappingJackson2HttpMessageConverter match is performed and the json transformation is performed. (why it matches, please check the source code for yourself.)

Example explanation

After we have analyzed the conversion process of the converter, let's use an example to verify our conclusion.

First of all, let's implement the xml converter.

As analyzed previously, xml is supported in the default converter. Let's try to add notes next.

Because Map is part of the jdk source code, we use Employee to do demo.

Therefore, Controller adds a method:

@ RequestMapping ("/ xmlOrJsonSimple") @ ResponseBody public Employee xmlOrJsonSimple () {return employeeService.getById (1);}

Add @ XmlRootElement annotation to the entity

The results are as follows:

We found that it was parsed to xml.

Why is it parsed to xml instead of json here?

As analyzed earlier, the message translator is determined based on class and mediaType.

We use firebug to see:

We found that Accept has xml, not json. So it parses to xml.

Let's verify that the same address and different HTTP headers have different Accept. See if it's right.

Ajax ({url: "${request.contextPath} / employee/xmlOrJsonSimple", success: function (res) {console.log (res);}, headers: {"Accept": "application/xml"}})

Ajax ({url: "${request.contextPath} / employee/xmlOrJsonSimple", success: function (res) {console.log (res);}, headers: {"Accept": "application/json"}})

Verification was successful.

About configuration

If you don't want to use the default RequestMappingHandlerAdapter in mvc:annotation-driven/, we can redefine the bean,spring to override the default RequestMappingHandlerAdapter.

Why do you overwrite it? please refer to another blog post of the landlord: http://www.cnblogs.com/fangjian0423/p/spring-Ordered-interface.html

``

Or if you just want to change the messageConverters.

If you want to use other converters.

This is the converters in the spring-mvc jar package.

Here we use MarshallingHttpMessageConverter that transforms xml.

Marshaller is used in this converter for conversion.

We use XStreamMarshaller here.

Json has no converter and returns 406.

As for the problem of xml format, let's solve it by ourselves. XStream~ is used here.

In this way, pom don't forget to add xstream dependencies:

Com.thoughtworks.xstream xstream 1.4.7 Summary

After writing so much, the reader may feel a little wordy. After all, these are some of my own experiences, and I hope I can share them with my readers.

When I first came into contact with SpringMVC, I found that this automatic conversion mechanism is very powerful, but I have not studied its principle. At present, I can be regarded as a small wish. SpringMVC has a lot of content, and I will share it with you when I study other content in the future.

It is inevitable that there will be some mistakes in the article. I hope readers can point them out.

references

Http://my.oschina.net/HeliosFly/blog/205343

Http://my.oschina.net/lichhao/blog/172562

Http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

Detailed explanation of RequestBody and @ ResponseBody notes

Summary in SpringMVC, @ RequestBody and @ ResponseBody annotations can be used to complete the conversion of request message to object and object to response message respectively. The underlying flexible message conversion mechanism is the newly introduced HttpMessageConverter message converter mechanism in Spring3.x.

# the abstraction of the Http request comes back to the request-response, that is, parsing the request body and then returning the response message, which is the most basic Http request process. We know that in the servlet standard, you can use the following methods in the javax.servlet.ServletRequest interface:

Public ServletInputStream getInputStream () throws IOException

To get a ServletInputStream. In this ServletInputStream, you can read all the contents of an original request message. Similarly, in the javax.servlet.ServletResponse interface, you can use the following methods:

Public ServletOutputStream getOutputStream () throws IOException

To get a ServletOutputStream, this ServletOutputSteam, inherited from OutputStream in java, allows you to output the contents of the Http response message.

Let's try to think like the designers of SpringMVC. We know that Http request and response messages are essentially strings. When the request message comes to the java world, it will be encapsulated into an ServletInputStream input stream for us to read. The response message outputs the response message through an output stream of ServletOutputStream.

We can only read the original string message from the stream, and similarly, we can only write the original characters to the output stream. In the java world, the processing of business logic is based on business meaningful objects, so when the message arrives at SpringMVC and goes out from SpringMVC, there is an impedance problem from string to java object. This process cannot be manually converted by the developer. We know that in Struts2, OGNL is used to deal with this problem, while in SpringMVC, it is the HttpMessageConverter mechanism. Let's first look at two interfaces.

The class # HttpInputMessage is the abstraction of a Http request message within SpringMVC. In the read () method of HttpMessageConverter, there is a formal parameter of HttpInputMessage, which is the internal abstraction of the recipient "request message" acted by the message converter of SpringMVC. The message converter extracts the message from the "request message" according to the rules and converts it into the object declared in the method parameter.

Package org.springframework.http;import java.io.IOException;import java.io.InputStream;public interface HttpInputMessage extends HttpMessage {InputStream getBody () throws IOException;}

The class # HttpOutputMessage is the abstraction of a Http response message within SpringMVC. In the write () method of HttpMessageConverter, there is a formal parameter of HttpOutputMessage, which is the internal abstraction of the receptor "response message" acted by the message converter of SpringMVC. The message converter writes the "response message" into the response message according to certain rules.

Package org.springframework.http;import java.io.IOException;import java.io.OutputStream;public interface HttpOutputMessage extends HttpMessage {OutputStream getBody () throws IOException;}

# HttpMessageConverter abstracts the highest-level interface of a message converter and describes the general characteristics of a message converter. We can understand how Spring3.x designers think about this mechanism from the methods defined in this interface.

Package org.springframework.http.converter;import java.io.IOException;import java.util.List;import org.springframework.http.HttpInputMessage;import org.springframework.http.HttpOutputMessage;import org.springframework.http.MediaType;public interface HttpMessageConverter {boolean canRead (Class clazz, MediaType mediaType); boolean canWrite (Class clazz, MediaType mediaType); List getSupportedMediaTypes (); T read (Class)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report