SpringMVC簡單構造restful, 並返回json

在別人的博客上看到的文章,就摘抄下來了,最近看書的方向比較亂,nodejs準備學着看看。。轉載的內容先爲自己留着

 

文章要要點:

  1. 快速搭建構造restful的StringMvc

  2. GET, POST , PUT , DELETE的各種調用

  3. 同一資源 多種表述 (ContentNegotiatingViewResolver解析器),既可以返回對象給JSP, 也可以返回JSON

快速搭建構造restful的StringMvc

首現搭建一個簡單的restfulMvc框架,  並上配置文件, 後期會增加帶JSON返回值的配置

JAR包


 

web.xml配置

<servlet>

     <servlet-name>spring</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>classpath:config/spring-servlet.xml</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
      <servlet-name>spring</servlet-name>
      <url-pattern>/api/*</url-pattern>
</servlet-mapping>


<listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 指定Spring Bean的配置文件所在目錄。默認配置在WEB-INF目錄下 -->

<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:config/applicationContext-*.xml</param-value>
</context-param>

 

spring-servlet.xml配置

 

<!-- 啓動註解驅動的Spring MVC功能,註冊請求url和註解POJO類方法的映射-->  
 <mvc:annotation-driven />   
 <!-- 啓動包掃描功能,以便註冊帶有@Controller、@Service、@repository、@Component等註解的類成爲spring的bean -->  
 <context:component-scan base-package="com.dsp" />   
      
 <!-- 對模型視圖名稱的解析,在請求時模型視圖名稱添加前後綴 -->  
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />


 

applicationContext.xml暫時沒寫東西

該配置的配置完了,下面就是寫第一個HelloWord

package com.dsp.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Scope("prototype")
@Controller
@RequestMapping("/products")public class TestController{
   
 /**
  * 測試方法,HelloWord
  * @param request
  * @param response
  * @return
  * @throws Exception
  */
 @RequestMapping(value="/list",method=RequestMethod.GET)
    public String getProducts(HttpServletRequest request,HttpServletResponse response) throws Exception {
    
        request.setAttribute("name""helloWord");
          
        return "products/list";
          
    }
}

地址欄輸入 http://localhost:8080/RestFulMvc/api/products/list

得到結果

GET, POST , PUT , DELETE的各種調用

剛纔寫的是第一種GET, 第二種GET:

@RequestMapping(value="/info/{proId}",method=RequestMethod.GET)
    public String getProductInfo(@PathVariable String proId, HttpServletRequest request,HttpServletResponse response) throws Exception {
    
          request.setAttribute("name", proId);
            
          return "products/list";
          
    }

@PathVariable註解獲取的就是大括號裏的值

測試 : 輸入地址 http://localhost:8080/RestFulMvc/api/products/info/00001

測試結果爲

如果不用@PathVariable接收大括號裏的值,也可以用bean來接收:

public String getProductInfo(Product pro, HttpServletRequest request,HttpServletResponse response)...

而且也可以設置多個參數

@RequestMapping(value="/info/{pid}/{pname}",method=RequestMethod.GET)

讓我們看下面這段代碼

@RequestMapping(value="/info/{pid}/{pname}",method=RequestMethod.GET)

    public String getProductInfo(Product pro, HttpServletRequest request,HttpServletResponse response) throws Exception {

    

  request.setAttribute("name", pro.getPid()+"___"+pro.getPname());

    

  return "products/list";

          

    }

 

訪問地址: http://localhost:8080/RestFulMvc/api/products/info/00001/23123

得到的結果爲 :

 

下面介紹POST的調用

list.jsp新增form表單如下

<body>
    ${name }
    <form action="<%=basePath%>/api/products/info" method="post">
         <input type="text" name="pid"/> 
         <input type="text" name="pname"/> 
         <input type="submit"/>
    </form>
</body>

JAVA代碼

@RequestMapping(value="/info",method=RequestMethod.POST)
    public String insertProduct(Product pro, HttpServletRequest request,HttpServletResponse response) throws Exception {
    
        request.setAttribute("name", pro.getPid()+"___"+pro.getPname());
          
        return "products/list";
          
    }

form提交後結果爲

執行成功.

正常的FORM提交 , 只需要用對象接就可以了

 

補上 PUT DELETE 就和表單不一樣了, 因爲表單只支持GET和POST

這時候就需要用到ajax,  或者nodejs調用

貼上jsp代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type="text/javascript" src='<%=basePath%>/public/js/jquery-2.1.0.min.js'></script>
<script type="text/javascript">
function savepro(){
 var saveData = {"pid":"aa"}; //發送給服務器的JSON
 $.ajax({
  type : "PUT",
  url : "/RestFulMvc/api/products/info.json",
  data:JSON.stringify(saveData),
  contentType:"application/json",  //發送至服務器的類型
  dataType : "json",     //預期服務器返回類型
  success: function(data){
   alert(data);
  }
    
 })
}
</script>
</head>
<body>
<div>
 <input type="button" value="保存" onclick="savepro()"/>
</div>
</body>

後臺代碼

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping(value="/info",method=RequestMethod.PUT)
    public ModelAndView updateProduct(@RequestBody Product pro, HttpServletRequest request,HttpServletResponse response) throws Exception {
    
  Map<String,Object> map1 = new HashMap<String,Object>();
  map1.put("pid", pro.getPid());
    
  ModelAndView mav=new ModelAndView("products/list",map1);
    
  return mav;
 }

和以往不一樣的是, 後臺接收參數的對象前面 加了個@RequestBody , 這個是用於把傳來的JSON 轉換成接收的對象, 如果是form提交就不需要了, 但如果前臺用的是application/json類型傳進來,就一定要加@RequestBody

得到的結果:

同一資源 多種表述

如果寫完一個方法,返回request到JSP, 可同時手機端需要調接口怎麼辦, 如果前臺的一層皮換成了以nodejs爲服務的框架調用怎麼辦

可以每個需求再寫一個方法返回JSON, 可下面這個可以同一資源,多種返回

spring-servlet.xml加入如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 <!-- ContentNegotiatingViewResolver視圖解析器,利用他就可以配置多種返回值 -->
 <bean  class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">   
        
   <!-- 這裏是否忽略掉accept header,默認就是false -->
   <property name="ignoreAcceptHeader" value="true" />   
     
   <!-- 如果所有的mediaType都沒匹配上,就會使用defaultContentType -->
   <property name="defaultContentType" value="text/html" />   
     
   <property name="mediaTypes">    
    <map>     
     <entry key="json" value="application/json" />      
     <entry key="xml" value="application/xml" />      
    </map>    
   </property>   
  <!-- 默認使用MappingJacksonJsonView生成jsonview-->
  <property name="defaultViews">    
    <list>     
     <bean  class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">        
         <property  name="extractValueFromSingleKeyModel" value="true" />     
      </bean>        
      <bean  class="org.springframework.web.servlet.view.xml.MarshallingView">      
       <property name="marshaller">        
        <bean  class="org.springframework.oxm.xstream.XStreamMarshaller" />        
      </property>      
      </bean>      
     </list>     
    </property>  
  </bean>

 

這樣同一個地址,只要在後面加 .json  mediaTypes就可以把 http://localhost:8080/RestFulMvc/api/products/info/00001/23123.json 的 .json映射到application/json

值得注意的是, 如果不加 <property  name="extractValueFromSingleKeyModel" value="true" />

得出來的Product對象的JSON爲

{"product":{"pid":"00001","pname":"23123"}}

如果想要的結果爲

{"pid":"00001","pname":"23123"}

則不要前面的對象名稱包在外面時, 請加上它

後臺代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping(value={"/info/{pid}"},method=RequestMethod.GET)
    public ModelAndView getProductInfo(@PathVariable String pid, HttpServletRequest request,HttpServletResponse response) throws Exception {
    
          Map<String,Object> map = new HashMap<String,Object>();
            
          Product pro = new Product();
          pro.setPid(pid);
          map.put("name", pid);
          map.put("pro", pro);
            
          ModelAndView mav=new ModelAndView("products/list",map);
            
          return mav;
    }

測試: 輸入地址 :  http://localhost:8080/RestFulMvc/api/products/info/00001.json

得到的結果爲

{"pro":{"pid":"00001","pname":null},"name":"00001"}

 

最後 如果是nodejs  ajax提交的數據,以application/json格式提交時,

接收參數可以在參數前加 @RequestBody

public ModelAndView getProductInfo(@RequestBody Product pro, HttpServletRequest request .....

它可以把json轉換爲對象裏的屬性

 

 -----------------------------------------------------------------------------------------------------------------------

PUT/DELETE方法:從語義上來講,對資源是有破壞性的,PUT更改現有的資源,而DELETE摧毀一個資源,帶有破壞性質的方法有時候會被防火牆或者IT管理人員特別關注,所以當提供PUT/DELETE接口服務時,需要確保服務器前置的防火牆沒有block這些方法。當然如果走的是HTTPS協議,無需擔心這一點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章