SpringMVC简单构造restful, 并返回json

文章要要点:

  1. 快速搭建构造restful的StringMvc

  2. GET, POST , PUT , DELETE的各种调用

  3. 同一资源 多种表述 (ContentNegotiatingViewResolver解析器),既可以返回对象给JSP, 也可以返回JSON

快速搭建构造restful的StringMvc

首现搭建一个简单的restfulMvc框架,  并上配置文件, 后期会增加带JSON返回值的配置

JAR包

web.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
< servlet >
     < servlet-name >spring</ servlet-name >
     < servlet-class >org.springframework.web.servlet.DispatcherServlet</ servlet-class >
     <!-- 可以自定义servlet.xml配置文件的位置和名称,默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如spring-servlet.xml-->
     < init-param >
         < param-name >contextConfigLocation</ param-name >
         < param-value >classpath:config/spring-servlet.xml</ param-value > <!-- 现定义为src下config包里(个人习惯) -->
     </ init-param >
     < load-on-startup >1</ load-on-startup >
    </ servlet >
   
  < servlet-mapping >
      < servlet-name >spring</ servlet-name >
      < url-pattern >/api/*</ url-pattern >
  </ servlet-mapping >
  
  <!-- Spring配置 -->
  < 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配置

?
1
2
3
4
5
6
7
  <!-- 启动注解驱动的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

?
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
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" ;
         
     }
}

@Scope("##") : spring默认的Scope是单列模式(singleton),顾名思义,肯定是线程不安全的.  而@Scope("prototype")

    可以保证每个请求都会创建一个新的实例,  还有几个参数: session  request

    @Scope("session")的意思就是,只要用户不退出,实例就一直存在,

    request : 就是作用域换成了request

@Controller : 不多做解释 , 标注它为Controller

@RequestMapping :是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是   以该地址作为父路径。 比如现在访问getProducts方法的地址就是 :

   http://localhost:8080/项目名/上面web.xml配置(api)/products/list

  l

暂时先介绍两个属性 value和method

具体可以参考我参考的文章 http://blog.sina.com.cn/s/blog_72827fb10101pl9i.html

value: 就是映射的实际地址,这个上面有说过,  而重要的是里面的值 , 有几个比较感兴趣的

   1. 正常的 /list                          访问地址类似 http://localhost:8080/项目名/api/products/list

   2. 带参数的 /info/{proId}          访问地址类似 http://localhost:8080/项目名/api/products/info/0001

method: 请求的method类型 GET POST PUT DELETE等

好,做个测试 JSP代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
<! DOCTYPE  html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
< html >
< head >
< meta  http-equiv = "Content-Type"  content = "text/html; charset=UTF-8" >
< title > 你好</ title >
</ head >
< body >
${name }
</ body >
</ html >

地址栏输入 http://localhost:8080/RestFulMvc/api/products/list

得到结果

 

 

GET, POST , PUT , DELETE的各种调用

刚才写的是第一种GET, 第二种GET:

?
1
2
3
4
5
6
7
8
@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)

让我们看下面这段代码

?
1
2
3
4
5
6
7
8
@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表单如下

?
1
2
3
4
5
6
7
8
< 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代码

?
1
2
3
4
5
6
7
8
@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"}

 

ModelAndView是springmvc自带的重定向方法

第一个参数是返回的地址,和以往一样,  第二个参数以后, 是传给前台的值 .

如果有第二个参数, 没有第三个参数 , 那第二个参数只能是map的

也可以第二个参数为建, 第三个参数为值的方式传给前台,  具体大家可以new一个ModelAndView看看它提供的构造方法

 

 

最后 如果是nodejs  ajax提交的数据,以application/json格式提交时,

接收参数可以在参数前加 @@RequestBody

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

它可以把json转换为对象里的属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值