文档章节

Spring MVC Rest 学习 二

learn_more
 learn_more
发布于 2014/11/02 23:40
字数 2220
阅读 6897
收藏 22

 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文件去取吧,如果实在需要,可以留言.....












© 著作权归作者所有

learn_more
粉丝 94
博文 240
码字总数 210196
作品 0
深圳
程序员
私信 提问
Spring MVC Rest 返回值为空

问题描述: 采用Spring Restful ,可以通过浏览器的地址栏URL正确访问后台且不报错误,但是前台总是获取不到数据,前台也是收到了后台的响应,就是没有数据。 具体如下: 采用 Spring Restf...

learn_more
2015/03/16
0
0
java – 混合Spring MVC Spring数据休息导致奇怪的MVC响应

我有两个JPA实体,一个具有SDR导出的存储库,另一个具有Spring MVC控制器和一个未导出的存储库. MVC暴露实体引用了SDR管理实体.参见下面的代码参考. 从UserController检索用户时,问题出现. SDR...

小刀爱编程
2018/10/15
0
0
spring boot简单实现rest服务

问题 最开始我是想使用Spring MVC搭建一个简单的REST服务,去官网看了看教程,现在Spring胆越来越大了,需要我集成一个maven的父项目,我并不愿意继承Spring的父项目。然后,就开始下面的探索...

亚林瓜子
2018/06/12
0
0
Portal-Basic Java Web 应用开发框架 v2.6.2(源码、示例、文档及 v3.0 新特性介绍)

Portal-Basic Web 应用开发框架(简称 Portal-Basic)是一套功能完备的高性能 Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 访问接口(已内置 Hibernate、MyBatis 和 JDBC 支持)...

伤神小怪兽
2012/11/28
980
7
Spring MVC静态资源url映射处理

今天发现网上有些坑爹的博客,估计博主自己也没要用过,就写了出来,害得我折腾半天。鉴于避免其他同学出现类似的情况,写出来,也请大家指正。 优雅REST风格的资源URL不希望带 .html 或 .d...

钟声已经敲响
2016/10/10
503
0

没有更多内容

加载失败,请刷新页面

加载更多

3分钟看懂Activity启动流程

背景介绍 从事开发到了一定阶段,想要提高就必须搞明白系统的一些工作原理。为什么?因为只有明白了这些,你才能针对平台的特性写出优质的代码。当遇到棘手的问题时,你才能更快速的结合系统...

天王盖地虎626
28分钟前
1
0
机器学习算法GPU版本安装配置

##XGBoost for GPU安装https://blog.csdn.net/weixin_30963287/article/details/79145107https://blog.csdn.net/wl2858623940/article/details/80546140https://blog.csdn.net/u01164186......

KYO4321
31分钟前
1
0
微软展开训练AI来推Windows 10 1903版自动更新

Windows 10 May 2019(1903版)正式释出将近一个月,或许已经有用户自主安装更新了,不过微软认为还不够多。微软表示将开始训练机器学习(machine learning)技术,帮助1803版本以前的PC更新...

yisy5566
今天
0
0
前后端分离-前端搭建(Vue)(2)

先安装node.js以及npm 现在基本的node.js都包含有npm,下载安装后, 可以在cmd命令里输入 node -v 和npm -v 分别查看安装的版本 两个都显示了版本就是安装ok 这次我们使用JetBrains WebStor...

咸鱼-李y
今天
0
0
好程序员web前端教程分享三大前端框架相关问题

  好程序员web前端教程分享三大前端框架相关问题,三大前端框架,有没有哪个框架的组件间交互像js的方法传值一样简单? 首先框架组件通信是为了方便组件模块之间进行数据交互的,因为框架的...

好程序员IT
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部