處理JSON
對於JSON的處理一般都是基於Ajax前端技術來實現的,可以實現頁面的局部刷新數據顯示。
在Springmvc處理JSON是非常簡單的。
分爲三步走:
一、前臺提交請求Ajax
二、後臺處理請求@ResponseBody
三、前臺接收返回的JSON數據 dataType
<!-- 前臺提交請求 一般都是利用ajax -->
<a href="testJson" id="testjson">Test JSON</a>
$(function(){
$("#testjson").click(function(){
var url= this.href;
var args= {};
$.ajax({
url:url,
type:'post',
dataType:'json',
success:function(data){
for(var i=0;i<data.length;i++){
var id= data[i].id;
var lastName=data[i].lastName;
alert(id+":"+lastName);
//$("#two").append(data);
}
}
});
return false;
});
})
<!-- 後臺處理 -->
// 測試JSON 注意返回的數據
@ResponseBody
@RequestMapping("/testJson")
public Collection<Employee> testJson(){
System.out.println("test JSON");
return employeeDAO.getAll();
}
注意:進行ajax數據提交的時候,在後臺我們的數據不能再存放在Map集合中了,這是因爲,存放Map集合中 的數據需要進行頁面刷新或者頁面跳轉才能顯示數據,而我們利用的Ajax異步傳輸。
注意:我們返回的值,直接是我們前臺所需要的數據。而不再需要進行視圖渲染,所以我們也是添加了註解@ResponseBody。
Jackson簡介
JackSon框架類似於json-lib框架(struts2提供了集成json-lib的插件),都是講Java對象與JSON對象之間的轉換。但是相比json-lib框架,Jackson所依賴的jar包較少。
Jackson可以輕鬆的將Java對象轉換成json對象和xml文檔,同樣也可以將json、xml轉換成Java對象。
對於Jackson來講,只需要導入三個jar包就可以實現JSON的轉換【jackson-databind-2.4.0】【jackson-core-2.4.0】【jackson-annotations-2.4.0】,所以在我們編寫上面代碼時,不要忘記進行jar包的導入。
jackson 框架提供了JsonGenerator ,ObjectMapper兩個類通過這兩個類提供的方法可以將java 對象轉化爲json 對象,json 數組格式,也可以將json對象、數組格式轉化爲java對象。
HttpMessageConverter基礎概念
爲什麼能夠處理JSON ,對於Spring3.0 ,新增了一個接口HttpMessageConverter[T],這個接口負責將請求轉化爲一個對象(類型爲T),將對象(類型爲T)輸出爲響應信息。
HttpMessageConverter[T]接口中定義了一些方法(在代碼中可以搜索HttpMessageConverter進行查看):
【boolean canRead(Class[ ? ] clazz, MediaType mediaType)】:指定轉換器可以讀取的對象類型,即轉換器是否可以將請求信息轉化爲Clazz類型的對象,同時指定支持MIEI類型(text/html,application/json等)。
【boolean canWrite(Class[ ? ] clazz, MediaType mediaType)】:指定轉換器是否可以將Clazz類型的對象寫入到響應流中,響應流支持的媒體類型在MediaType中定義。
【List[MediaType] getSupportedMediaTypes()】:該轉換支持的媒體類型。
【T read(Class[? extends T] clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException 】:將請求信息流轉化爲T類型的對象。
【void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException】:將T類型的對象寫到響應流中,同時指定相信的媒體類型爲contentType
HttpMessageConverter工作原理流程 查看【HttpInputMessage】和【HttpOutputMessage】
HttpMessageConverter接口的實現類
查看Springmvc裝配了那些實現類。
在我們測試的testJSON方法中打上斷點,debug之後,我們可以向前找到dispatchServlet,然後變量域中找到【this】【handlerAdapters】【elementData中的RequestMappingHandlerAdapter】【MessageConverters】
HttpMessageConverter使用方式
使用HttpMessageConverter[T]能做些什麼呢? 使用這個我們可以將請求信息轉化並綁定到處理方法的入參中,或者,響應結果轉化爲對應類型的響應信息,注意是請求信息的處理和轉化爲對應的類型的響應信息,spring 提供了兩種路徑:
使用【@ResponseBody】和【@RequestBody】對處理方法進行標註
使用【HttpEntity[T]】和【ResponseEntity[T]】作爲處理方法的入參和返回值。
當控制器處理的方法使用到上述四個註解時,Spring 首先根據請求頭和響應頭的Accept屬性(HTTP協議)選擇匹配的HttpMessageConverter(上面的默認實現類),進而根據參數類型或者泛型類型的過濾得到匹配的HttpMessageConverter,如果找不到可用的如果找不到可用的將報錯。
【@ResponseBody】和【@RequestBody】【HttpEntity[T]】和【ResponseEntity[T]】不需要成對出現。
@RequestBody 將HTTP請求正文轉換爲適合的HttpMessageConverter對象。
@ResponseBody 將內容或對象作爲 HTTP 響應正文返回,並調用適合HttpMessageConverter的Adapter轉換對象,寫入輸出流。
實例一 讀取文件內容。類似於上傳效果的使用:
<!--前臺提交數據 -->
<form action="testHttpMessageConverter" method="post" enctype="multipart/form-data">
File:<input type="file" name="file"/><br>
Desc:<input type="text" name="desc"/>
<input type="submit" value="submit">
</form>
<!-- 後臺進行處理 -->
// 類似於上傳工作
//此時利用的是StringHttpMessageConverter 將請求信息轉換爲字符串
@RequestMapping("/testHttpMessageConverter")
public String testHttpMessageConverter(@RequestBody String body){
System.out.println(body);
return "Hello HttpMessage"+new Date();
}
實例二 實現文件下載
<!-- 前臺數據連接 -->
<a href="TestResponseEntity">TestResponseEntity</a>
<!-- 後臺數據處理下載 -->
@RequestMapping("/TestResponseEntity") // 類似於下載
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{
byte []body=null;
ServletContext context = session.getServletContext();
InputStream in = context.getResourceAsStream("/files/abc.txt");
body = new byte[in.available()];
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename=abc.txt");
// 設置響應頭 爲下載
HttpStatus stateCode = HttpStatus.OK;
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body,headers,stateCode);
return response;
}
國際化
默認情況下,Springmvc會根據請求中的Accept-Language參數判斷客戶端的本地化類型(HTTP協議)。當接受到請求時Springmvc會在上下文找一個本地化解析器(LocalResolver),找到後使用他獲取請求所對應的本地化類型信息。Springmvc還允許裝配一個動態更改本地化類型的攔截器。這也是我們所在springmvc.xml中所配置的文件,這樣就通過指定一個請求參數就可以控制單個請求的本地化類型。
本地化解析器和本地化攔截器
【AcceptHeaderLocaleResolver】:根據http請求頭的Accept-Language確定本地化類型,Springmvc使用該解析器。
【CookieLocaleResolver】:指定的cookie值確定本地化類型。
【SessionLocalResolver】:根據session中特定的屬性確定本地化類型。
【LocaleChangeInterceptor】:從請求參數中獲取本次請求對應的本地化類型。
他們在配置文件中進行使用。
關於國際化
作用:
1、在頁面上能夠根據瀏覽器語言設置的情況對文本(不是內容),時間,數值進行本地化處理
2、 可以在bean中獲取國際化資源文件,Locale 對應的消息(使用時注意配置文件要關閉)
3、 可以通過超鏈接切換Locale (切換語言) 而不用瀏覽器的語言設置情況
解決
1、 使用JSTL 的fmt 標籤,對國際化字段進行顯示。
2、 在bean中注入ResourceBundleMessageSource的實例,使用其對應的getMessage方法即可
3、 配置SessionLocaleResource 和LocaleChangeInterceptor
注意上述的作用和解決方案一一對應
<!-- spring.xml配置文件 -->
<!-- 配置國際化資源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
<!-- 配置 SessionLocaleResolver -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
</bean>
<!-- 配置攔截器 LocaleChangeInterceptor-->
<mvc:interceptors>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
</bean>
</mvc:interceptors>
<!--直接跳轉到頁面,不經過Controller -->
<!-- <mvc:view-controller path="/i18n" view-name="i18n" /> 獲取資源時,利用Controller 所以屏蔽 -->
<mvc:view-controller path="/i18n2" view-name="i18n2" />
<!-- 前臺鏈接一 -->
<a href="i18n"> I18N Page </a> // 第一頁面 index.jsp 跳轉第二頁面
<!-- 前臺鏈接二 --> // 第二頁面 i18n.jsp 注意上面的直接跳轉配置
<fmt:message key="i18n.username"></fmt:message> // 國際化顯示
<a href="i18n2"> I18N2 Page </a>
<br>
<a href="i18n?locale=zh_CN"> 中文 </a>
<br>
<a href="i18n?locale=en_US"> English</a>
<br>
<!-- 前臺鏈接三 --> // 第三頁面 i18n2.jsp
<fmt:message key="i18n.password"></fmt:message>
<a href="i18n"> I18N Page </a>
<!-- 後臺處理代碼 -->
@Autowired
private ResourceBundleMessageSource messageSource;
@RequestMapping("/i18n")
public String Testi18n(Locale locale){ // Locale 入參
String val = messageSource.getMessage("i18n.username", null, locale);
System.out.println(val);
return "i18n";
}
文件上傳
對於文件上傳Springmvc提供了直接的支持!這種支持是通過即插即用的MultipartResolver,Springmvc用Jakarta Commons FileUpload技術實現了一個【MultipartResolver】實現類:【CommonsMultipartResolver】。
Springmvc 上下文中默認沒有裝配【MultipartResolver】因此,默認情況下事不能處理文件的上傳工作。如果想使用Springmvc的文件上傳功能,需要在上下文進行配置【MultipartResolver】。
分爲四步走:
第一步:加入jar包
第二步:配置文件
第三步:前臺文件提交
第四步:後臺數據處理
第一步:加入jar包
由於我們使用Jakarta Commons FileUpload技術,所以我們要加入需要的jar包【commons-fileupload-1.2.1】【commons-io-2.0.1】注意fileupload依賴io所以也要進行加入。
第二步:配置文件:
<!--文件的上傳 -->
<!-- 配置 CommonsMultipartResolver 具體的屬性配置去源碼中查看,注意編碼的問題 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="1024000000000"></property>
</bean>
可配置屬性
第三步:前臺文件提交
<p>FileUpload</p>
<form action="TestFileUpload" method="post" enctype="multipart/form-data">
File:<input type="file" name="file01"/><br>
Desc:<input type="text" name="desc01"/>
<input type="submit" value="submit">
</form>
第四步:後臺數據處理
利用入參MultipartFile 類型用來接收文件的相關信息
@RequestMapping("/TestFileUpload")
public String TestFileUpload(@RequestParam(value="desc01",required=false) String desc,
@RequestParam("file01") MultipartFile file ) throws Exception{
//參數MultipartFile 用來傳遞文件的相關信息
System.out.println("desc:"+desc);
System.out.println("OriginalFilename"+file.getOriginalFilename());
System.out.println("getInputStream"+file.getInputStream());
InputStream inputStream = file.getInputStream();
if(file.isEmpty()){
file.transferTo(new File("d:\\"+file.getOriginalFilename()));
// 文件寫入地點
}
return "success";
}
注意的是HttpMessageConverter是不能做文件上傳的,但是他能分辨出那個是文件