1. 程式人生 > >spring MVC 獲取request中的body體

spring MVC 獲取request中的body體

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">	</span>在專案中,客戶端向服務端傳送一組json資料,這組資料隨著時間的推移可能會越來越大,可能會受到伺服器對引數大小的限制的影響,因此,想直接將資料塞進request的body體中,繼而傳送給服務端,服務端直接將request中body 以流的方式讀出來,並持久化。</span>

HttpServletRequest

類中有兩個方法 getInputStream() 和request.getReader() ,本以為可以直接快速搞定,但是執行程式時報異常:getInputStream() has already been called for this request ,經過查證,原來專案採用springmvc框架,框架內部已經讀過request中流,所以當再次讀取時,就讀不到了,所以直接獲取走不通了。

在網上問了問度娘,springmvc 中有一個註解@RequestBody 可以獲取request中資料,部分程式碼如下:

@RequestMapping("/save")

public ModelAndView save(HttpServletRequest request,@RequestBody String s

){ 

//具體操作 省略

}

執行過程中,還是有問題,但至少有進了一步,上述的String物件依然無法獲取資料,這就有些糾結了,又開始問度娘和下載找spring的原始碼,瞭解@RequestBody的實現細節,發現獲取body spring用了一系列的HttpMessageConverter 來實現,如:ByteArrayHttpMessageConverter,stringHttpMessageConverter ,spring自個實現的轉換器,com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter【國產的json轉換器,該轉換器需要在配置檔案中配置】,預設的轉換器的初始化工作在RequestMappingHandlerAdapter這個類中實現

	private List<HttpMessageConverter<?>> messageConverters;//轉換器的集合
public RequestMappingHandlerAdapter() {

		StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
		stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316

		this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(stringHttpMessageConverter);
		this.messageConverters.add(new SourceHttpMessageConverter<Source>());
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
	}//初始化工作

找到這發現byte ,String的轉換器已經初始化了,但是為啥還是拿不到String型別的資料呢,接著找關於converters相關的程式碼,有個setMessageConverters方法

	/**
	 * Provide the converters to use in argument resolvers and return value
	 * handlers that support reading and/or writing to the body of the
	 * request and response.
	 */
	public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
		this.messageConverters = messageConverters;
	}
spring在解析xml過程中會呼叫該方法 ,從而將用到的converters注入進去,因此明白專案在啟動的過程中重新設定了HttpMessageConverter ,而我需要的converter並沒有注入進去,因此在xml中配置如下
<mvc:annotation-driven >
		<mvc:message-converters> 
            <ref bean="fastJsonHttpMessageConverter" /> 
        </mvc:message-converters> 
	</mvc:annotation-driven>
	
	<bean id="stringHttpMessageConverter"  
        class="org.springframework.http.converter.StringHttpMessageConverter">  
        <constructor-arg value="UTF-8" index="0"></constructor-arg>
        <property name="supportedMediaTypes">  
            <list>  
                <value>text/plain;charset=UTF-8</value>  
            </list>  
        </property>  
    </bean>
    <bean id="byteHttpMessageConverter"  
        class="org.springframework.http.converter.ByteArrayHttpMessageConverter">  
    </bean>    
    <bean id="fastJsonHttpMessageConverter"  
        class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">  
  
        <property name="supportedMediaTypes">  
            <list>  
                <value>application/json;charset=UTF-8</value>  
                <value>text/html;charset=UTF-8</value> 
            </list>  
        </property>
         <property name="features">  
            <list>  
                <!-- <value>WriteMapNullValue</value> -->  
                <value>QuoteFieldNames</value>  
                <value>WriteDateUseDateFormat</value>  
            </list>  
        </property>    
    </bean>  

這時啟動專案,可以拿到資料了。。。

因此,在遇到問題的時候,先按照自己的思路嘗試著去解決,可能有時候有些問題確實不知道如何解決的時候,可以先查查網上有沒有相關問題的解決方案,選擇合適的方案,自然問題就迎刃而解了,但是個別的時候,會遇到相當棘手的問題,通過一系列方案都無法完美解決的時候,可以嘗試去查閱原始碼,同過閱讀原始碼,一會理解框架的開發者的設計思路,只要順著他們的思路,我們的問題自然就不是問題了。

最後,多讀讀優秀的開源專案的原始碼。


附:遍歷轉換器的程式碼

AbstractMessageConverterMethodArgumentResolver 

/**
	 * Creates the method argument value of the expected parameter type by reading
	 * from the given HttpInputMessage.
	 *
	 * @param <T> the expected type of the argument value to be created
	 * @param inputMessage the HTTP input message representing the current request
	 * @param methodParam the method argument
	 * @param targetType the type of object to create, not necessarily the same as
	 * the method parameter type (e.g. for {@code HttpEntity<String>} method
	 * parameter the target type is String)
	 * @return the created method argument value
	 * @throws IOException if the reading from the request fails
	 * @throws HttpMediaTypeNotSupportedException if no suitable message converter is found
	 */
	@SuppressWarnings("unchecked")
	protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage,
			MethodParameter methodParam, Type targetType) throws IOException, HttpMediaTypeNotSupportedException {

				MediaType contentType = inputMessage.getHeaders().getContentType();
				if (contentType == null) {
					contentType = MediaType.APPLICATION_OCTET_STREAM;
				}

				Class<?> contextClass = methodParam.getDeclaringClass();
				Map<TypeVariable, Type> map = GenericTypeResolver.getTypeVariableMap(contextClass);
				Class<T> targetClass = (Class<T>) GenericTypeResolver.resolveType(targetType, map);

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





相關推薦

spring MVC 獲取requestbody

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre">

spring mvc 從bean自動獲取物件

寫在前面 在日常開發或者學習spring mvc web專案中,當專案打包部署後,某些自定義配置項引數可能會需要改動。而這些配置項引數如果被寫死進專案中,或許會造成很大的麻煩。因此,有時候這些需要變動的自定義的配置項引數,便需要寫進配置檔案中。spring m

spring mvc獲取絕對路徑的幾種方法

col 文件 結果 ret 項目 tps span ppr etc 1.首先如果是在一個controller方法中,則很簡單,直接用下面語句。 1 @RequestMapping("categoryHome") 2 public ModelAndVie

解決Spring MVC @ResponseBody返回文字符串亂碼問題

有效 per log bean dia media converter 原因 ons 引起亂碼原因為spring mvc使用的默認處理字符串編碼為ISO-8859-1 具體參考org.springframework.http.converter.StringHttpMess

spring mvc-獲取 @resposeBody

方式 clas 狀態 cut nts logger esc str G1 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.MethodPara

Spring MVC獲取不到post提交的multipart/form-data格式的資料

我們在寫介面時,經常會用postman測試介面。前段時間我寫介面時,發現post的form-data提交資料,後端竟然接收不到請求引數,而使用post的x-www-form-urlencoded方式提交資料,後端可以接收到引數。為什麼? postman的form-data是指mult

Spring MVC——The request sent by the client was syntactically incorrect ()的原因與解決辦法

這句話的意思是客戶端傳送的請求語法錯誤,從而導致springmvc無法實現資料繫結。  而這種錯誤呢,大部分是由於引數格式不正確。 下面舉一個例子來說明: <form:form id="seller_changepassword_form" modelAttribute=

spring mvc 獲取後端傳遞的值

jsp頁面怎麼獲取從後端傳遞過來的值? JSTL 方法獲取後端傳遞的值 @RequestMapping("index1") public ModelAndView index1() { ModelAndView model = new ModelAndView("/Ind

spring MVC接受物件包含enum屬性

- 說明:後臺使用了fastJson,且希望傳遞的引數不是列舉的名稱(例下面物件:INDUSTRY),則需使用@JSONField(name = “100”)。如果傳的的引數就是(INDUSTRY),則預設就能接收。 //前臺傳遞的json物件 { "

英科--獲取request 的所有引數-包括Cookie-摘錄

import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.Cookie; import j

Spring MVC實際專案的應用

目前的專案應用了Spring MVC框架,總結一下實際應用中這個框架是如何發揮作用的,下圖是處理流程。參考 1: 首先使用者傳送請求資訊,例如url:http://ggg-admin.inta.sit.fan.com/advertisement/query

spring mvc獲取IP地址

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()

獲取 request json 資料

springMVC獲取請求中的json資料:都是post方式 方法一:  http://m.blog.csdn.net/article/details?id=50149061 方法二: InputStream is = request.getInputStream

Spring MVC獲取所有註冊的url

本文的目的是獲取所有通過requestMapping註冊的url @RequestMapping("getAllUrl")

spring mvc 返回json去除null欄位

為了減少不必要的內容傳輸, 過濾null欄位,可對返回的類加入註釋來解決。 條件: 1.  spring MVC 3.X 支援註解 2. jackson-code.jar,jackson-mapper.jar 通常用jackson-all-xxx.jar 就行

spring mvc ${}獲取不到變數

control類如下 @Controller public class HelloControl { @RequestMapping(value = "/",method = Request

spring手動獲取容器的bean

只需要定義一個bean,這個bean繼承ApplicationContextAware如下:public class SpringContextHolder implements ApplicationContextAware { private static A

關於maven Web(Spring MVC)專案,部分專案啟動後無法訪問路徑的解決方案及解釋。

在最近兩天學習新的Spring 內容中, 發現按照Spring in action 敲得程式碼無法進入後臺,在檢查後, 確認程式碼無誤。  然後開始不停的找原因。之後在檢視tomcat中的專案時, 發現專案的路徑不對, class的位置不對, 然後jsp的位置也不對,甚至沒

JFINAL+Ajax傳參 array 陣列方法 獲取request陣列

前臺程式碼jsvar _list =[]; for (var i = 0; i < array.length; i++) { _list[i] = a

Spring mvc獲取資料庫的詳細時間

問題 在Spring中,想獲取資料庫的時間,年月日時分秒,但是怎麼都獲取不到時分秒,發現是寫錯了mybatis的配置檔案。 mybatis的配置檔案 <result column="TOPIC_TIME" property="topicTim