Spring MVC Rest 学习 二

原创
2014/11/02 23:40
阅读数 1.4W

 1、Controller应该是SpringMVC的核心,Controller中要学习的注解也是多之又多,不过这些注解在程序中的作用确实不可小觑,看看列出这几项:

@Controller  :  定义一个类为控制器,这个与 @Repository 有点像

@RequestMapping : 定义Controller的URL映射以及请求方法

@PathVariable : 定义路径参数,Rest本身就是把资源进行唯一定义,那么URL中使用参数也是唯一定义的一种形式

@ResponseBody : 定义返回结果,这个在ajax请求的时候特别有用,因为不需要跳转到其他URL

@ResponseStatus : 定义返回状态

@RequestParam : 定义请求参数,如果是前台与后台同名参数,那么没必要使用它

........................

    下面贴出Controller的代码

/**
 * <p>项目名称:restful
 * <p>Package名称:com.hnust.controller
 * 文件名称:ResourceController.java 
 * 版本:1.00 
 * 创建日期:2014年10月26日
 * Copyright©2014 HNUST .All Rights Reserved.
 */
package com.hnust.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
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.ResponseBody;

import com.hnust.bean.Message;
import com.hnust.bean.Resource;
import com.hnust.service.ResourceService;

/**
 *
 *@author:Heweipo
 *@version 1.00
 *
 */
@Controller
@RequestMapping("/resource")
public class ResourceController {

	@Autowired
	private ResourceService service;
	
	/**
	 * 
	 * <p>通过id获取资源
	 * 在这里采用@PathVariable注解,同时返回一个String,让SpringMVC自动寻找最合适的视图解析器
	 * 优点是能够找到html视图解析器,但是缺点是,JavaBean转为XML格式,
	 * 需要在 org.springframework.oxm.jaxb.Jaxb2Marshaller绑定JavaBean
	 * 所以 这里Resource一定要进行绑定
	 * @param id
	 * @param model
	 * @return 
	 * @return String    
	 * author: Heweipo
	 */
	@RequestMapping(value="/get/{id}" , method=RequestMethod.GET)
	public String get(@PathVariable("id") String id , ModelMap model){
		model.put("resource", service.getResource(id));
		return "resource";
	}
	
	/**
	 * 
	 * <p>存储resource,另外,关于resource的number参数注入很值得注意,如果URL中携带的参数不能转为
	 * Integer类型,那么是无法继续访问这个方法的!!所以,对于JavaBean最好设置与数据库对应的数据类型
	 * 进行类型约束。
	 * 在这里采用@ResponseBody注解,那么返回的对象将会被对应的视图解析器解析,
	 * 但是不会有html解析器,但是有一个
	 * 优点:javaBean 如果转为 XML 是不需要在spring-servlet 中
	 * org.springframework.oxm.jaxb.Jaxb2Marshaller 绑定的
	 * @param resource
	 * @param model 
	 * @return void    
	 * author: Heweipo
	 */
	@RequestMapping(value="/put" , method=RequestMethod.PUT)
	public @ResponseBody Message put(Resource resource , ModelMap model){
		Message message = new Message();
		if(StringUtils.isEmpty(resource.getId()) 
		        || StringUtils.isEmpty(resource.getName())){
			message.setMsg("请输入id 和 用户名");
			message.setResult("faile");
			return message;
		}
		service.insertResource(resource);
		message.setMsg("数据已经存储");
		message.setResult("success");
		return message;
	}
	
	/**
	 * 
	 * <p>通过id更新resource
	 * @param resource
	 * @param model
	 * @return 
	 * @return Message    
	 * author: Heweipo
	 */
	@RequestMapping(value="/post" , method=RequestMethod.POST)
	public @ResponseBody Message post(Resource resource , ModelMap model){
		Message message = new Message();
		if(StringUtils.isEmpty(resource.getId())){
			message.setMsg("id不能为空");
			message.setResult("faile");
			return message;
		}
		service.updateResource(resource);
		message.setMsg("数据已经修改");
		message.setResult("success");
		return message;
	}
	
	/**
	 * 
	 * <p>通过id删除资源
	 * @param id
	 * @param model
	 * @return 
	 * @return Message    
	 * author: Heweipo
	 */
	@RequestMapping(value="/delete/{id}" , method=RequestMethod.DELETE)
	public @ResponseBody Message delete(@PathVariable("id")String id, ModelMap model){
		Message message = new Message();
		service.deleteResource(id);
		message.setMsg("数据已删除");
		message.setResult("success");
		return message;
	}
	
}

注意的几点说明:

1)关于请求参数自动封装问题,当我们在方法的形参中采用JavaBean时,SpringMVC会把请求的参数中与JavaBean对应的属性封装成JavaBean的一个实例返回,如果有些属性没有值,他就为空;如果属性值进行赋值是类型转换发生错误,则无法请求URL。封装好的JavaBean实例会存储在ModelMap中,并且以JavaBean的类名首字母小写的形式作为key值,所以,你可以 这样获取 model.get('resource');实际这也是很常用的,因为 XML解析的时候需要一个根元素,那么,如果我们的model中存储太多的元素XML是无法解析的。这个Controller不存在这种情况,原因是我是用了@ResponseBody

2)关于返回值的问题,@ResponseBody 是返回值的标识,尤其是对象解析的时候特别有用。而且,使用@ResponseBody后,对于XML解析的对象都可以不用在spring-servlet中进行绑定,然而,如果我们有些时候需要返回一个html,或者Json,或者XML的时候,我们就不会去使用@ResponseBody,而是采用String的形式,把返回的对象存储在model中。当返回值为null时效果与@ResponseBody 是一样的。

下面是修改后的代码:

/**
	 * 
	 * <p>通过id更新resource
	 * Message 一定要在 org.springframework.oxm.jaxb.Jaxb2Marshaller 绑定
	 * @param resource
	 * @param model
	 * @return 
	 * @return Message    
	 * author: Heweipo
	 */
	@RequestMapping(value="/post" , method=RequestMethod.POST)
	public String post(Resource resource , ModelMap model){
		// 这里清除掉SpringMVC帮我们封装的JavaBean
		model.remove("resource");
		Message message = new Message();
		// 这里存储我们需要解析的JavaBean
		model.put("message", message);
		if(StringUtils.isEmpty(resource.getId())){
			message.setMsg("id不能为空");
			message.setResult("faile");
			return null;
		}
		service.updateResource(resource);
		message.setMsg("数据已经修改");
		message.setResult("success");
		// 返回空的效果和使用@ResponseBody是一样的,但是原理不同,
		// @ResponseBody 貌似采用了Servlet3.0 的异步特性
		return null;
	}

对应的spring-servlet.xml源代码:

 <!-- XML 与 Java 数据转换  -->
	  <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
			 <!-- 需要在这里绑定,原因是controller里没有采用@ResponseBody进行返回 -->
			 <value>com.hnust.bean.Message</value>
			</list>
		</property>
	  </bean>

2 请求类型

    在@RequestMapping中我们对method进行赋值,如果赋值了那么必须按照对应的请求方法进行访问,否者出现405.该项目中采用测试工具进行测试:

工具采用:Firefox 的RestClient 插件 https://addons.mozilla.org/zh-CN/firefox/addon/restclient/

1)新增资源:put  http://localhost:8080/restful/resource/put?id=id_888&name=ireport&number=89

<message>
<msg>数据已经存储</msg>
<result>success</result>
</message>

2)更新资源 post http://localhost:8080/restful/resource/post?id=id_888&name=node.js&number=12

<message>
<msg>数据已经更新</msg>
<result>success</result>
</message>

3) 删除资源 delete http://localhost:8080/restful/resource/delete/id_888

<message>
<msg>数据已删除</msg>
<result>success</result>
</message>

3 关于返回内容格式

    内容协商机制很简单,有两种方式,一种是该项目中使用的视图渲染进行内容协商,另外一种则是进行类型转换,本项目中源码如下:

  <!-- 主要是进行Controller 和 URL 的一些注解绑定,这里可以进行转换器配置:只有配置好了转换器才能进行类与JSON和XML的转换,当然只是针对基于转换器协商资源表述 -->
	  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
	  
	  
	   <!-- XML 与 Java 数据转换  -->
	  <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<!--common XML 映射  JavaBean 注册  -->
				<value>com.hnust.bean.Resource</value> 
				<!-- 不需要在这里绑定,原因是controller里采用ResponseBody进行返回 -->
				<!-- <value>com.hnust.bean.Message</value>  -->
			</list>
		</property>
	  </bean>
	  
	  <!-- 基于视图渲染进行协商资源表述  -->
	  <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
	  	<!-- restful 是否采用扩展名的方式确定内容格式,id.json 返回JSON格式 -->
	    <property name="favorPathExtension" value="true"></property>
	  
	    <!-- restful 是否采用参数支持确定内容格式,id?format=json 返回JSON格式 -->
	    <property name="favorParameter" value="true"></property>
	  
	    <!-- restful 是否忽略掉accept header,Accept:application/json -->
	    <property name="ignoreAcceptHeader" value="false"></property>
	    
	    <!-- 基于视图按顺序解析  -->
	    <property name="order" value="1" />
	    
	    <!-- 对采用扩展名,参数新式的 URL 进行获取对应的 accept  -->
		<property name="mediaTypes">
		    <map>
		    	<entry key="json" value="application/json"/>
		        <entry key="xml" value="application/xml"/>
		        <entry key="html" value="text/html"/>
		    </map>
		</property>
		
		<!-- 如果扩展名,参数甚至header 信息都没有找到对应的accept时  -->
		<property name="defaultContentType" value="text/html"/>
		
		<!-- 采用对应的视图进行渲染  -->
		<property name="defaultViews">
		    <list >
				<!-- 转换Java对象为XML格式数据 -->
				<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
					<constructor-arg ref="jaxbMarshaller" />
				</bean>
				
				<!-- 转换Java对象为JSON 格式数据 -->
				<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/> 
		    </list>
		</property>
		<!-- 采用对应的视图进行渲染  -->
		<property name="viewResolvers">
		    <list >
		    	<!-- 查找在上下文中定义了ID的Bean,并且定位该ID  -->
		        <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
		        <!-- 对Controller中返回的视图实例进行解析,并且组装URL定位到对应的资源  -->
		        <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
					<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
					<property name="prefix" value="/WEB-INF/jsp/"/>
					<property name="suffix" value=".jsp"/>
				</bean>
		    </list>
		</property>
	</bean>

然而如果使用转换机制的话:

<!-- 输出字符串内容,非路径 -->
	<bean id="stringConverter"
		class="org.springframework.http.converter.StringHttpMessageConverter">
		<property name="supportedMediaTypes">
			<list>
				<value>text/plain;charset=UTF-8</value>
			</list>
		</property>
	</bean>

	<!-- JSON -->
	<bean id="jsonConverter"
		class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
	 <bean id="marshallingHttpMessageConverter"
          class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
        <constructor-arg ref="jaxbMarshaller"/>
        <property name="supportedMediaTypes" value="application/xml" />
    </bean>

    <!-- 基于转换器进行内容协商 -->
    <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <!-- XML转换器需要绑定需要转换的类 -->
        <property name="classesToBeBound">
            <list>
                <value>com.hnust.bean.Resource</value>
            </list>
        </property>
    </bean>
		
    <!-- 注册对象转换器  -->	
    <bean
	class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	    <property name="messageConverters">
		<list>
			<ref bean="stringConverter" />
			<ref bean="jsonConverter" />
                        <ref bean="marshallingHttpMessageConverter"/>
		</list>
	</property>
    </bean>

4 pom文件,获取jar包

  	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>3.2.8.RELEASE</version>
	</dependency>
  
  	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>3.2.8.RELEASE</version>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-oxm</artifactId>
		<version>3.2.8.RELEASE</version>
	</dependency>
	
  
 	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jstl</artifactId>
		<version>1.2</version>
	</dependency>
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.1.3</version>
	</dependency>
	<dependency>
		<groupId>net.sf.json-lib</groupId>
		<artifactId>json-lib</artifactId>
		<version>2.4</version>
		<classifier>jdk15</classifier>
	</dependency>
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-mapper-asl</artifactId>
		<version>1.9.13</version>
	</dependency>
  
  	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>servlet-api</artifactId>
		<version>3.0-alpha-1</version>
	</dependency>

5 项目源码链接:

 http://download.csdn.net/detail/wp562846864/8113077

说明:源码中没有jar包,因为Maven项目,jar包就通过pom文件去取吧,如果实在需要,可以留言.....












展开阅读全文
打赏
1
22 收藏
分享
加载中
更多评论
打赏
0 评论
22 收藏
1
分享
返回顶部
顶部