`
houniao
  • 浏览: 76433 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring mvc3提高生产力之——利用annotation使前后台数据交互更透明

阅读更多

这周花了点时间弄了一下spring mvc3,打算整理一个cheatsheet出来,方便后来者快速上手。


服务端数据到客户端
  1. 返回页面,Controller中方法返回String,String对应的是view的位置,如果需要携带数据通过model(相当于一个Map)传递到view, view中使用jstl的EL表达式来绑定model带来的数据。
    @RequestMapping(value="/getPojoView", method=RequestMethod.GET)
    public String getPojoView(Model model){
      Pojo pojo = new Pojo();
      pojo.setPojoName("testName");
      pojo.setPojoValue("testValue");
      model.addAttribute(pojo);
      return"sample/pojoView";
    }
    
     
  2. 返回Json对象,利用@ResponseBody来实现。
    @RequestMapping(value="/getPojoJson", method=RequestMethod.GET)
    public  @ResponseBody Pojo getPojoJson(){
      Pojo pojo = new Pojo();
      pojo.setPojoName("testName");
      pojo.setPojoValue("testValue");
    
      return pojo;
    }
    
      注:spring mvc自动将java对象转化成了json对象传回了客户端,返回对象可以是Pojo也可以是List

  3. 直接操作Response自己实现想要的效果。
    @RequestMapping(value="/getCustomResponse", method=RequestMethod.GET)
    public void getCustomResponse(HttpServletResponse response){
      //操作response...
    }
    
      注:response为spring根据方法的type类型注入的
客户端数据到服务端
  1. 通过URL传回参数:
    view
    <script type="text/javascript"src="jquery-1.4.min.js"></script>
    <h1>button与链接效果一致</h1>
    <a href="simple?name=text&age=28">simple</a><button onclick="simple()">simple</button><br/>
    <script type="text/javascript">
    function simple(){
      $.getJSON("simple",{"name":"nameJsonTest","age":"100"},function(){});
    }
    </script>
    <a href="list?names[]=aaaa&names[]=bbbb">list</a><button onclick="list()">list</button><br/>
    <script type="text/javascript">
    function list(){
      $.getJSON("list",{"names":["name1","name2","name3"]},function(){});
    }
    </script>
    <a href="pojo?pojo[pojoName]=hahaha&pojo[pojoValue]=kkkkkk">pojo</a><button onclick="pojo()">pojo</button><br/>
    <script type="text/javascript">
    function pojo(){
      $.getJSON("pojo",{"pojo":{"pojoName":"testName","pojoValue":"testValue"}},function(){});
    }
    </script>
    <a href="rest/10/2">rest</a><button onclick="rest()">rest</button><br/>
    <script type="text/javascript">
    function rest(){
      var pageSize = 20;
      var pageNo = 3;
      $.getJSON("rest/"+pageSize+"/"+pageNo,{},function(){});
    }
    </script> 
    controller
    package sample;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Controller
    @RequestMapping(value="/urlparam")
    public class UrlParamController {
      @RequestMapping(value="/", method=RequestMethod.GET)
      public String index(){
        return"urlparam/index";
      }
     
      @RequestMapping(value="/simple", method=RequestMethod.GET)
      public void simple(@RequestParam String name, @RequestParam Integer age){
        System.out.println("name:"+name);
        System.out.println("age:"+age);
      }
    
      //list内不能放POJO对象
      @RequestMapping(value="/list", method=RequestMethod.GET)
      public void list(@RequestParam("names[]") String[] names){ 
      //也可以用List<String> names来接收
      for(String name : names){
        System.out.println("name:"+name);
      }
    }
    
      //单URL目前还不支持POJO对象,只能支持键值对,希望spring以后有所改善
      @RequestMapping(value="/pojo", method=RequestMethod.GET)
      public void pojo(@RequestParam("pojo[pojoName]") String name, @RequestParam("pojo[pojoValue]") String value){
        System.out.println("name:"+name);
        System.out.println("value:"+value);
      }
    
      @RequestMapping(value="/rest/{pageSize}/{pageNo}", method=RequestMethod.GET)
      public void rest(@PathVariable Integer pageSize, @PathVariable Integer pageNo){
        System.out.println("pageSize:"+pageSize);
        System.out.println("pageNo:"+pageNo);
      }
    } 

  2. 通过POST表单传回参数:
    方式同与url的是一致的,需要将method=RequestMethod.POST,不过有中文的话一般都用post来避免转码。一般ajax的时候用$.post而不能使用jQuery插件json的$.postJSON。下面会讲到。

  3.  通过使用jQuery插件json的$.postJSON传回参数:
    $.postJSON返回的是:application/json,
    $.post返回的是: application/x-www-form-urlencoded
    spring会将postJSON传回的json字符串转换成对象再将对象丢给带有@RequestBody的形参。
     由于json字符串直接转换为对象,所以@RequestBody只能接收一个对象还需要属性一一对应,不能多传参数。此方式可以传POJO,也可以传List<POJO>。
    $.postJSON('url', {"name":"testName","age":"28"},function(){});
    class Pojo{
      private Long id;
      private String name;
      private Integer age;
      //get,set...
    }
    @RequestMapping(value="pojo", method=RequestMethod.POST)
    publicvoid sentPojo(@RequestBody Pojo pojo){
      System.out.println(pojo.getPojoName());
      System.out.println(pojo.getPojoValue());
    }
    
      注:目前对于一对象,附带几个简单参数的解决办法是将简单参数通过为REST的url路径参数来传送。

  4.  直接拿到Request来操作:
    @RequestMapping(value="/", method=RequestMethod.GET)
      public String withRequest(HttpServletRequest request){
         //操作request...
       return"someview";
    }
     

以上controller内的方法的形参, 除了@RequestBody和@RequestParam不能同时声明外,都可以进行组合来满足各种需求。

 

小结:spring mvc3充分利用了annotation的好处将参数传递过程中的转换全部变为了透明,这样省去了程序员对参数进行一些无聊的转换,这肯定能提高不少效率。另一方面想说的是spring的@RequestBody还可以做的更好,如果能允许多个对象同时传送,那这个东西就十分好了。

分享到:
评论
26 楼 wilsonchen 2013-03-27  
yuanzhuohang 写道
引用

以上controller内的方法的形参, 除了@RequestBody和@RequestParam不能同时声明外,都可以进行组合来满足各种需求。

LZ,@RequestBody和@RequestParam可以同时声明,你看我下面的代码。
经过测试,这可以做得到的。
@RequestMapping(method=RequestMethod.POST, params="del")
@ResponseBody
public ArticleSort deleteArticleSort(@RequestBody ArticleSort articleSort, @RequestParam("cascade") boolean isCascade) throws DefaultViewNoFoundException{
	//...
}

[img]
http://dl.iteye.com/upload/picture/pic/106118/137eedc6-0dd8-3535-90aa-f974d659c37a.png
[/img]


是不可以的吧,你在client是怎样请求的呢?
25 楼 yuanzhuohang 2012-01-18  
引用

以上controller内的方法的形参, 除了@RequestBody和@RequestParam不能同时声明外,都可以进行组合来满足各种需求。

LZ,@RequestBody和@RequestParam可以同时声明,你看我下面的代码。
经过测试,这可以做得到的。
@RequestMapping(method=RequestMethod.POST, params="del")
@ResponseBody
public ArticleSort deleteArticleSort(@RequestBody ArticleSort articleSort, @RequestParam("cascade") boolean isCascade) throws DefaultViewNoFoundException{
	//...
}

[img]
http://dl.iteye.com/upload/picture/pic/106118/137eedc6-0dd8-3535-90aa-f974d659c37a.png
[/img]
24 楼 yin_bp 2011-05-07  
caoyangx 写道
springmvc的确非常不错,运行速度快,开发速度更快,不过在标签方面需要向前辈学习,springmvc的标签不是很丰富,希望能够继续完善。


可以看看开源项目bbossgroups中的mvc框架,功能和spring mvc 3差不多,配套的标签体系也非常完善,持久层套件的功能也不亚于spring jdbc,呵呵,bboss aop对quartz任务调度、cxf webservice的支持、组件异步调用功能的支持也比spring要强大很多哦,呵呵,详情可看看bbossgroups项目的官方博客:http://yin-bp.iteye.com/
也可以直接看ppt介绍。

bbossgroups源码工程(http://sourceforge.net/projects/bboss/files/bbossgroups-3.1/bbossgroups-3.1-src.zip/download
mvc框架的demo war包(http://sourceforge.net/projects/bboss/files/bbossgroups-3.1/mvcdemo-war.zip/download
简单mvc eclipse开发工程,开箱即用(http://sourceforge.net/projects/bboss/files/bbossgroups-3.1/mvcdemo-eclipse.zip/download
bbossgroups 培训ppt(http://sourceforge.net/projects/bboss/files/bbossgroups-3.1/bbossgroups%203.1%20in%20action.zip/download

23 楼 hd540718584 2011-04-23  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {    
       //Controller访问前进行拦截,允许通过返回true,否则返回false    
       ...... 
       此处怎么修改用户提交的值,然后action里得到的值是被修改后的值,达到过滤非法字符的作用。 
    } 
有没有高人用spring3mvc,过滤关键字,把用户提交的值进行修改,比如:aaa字符换成**
22 楼 pengjj2 2010-12-24  
爪哇岛岛主 写道
我真无语,入门级的啊

可以像struts2一样自动类型转换吗?为什么我试不出,入门级,你说下?怎么实现

对象 department, 成员变量 id,name,departmentparent(同样是department对象)

一对一的关系。

页面上<input type="text" id="name" name="name" />
         <input type="text" id="department.departmentparent.name" name="department.departmentparent.name" />

后台接受对象为 department,

你能传递 department.departmentparent。里面有值???

你试过吗??
21 楼 爪哇岛岛主 2010-12-24  
我真无语,入门级的啊
20 楼 pengjj2 2010-12-23  
是不是还是不支持对象嵌套啊
19 楼 tomcat4 2010-12-21  
零配置的代码是JSP+JavaBean,其实看看Spring 3的Controller的Requestmapping也是一种hardcode,回到了<form action="save.jsp"></form>,只不过把action定位到了一个具体的方法,而不是JSP页面了!
回过头来看,从JSP
<form action="save.jsp>(无需配置)
到servlet<form action="saveServlet>(配置web.xml)个人感觉Servlet中的监听器、过滤器是JSP不可替代的,但是从配置的简单性、可维护性(JSP不需要重新build)来说,JSP优势是大大的
到struts1<form action="saveAction.do>(头大的struts1的配置文件)
再到struts2<form action="saveAction.action>(还是配置文件,提出“习惯优于配置,有点回头的感觉”)
终于回到spring3 MVC推荐的@RequestMapping的annotation(典型的hashcode,和action="save.jsp几乎没有区别",对于编程人员来说,form被post到一个url,根据这个url跟踪到哪个Controller,哪个method确实是一个比较浪费时间的事)
18 楼 181054867 2010-12-02  
楼主能不能做一个纯显示的例子,比如:提交一些条件,按条件查询出List,显示在JSP页面上!
很希望看到整个流程如何走到最终的页面来!
17 楼 houniao 2010-06-05  
香烟与酒 写道
顶楼主下,能否把那个配置文件贴出来看看

我本来想弄个开源项目,把spring mvc的一些常见需求的实践方式整合一下,比如楼上说:multiview resolver, 乱码的问题,json多对象传递的问题,表单验证数据回显的问题,比较复杂的跳转需求等等,很多都是一些常见的问题
不过对于刚使用的人来说或多或少会浪费自己的时间来弄这些东西
如果把这些东西做成一个项目,再出一个已经解决问题的列表,大家根据问题列表马上找到自己想要实现的效果,我觉得还是有一定的价值的

大家如果比较急的话可以去看下spring官方提供的例子:
https://src.springframework.org/svn/spring-samples
它下面有个mvc-ajax
16 楼 houniao 2010-06-05  
Angel_Night 写道
楼主 我如何在 getPojoView 中直接跳转到 getPojoJson中

比如说:
我写了个login
我login成功之后 进入index.

index里面有我的离线消息..
所以在进这个页面时 我需要先给页面放入离线消息
所以 我写了一个 index 的 method=RequestMethod.GET 给页面赋值

问题我现在的做法是...
response.sendRedirect(request.getContextPath() + "/result/" + personInfoId);


我不想在login中加入index的数据
而login只管登陆 不管给index赋值

楼主如何做啊


我不明白你为什么不把personID放session里,再根据personID来取info
如果非要login来做跳转,你可以考虑将login当成一个proxy,如:http://...login?url=http://infopage
这样login只做放sessionid,然后根据你给定的链接来跳转
15 楼 realcbb 2010-06-01  
请教楼主,用@ResponseBody时,返回字符串可以,但是返回其他形式的对象,如List就html状态码406了.另外返回字符串时中文乱码.
14 楼 Angel_Night 2010-06-01  
楼主 我如何在 getPojoView 中直接跳转到 getPojoJson中

比如说:
我写了个login
我login成功之后 进入index.

index里面有我的离线消息..
所以在进这个页面时 我需要先给页面放入离线消息
所以 我写了一个 index 的 method=RequestMethod.GET 给页面赋值

问题我现在的做法是...
response.sendRedirect(request.getContextPath() + "/result/" + personInfoId);


我不想在login中加入index的数据
而login只管登陆 不管给index赋值

楼主如何做啊
13 楼 Angel_Night 2010-06-01  
mycybyb 写道
icanfly 写道
mycybyb 写道
如此繁杂的注解实在是耗费脑细胞啊

楼上这位兄台,可否说说struts2的xml配置死的脑细胞如何?可否说说struts2的annotation配置死的脑细胞如何?

为什么呢?我也不用struts2啊。我用自己的MVC框架,零配置的。


那需要遵守你的规则吧...

需要按照你框架的约定走吧...

记住那些对于你来说 不是耗费脑细胞..
对于你以外的人呢?
12 楼 mycybyb 2010-06-01  
icanfly 写道
mycybyb 写道
如此繁杂的注解实在是耗费脑细胞啊

楼上这位兄台,可否说说struts2的xml配置死的脑细胞如何?可否说说struts2的annotation配置死的脑细胞如何?

为什么呢?我也不用struts2啊。我用自己的MVC框架,零配置的。
11 楼 icanfly 2010-06-01  
mycybyb 写道
如此繁杂的注解实在是耗费脑细胞啊

楼上这位兄台,可否说说struts2的xml配置死的脑细胞如何?可否说说struts2的annotation配置死的脑细胞如何?
10 楼 香烟与酒 2010-06-01  
顶楼主下,能否把那个配置文件贴出来看看
9 楼 mycybyb 2010-05-31  
如此繁杂的注解实在是耗费脑细胞啊
8 楼 hzd822 2010-05-31  
@RequestMapping(value="pojo", method=RequestMethod.POST)  
publicvoid sentPojo(@RequestBody Pojo pojo){  
  System.out.println(pojo.getPojoName());  
  System.out.println(pojo.getPojoValue());  
} 

这个有点问题,用楼主说的方法用$postJson跳过来的时候到java端会报个无法转换json类型的异常,光@RequestBodyspring好像是无法转换的吧,我用的是spring3.0.2。查了一下资料,应该是用到一个依赖转换
在xml进行定义:
	<!-- spring mvc注解支持 -->
	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="messageConverters">  
            <util:list id="beanList">  
                <ref bean="mappingJacksonHttpMessageConverter" />  
            </util:list>  
        </property>
	</bean>
	
	<bean id="mappingJacksonHttpMessageConverter"  
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> 



用到2个依赖jar包
jackson-core-lgpl-1.4.2.jar
jackson-mapper-lgpl-1.4.2.jar
注意版本,spring3.0.2仅支持1.4.2的jacksonjar包

7 楼 香烟与酒 2010-05-31  
请教下楼主,在配置多个视图解析器怎么做啊,这几天就是烦这个配置的事情.谢谢了

相关推荐

Global site tag (gtag.js) - Google Analytics