Spring MVC(10):REST 支持 Ajax+Spring MVC 实例
Spring 对于 REST 的支持
REST
- 表述性(Respresesntational):REST资源实际上可以使用各种形式来进行表述,包括 XML、JSON、HTML 等;
- 状态(State):当使用 REST 时候,我们更加关注资源的状态,而非对资源采取的行为;
- 转移(Transfer):REST 涉及资源数据转移时,它以某种表述形式从一个应用程序转移到另一个应用程序;
- Create:POST
- Read:GET
- Update:PUT、PATCH
- Delete:DELETE
- 控制器可以处理所有 HTTP 方法(包括 POST、GET、PUT、DELETE);
- 控制器借助 @PathVariable 注解,可以处理参数化的 URL;
- 借助 Spring 的视图和视图解析器,资源可以以多种方式进行表述,包括将模型数据渲染为 XML、JSON、Atom、RSS 等;
- 借助 @ResponseBody 注解,各种 HttpMethodConverter,可以替换基于视图的渲染方式;
- 借助 @ResquestBody 注解,各种 HttpMethodConvterter ,可以实现将传输的 HTTP 数据转化为传入控制器处理方法的 POJO;
- 借助 RestTemplate,Spring 应用可以很方便地处理和使用 REST 资源;
HTTP数据转化器 HttpMessageConverter<T>
Spring 提供了 HttpMessageConverter<T> 接口用于将请求信息转换为T类型的对象,将T类型的对象输出为响应信息;
![](/assets/blank.gif)
- StringHttpMessageConverter;
- ByteArrayHttpMessageConverter;
- SourceHttpMessageConverter;
- AllEncompassingFormHttpMessageConverter;
<!--装载 HttpMessageConverter 适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
p:messageConverters-ref="messageConverters"/>
<!--转换器列表-->
<util:list id="messageConverters">
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
</util:list>
<!--自动注册默认MessageConverter-->
<mvc:annotation-driven/>
服务端使用 HTTP 转换器
1)@RequestBody / @ResponseBody
@Controller
public class UserController {
private static final Logger log = LogManager.getLogger();
//接收客户端表单信息,使用 @RequestBody 将该请求正文转换后标识到方法入参
@RequestMapping(value="/handleForm",method= RequestMethod.POST)
public String handleFrom( @RequestBody String requestBody){
log.debug(requestBody);
return "success";
}
//向客户端发送一张imageId相关的图片的响应流,使用 @ResponseBody 将输出对象转换为相应的响应正文
@ResponseBody
@RequestMapping("/getImg/{imageId}")
public byte[] getImage(@PathVariable("imageId") String imageId) throws IOException {
log.debug("imageId: " + imageId);
Resource res = new ClassPathResource("testimg"+imageId+".jpg");
byte[] fileData = FileCopyUtils.copyToByteArray(res.getFile());
return fileData;
}
}
2)HttpEntity<T> / ResponseEntity<T>
//同 handleForm 方法
@RequestMapping("/handleForm2")
public String handleForm2( HttpEntity<String> httpEntity){
log.debug(httpEntity.getHeaders());
log.debug(httpEntity.getBody());
return "success";
}
//同 getImage 方法
@RequestMapping("/getImg2/{imageId}")
public ResponseEntity<byte[]> getImage2(@PathVariable("imageId") String imageId) throws IOException {
log.debug("imageId: " + imageId);
Resource res = new ClassPathResource("testimg"+imageId+".jpg");
byte[] fileData = FileCopyUtils.copyToByteArray(res.getFile());
//创建响应对象,将图片字节流加入响应正文
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(fileData, HttpStatus.OK);
return responseEntity;
}
客户端使用HTTP转换器
getForObject / getForEntity | 使用 GET 方法发送请求,获取服务器响应 |
postForObejct / postForEntity / postForLocation | 使用 POST 方法发送请求,获取服务器响应 |
put、patchForObject / patchForEntity | 使用 PUT、PATCH 方法发送请求,获取服务器响应 |
delete | 使用 DELETE 方法发送请求,获取服务器响应 |
exchange | 使用自定义方法发送请求,获取服务器响应 |
- StringHttpMessageConverter;
- ByteArrayHttpMessageConverter;
- SourceHttpMessageConverter;
- ResourceHttpMessageConverter;
- AllEncompassingFormHttpMessageConverter;
如果需要添加其他的转换器,可以通过 RestTemplate#setMessageConverter(List<HttpMessageConverter<?>> messageConverters) 方法手动注册其他转换器;
//调用服务端 UserController#handleForm 服务接口
@Test
public void testHandleForm(){
//创建RestTemplate
RestTemplate restTemplate = new RestTemplate();
//构建表单对象
MultiValueMap<String,String> form = new LinkedMultiValueMap<>();
form.add("userId","1");
form.add("userName","name");
form.add("userAge","20");
//发送请求
restTemplate.postForLocation("http://127.0.0.1:8080/project/handleForm",form);
}
//调用服务端 UserController#getImage 服务接口
@Test
public void testGetImage() throws Exception{
//创建RestTemplate
RestTemplate restTemplate = new RestTemplate();
//发送请求,接收服务接口的响应,将响应正文转换为 byte[] 对象
byte[] response = restTemplate.postForObject("http://127.0.0.1:8080/project/getImg/{itemId}",null,byte[].class,"001");
Resource res = new PathResource("./img_copy.jpg");
FileCopyUtils.copy(response,res.getFile());
}
//调用服务端 UserController#handleForm2 服务接口
@Test
public void testHandleForm2(){
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,String> form = new LinkedMultiValueMap<>();
form.add("userId","1");
form.add("userName","name");
form.add("userAge","18");
restTemplate.postForLocation("http://127.0.0.1:8080/project/handleForm2",form);
}
//调用服务端 UserController#getImage2 服务接口
@Test
public void testGetImage2() throws Exception{
RestTemplate restTemplate = new RestTemplate();
byte[] response = restTemplate.postForObject("http://127.0.0.1:8080/project/getImg2/{itemId}",null,byte[].class,"001");
Resource res = new PathResource("./img_copy.jpg");
FileCopyUtils.copy(response,res.getFile());
}
使用 HTTP 转换器处理 XML、JSON 数据
- MarshallingHttpMessageConverter:处理 XML请求/响应
- Jaxb2RootElementHttpMessageConverter:处理XML请求/响应,底层使用JAXB
- MappingJackson2HttpMessageConverter:处理JSON请求/响应
服务端
<!--装载 HttpMessageConverter 适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
p:messageConverters-ref="messageConverters"/>
<!--转换器列表-->
<util:list id="messageConverters">
<!--XML消息转换器-->
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"
p:marshaller-ref="xmlMarshaller"
p:unmarshaller-ref="xmlMarshaller"/>
<!--JSON 消息转换器-->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</util:list>
<!--自动注册默认MessageConverter-->
<mvc:annotation-driven/>
<!--装载Marshaller,使用XStream处理XML-->
<bean id="xmlMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="streamDriver"> <!--声明xml处理驱动-->
<bean class="com.thoughtworks.xstream.io.xml.StaxDriver" /> <!--使用STAX对消息进行处理-->
</property>
<property name="annotatedClasses"> <!--声明使用XStream注解进行XML转换规则的类-->
<list>
<value>site.assad.model.User</value>
</list>
</property>
</bean>
package site.assad.model;
@XStreamAlias("user")
public class User implements Serializable{
@XStreamAlias("id")
private int userId;
@XStreamAlias("name")
private String userName;
@XStreamAlias("age1")
private int age;
//省略 getter,setter
}
//输出 User 对象 XML / JSON 格式正文的响应
@RequestMapping(value="/getUser/{userId}",method=RequestMethod.GET)
public ResponseEntity<User> handleUser( @PathVariable("userId") int userId){
User user = userService.getUser(userId);
ResponseEntity<User> responseEntity = new ResponseEntity<>(user,HttpStatus.OK);
log.debug(responseEntity.getHeaders());
log.debug(responseEntity.getBody());
return responseEntity;
}
//从请求中获取 XML / JSON 正文,并转化为 User 对象
@ResponseBody
@RequestMapping(value="/putUser",method=RequestMethod.POST)
public String getUser( HttpEntity<User> requestEntity ){
User user = requestEntity.getBody();
log.debug(user);
return "server get User:" + user;
}
客户端
//接收服务器 XML 响应正文,并转化为 User
@Test
public void testHanldeUserXML(){
RestTemplate restTemplate = buildRestTemplate();
//构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML)); //请求头说明接收的响应正文类型为XML格式
//构建请求对象
HttpEntity<String> requestEntity = new HttpEntity<>(null,headers);
//发送请求,获取响应对象
ResponseEntity<User> responseEntity = restTemplate.exchange(
"http://127.0.0.1:8080/project/getUser/{userId}",HttpMethod.GET,requestEntity,User.class,"1");
User user = responseEntity.getBody();
log.debug(responseEntity.getHeaders() + "\n" + user);
}
//接收服务器 JSON 响应正文,并转化为 User
@Test
public void testHanldeUserJSON(){
RestTemplate restTemplate = buildRestTemplate();
//构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); //请求头说明接收的响应正文类型为JSON 格式
//构建请求对象
HttpEntity<String> requestEntity = new HttpEntity<>(null,headers);
//发送请求,获取响应对象
ResponseEntity<User> responseEntity = restTemplate.exchange(
"http://127.0.0.1:8080/project/getUser/{userId}",HttpMethod.GET,requestEntity,User.class,"1");
User user = responseEntity.getBody();
log.debug(responseEntity.getHeaders() + "\n" + user);
}
//创建包含 XML,JSON 转换器的 RestTemplate
private RestTemplate buildRestTemplate(){
RestTemplate restTemplate = new RestTemplate();
XStreamMarshaller xStreamMarshaller = new XStreamMarshaller();
xStreamMarshaller.setStreamDriver(new StaxDriver());
xStreamMarshaller.setAnnotatedClasses(new Class[]{User.class});
MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
xmlConverter.setMarshaller(xStreamMarshaller);
xmlConverter.setUnmarshaller(xStreamMarshaller);
restTemplate.getMessageConverters().add(xmlConverter); //添加 XML 转换器
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); //添加 JSON 转换器
return restTemplate;
}
//向服务端发送 User 的 XML 请求正文
@Test
public void testGetUserXML(){
RestTemplate restTemplate = buildRestTemplate();
User user = new User(4,"Tim",30);
//构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/xml;UTF-8")); //请求头说明请求正文数据类型为xml
//构建请求对象
HttpEntity<User> requestEntity = new HttpEntity<>(user,headers);
String fallback = restTemplate.postForObject("http://127.0.0.1:8080/project/putUser",requestEntity,String.class);
log.debug(fallback);
}
//向服务端发送 User 的 JSON 请求正文
@Test
public void testGetUserJSON(){
RestTemplate restTemplate = buildRestTemplate();
User user = new User(5,"Tim",30);
//构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/json;UTF-8")); //请求头说明请求正文数据类型json
//构建请求对象
HttpEntity<User> requestEntity = new HttpEntity<>(user,headers);
String fallback = restTemplate.postForObject("http://127.0.0.1:8080/project/putUser",requestEntity,String.class);
log.debug(fallback);
}
@RestController 和 AsyncRestTemplate
@ResrController
@Controller
@ResponseBody
public class UserController {
.....
}
//等同于
@RestController
public class UserController {
.....
}
AsyncRestTemplate
//演示客户端 AsyncRestTemplate 异步访问服务接口的的服务端接口
@RequestMapping(value="/getUserAsync",method=RequestMethod.GET)
public Callable<ResponseEntity<User>> handleUserLongTime(){
return new Callable<ResponseEntity<User>>() {
@Override
public ResponseEntity<User> call() throws Exception {
User user = new User(1,"assad",12);
ResponseEntity<User> responseEntity = new ResponseEntity<User>(user,HttpStatus.OK);
Thread.sleep(1000 * 10); //模拟处理时间
return responseEntity;
}
};
}
//演示客户端 AsyncRestTemplate 异步访问服务接口
@Test
public void testGetUserList() throws InterruptedException {
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
System.out.println("client start");
//调用服务接口后,立即返回
ListenableFuture<ResponseEntity<User>> future =
restTemplate.getForEntity("http://127.0.0.1:8080/project/getUserAsync",User.class);
//处理服务响应的异步回调方法
future.addCallback(new ListenableFutureCallback<ResponseEntity<User>>() {
@Override
public void onFailure(Throwable ex) {
log.debug("client failure: "+ ex);
}
@Override
public void onSuccess(ResponseEntity<User> result) {
User user = result.getBody();
System.out.println("client get result: " + user);
}
});
System.out.println("continue, no wait");
Thread.sleep(1000 * 20);
}
AJAX 实例
![](/assets/blank.gif)
![](/assets/blank.gif)
<!--加载 Spring WebApplicationContext: Service 层和 Dao 层的配置文件加载到 Spring 容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--启动 Spring 容器监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--声明 DispatcherServlet-->
<servlet>
<servlet-name>assad</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置 DispatcherServlet 的匹配 URL 模式-->
<servlet-mapping>
<servlet-name>assad</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context:component-scan base-package="site.assad.service" />
<!--装载 controller bean -->
<context:component-scan base-package="site.assad.web" />
<!--配置视图解析器,映射逻辑视图名的解析-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/" p:suffix=".jsp" />
<!--静态资源请求转发-->
<mvc:default-servlet-handler />
<!--装载 HttpMessageConverter 适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
p:messageConverters-ref="messageConverters"/>
<!--额外转换器列表-->
<util:list id="messageConverters">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</util:list>
<!--自动注册默认MessageConverter-->
<mvc:annotation-driven/>
package site.assad.web;
@Controller
public class AjaxController {
@Autowired
private UserService userService;
//转发入口url到jsp视图
@RequestMapping("/ajax")
public String toAjaxPage(){
return "ajaxTest";
}
//处理ajaxTest.jsp的Ajax请求,根据获取到的 userId,返回相应的User对象,
//具体转化为JSON,XML或其他格式的响应正文,由请求头的 Accept 决定
@RequestMapping(value="/getUserAjax",method=RequestMethod.GET)
public ResponseEntity<User> handleUserAjax(@RequestParam("userId") int userId){
User user = userService.getUser(userId);
ResponseEntity<User> responseEntity = new ResponseEntity<>(user, HttpStatus.OK);
return responseEntity;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Ajax 测试页面</title>
<script src="<c:url value="/resources/js/jquery-3.1.min.js"/>" ></script>
<script type="text/javascript">
$(document).ready(function(){
//监听userId输入框添的更改时间,加入Ajax方法
$("#userIdInput").change(function(){
var userId = $(this).val().trim();
if(userId !== "" && userId !== null && userId !== undefined ){
$.ajax({
url : "<c:url value="/getUserAjax"/>",
type : "GET",
headers: {
Accept : "application/json;charset=utf-8" //设置响应正文格式类型为 json
},
data : {"userId": userId},
success : function(resData){
if(resData.userId !== undefined){
$("#message").text(
"User Id :" + resData.userId+"\n"
+ "User Name: " + resData.userName + "\n"
+ "User Age: "+ resData.age + "\n"
);
}else{
$("#message").text("不存在该用户");
}
},
error : function(resData,status){
$("message").text("Ajax 请求错误");
}
});
}
});
});
</script>
</head>
<body>
<h1> 实时显示用户信息 </h1>
<label>Input User Id </label><input id="userIdInput" type="text" name="userId" />
<pre id="message"></pre>
</body>
</html>
Spring MVC(10):REST 支持 Ajax+Spring MVC 实例相关推荐
- spring boot注释_使用Spring Boot和注释支持配置Spring JMS应用程序
spring boot注释 1.简介 在以前的文章中,我们学习了如何使用Spring JMS配置项目. 如果查看有关使用Spring JMS进行消息传递的文章介绍 ,您会注意到它是使用XML配置的. ...
- 使用Spring Boot和注释支持配置Spring JMS应用程序
1.简介 在以前的文章中,我们学习了如何使用Spring JMS配置项目. 如果查看有关使用Spring JMS进行消息传递的文章介绍 ,您会注意到它是使用XML配置的. 本文将利用Spring 4. ...
- Spring MVC Controller与jquery ajax请求处理json
在用 spring mvc 写应用的时候发现jquery传递的[json数组对象]参数后台接收不到,多订单的处理,ajax请求: var cmd = {orders:[{"storeId&q ...
- Spring MVC和JQuery用于Ajax表单验证
在本教程中,我们将看到如何使用Ajax和Spring MVC和JQuery在服务器端验证表单. Spring MVC为通过注释驱动的配置采用Ajax提供了非常方便的过程. 我们将使用此注释驱动的配置以 ...
- spring MVC配置form支持PUT和DELETE方法
REST的关键原则之一就是"使用标准接口"(the use of the Uniform Interface),也就是提倡根据不同的语义使用GET, PUT, POST和DELET ...
- CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】
每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...
- Spring MVC前后台交互(前台ajax传递数据,后台controller接收数据返回json对象)
1.导入jar包 2.JS中用ajax传递用户数据 var data={origin:"register",tel:tel,pwd:pwd};$.ajax({url : " ...
- springmvc配置ssl_Spring Mvc和Spring Boot配置Tomcat支持Https
SpringBoot配置支持https spring boot因为是使用内置的tomcat,所以只需要一些简单的配置即可. 1.首先打开命令行工具,比如cmd,输入以下命令 keytool -genk ...
- springaop事务逻辑原理_太狠了!阿里大牛手写的Spring核心面试笔记:IOC+AOP+MVC+事务...
Spring作为现在最流行的java 开发技术,其内部源码设计非常优秀.如果你不会Spring,那么很可能面试官会让你回家等通知. Spring是什么? 有一个工地,几百号人在用铁锹铲子挖坑. 如果开 ...
最新文章
- android app文档,android App项目需求描述文档.docx
- 【脑电信号分类】脑电信号提取PSD功率谱密度特征
- 脚本事件中心与事件订阅器
- 一文读懂HttpServletRequest
- python列表和元组的应用_python学习笔记之列表(list)与元组(tuple)详解
- 如何在php中插入map热点,php中关于Map热点的运用
- 80-300-050-原理-MySQL执行解析
- java读文件指定行开始到文件的最后
- WebDevHelper -- RESTful服务和Ajax开发时的利器
- IE 不支持单引号(')的实体名称(amp;apos;)
- python基础4-序列
- 5G概念被热炒,运营商吃相不要太难看
- 统一修改PCB板上器件标识、阻值,后期方便手工焊接样板。(现以AD10为例)
- 技术真好玩第一期(2019-11-01)
- 微信小程序相册-笔记1
- 关于64位windows7系统下安装IE11失败(9c59)的解决过程记录
- org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dataSource' is defin
- html代码中文乱码解决
- GTN Yan LeCun 1998 文章中的一步
- 华为matepad鸿蒙系统,预装鸿蒙系统 华为MatePad Pro 2界面曝光
热门文章
- 华为matepad切换电脑模式_打开华为MatePad Pro电脑模式,四舍五入约等于拥有一台电脑?...
- python中筛选奇数_Python3基础 filter+lambda 筛选出1-20之间的奇数
- 地质勘查土质分类图片_如何看懂地质勘察报告
- PHPCMS v9自带截取字符串函数str_cut
- 计算机管理培训考试试题,计算机技能培训试题一
- 考试如何用计算机,计算机一级考试软件怎么使用_计算机一级考试软件安装使用教程...
- Linux内核启动logo
- c++编写函数把华氏温度转换为摄氏温度。
- sql语句中change和modify修改语法的区别
- 基于Java毕业设计在线学习平台源码+系统+mysql+lw文档+部署软件