JavaEE 企业级分布式高级架构师(四)SpringMVC学习笔记(3)

基础应用篇

@RequestMapping

Value属性

请求URL映射
  • 用于映射URL和HandlerMethod方法,用法如下:
@RequestMapping(value="/item")
@RequestMapping("/item")
@RequestMapping(value={"/item", "/queryItem"})
窄化请求映射
  • 限制此类下的所有方法的访问,请求url必须以请求前缀开头,对url进行模块化分类管理。用法如下:例如访问的URL是/item/findItem
@Controller
@RequestMapping("item")
public class ItemController{
	@RequestMapping("findItem")
	public String findItem(Model model){
		model.addAttribute("msg", "ItemController ... findItem方法执行了");
		return "success";
	}
}

method属性

  • 限定请求URL只能通过指定的method请求方式去访问该HandlerMethod。用法如下:
@RequestMapping(value="/findItem", method=RequestMethod.GET)
@RequestMapping(value="/findItem", method=RequestMethod.POST)
@RequestMapping(value="/findItem", method={RequestMethod.GET,RequestMethod.POST})

params属性

  • 通过设置params参数条件,进行访问HandlerMethod的限制。用法如下:
<!-- URL请求 -->
<a href="item/removeItem?name=iphone6&price>5000">删除商品,金额大于5000</a>
<a href="item/removeItem?name=iphone6&price>7000">删除商品,金额大于7000</a>
// Controller方法
@RequestMapping(value="removeItem", params={"name", "price>5000"})
public String removeItem(Model model){
	model.addAttribute("msg", "ItemController...removeItem方法执行了");
	return "success";
}

返回值处理

不使用注解修饰

  • ModelAndView:Controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定View。
  • void:在Controller方法形参上可以定义request和response,使用request和response指定响应结果:
void service(HttpServletRequest request, HttpServletResponse response){}


// 使用request转发页面,如下:
request.getRequestDispathcher("页面路径").forword(request, response);

// 也可以通过response页面重定向
response.sendRedirect("url")

// 也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
  • String(推荐):逻辑视图名
return "item/item-list";

// redirect重定向:相当于“response.sendRedirect()”;浏览器URL发生变化;Request域不能共享
return "redirect:testRedirect";

// forward转发:相当于“request.getRequestDispatcher().forward(request, response)”;浏览器URL不发生变化;Request域可以共享
return "forward:testForward";

使用注解修饰

  • 主要是使用 @ResponseBody 注解
注解介绍
  • ResponseBody注解的作用:可以针对Controller返回值类型,只用内置的9种HttpMessageConverter进行匹配,找到合适的HttpMessageConverter进行处理。
  • HttpMessageConverter处理逻辑分为三步:
    • 数据转换,比如Java对象装json字符串;
    • 指定HttpServletResponse的ContentType值;
    • 将转换之后的数据放到HttpServletResponse对象的响应体返回到页面。
  • @RequestBody注解的作用和@ResponseBody注解正好相反,它处理请求参数的http消息转换。
常用的HttpMessageConverter
  • MappingJacksonHttpMessageConverter:处理POJO类型返回值
    • 默认使用MappingJackson的JSON处理能力,将后台返回的Java对象(POJO类型),转为JSON格式输出到页面。
    • 将响应体Content-Type设置为application/json;charset=utf-8
  • StringHttpMessageConverter:处理String类型返回值
    • 调用response.getWriter()方法将String类型的字符串写回给调用者。
    • 将响应体的Content-Tyoe设置为text/plain;charset=utf-8。
示例
  • 添加依赖:
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.6</version>
</dependency>
  • JSP代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSON格式数据参数绑定和返回值处理演示demo</title>
</head>
<body>
	<!-- 使用@ResponseBody注解 -->
	<a href="${pageContext.request.contextPath}/reponsebody/returnString">测试String类型返回值</a>
	<a href="${pageContext.request.contextPath}/reponsebody/returnPOJO">测试POJO类型返回值</a>
	<!-- 使用@RestController注解 -->
	<a href="${pageContext.request.contextPath}/restcontroller/returnString">测试String类型返回值</a>
	<a href="${pageContext.request.contextPath}/restcontroller/returnPOJO">测试POJO类型返回值</a>
</body>
</html>
  • Controller代码:
// 方式1
@RequestMapping("responsebody")
@Controller
public class MyResponseBodyController {
	// @RequestMapping注解中的consumes和produces分别是为请求头和响应头设置contentType
	@RequestMapping(value="returnString", produces="text/plain;charset=UTF-8")
	@ResponseBody
	public String returnString(){
		// 如果在使用@ResponseBody注解的前提下,返回值是String类型,
		// 则返回值会由StringHttpMessageConverter进行处理
		return "查询失败";
	}
	@RequestMapping("returnPOJO")
	@ResponseBody
	public User returnPOJO(){
		User user = new User();
		user.setId(1);
		user.setUsername("张三丰");
		user.setSex("男");
		// 如果在使用@ResponseBody注解的前提下,返回值是POJO类型,
		// 则返回值会由MappingJacksonHttpMessageConverter(需要第三方jar包支持)进行处理
		return user;
	}
}
// 方式2
@RequestMapping("restcontroller")
@RestController	// 相当于Controller注解和ResponseBody注解的组合
public class MyRestController {
	// @RequestMapping注解中的consumes和produces分别是为请求头和响应头设置contentType
	@RequestMapping(value="returnString", produces="text/plain;charset=UTF-8")
	public String returnString(){
		// 如果在使用@ResponseBody注解的前提下,返回值是String类型,
		// 则返回值会由StringHttpMessageConverter进行处理
		return "查询失败";
	}
	@RequestMapping("returnPOJO")
	public User returnPOJO(){
		User user = new User();
		user.setId(1);
		user.setUsername("张三丰");
		user.setSex("男");
		// 如果在使用@ResponseBody注解的前提下,返回值是POJO类型,
		// 则返回值会由MappingJacksonHttpMessageConverter(需要第三方jar包支持)进行处理
		return user;
	}
}

参数绑定处理

什么是参数绑定?

  • 就是将请求参数中的Value值获取到之后,再进行类型转换,然后将转换后的值赋值给Controller类中方法的形参,这个过程就是参数绑定。
    • 请求参数格式:默认是key/value格式,比如:http://xxxx?id=1&type=301。
    • 请求参数值的数据类型:都是String类型的各种值。
    • 请求参数要绑定的目标类型:Controller类中的方法参数,比如简单类型、POJO、集合类型等。
  • SpringMVC内置的参数解析组件:默认内置了24种参数解析组件(ArgumentResolver)

默认支持的参数绑定

  • Controller方法形参中可以随时添加如下类型的参数(Servlet API支持),处理器会自动识别并进行赋值
    • HttpServletRequest:通过request对象获取请求信息;
    • HttpServletResponse:通过response处理响应信息;
    • HttpSession:通过session对象得到session中存放的对象;
    • InputStream、OutputStream;
    • Reader、Writer;
    • Model/ModelMap:ModelMap继承自LinkedHashMap,Model是一个接口,它们的底层实现都是同一个类(BindingAwareModelMap),作用就是向页面传递数据,相当于Request的作用,如下:
model.addAttribute("msg", "测试SpringMVC");

参数绑定使用要求

简单类型
  • 直接绑定:http请求参数的key和controller方法的形参名称一致
  • 注解绑定:请求参数的key和controller方法的形参名称不一致,需要使用@RequestParam注解才能将请求参数绑定成功
  • RequestParam注解:相当于request.getParameter(“url中的参数key”)
* value:参数名字,即入参的请求参数名字
		如value=“itemId”表示请求的参数中的名字为itemId的参数的值将传入
* required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报:
		HTTP Status 400 - Required Integer parameter 'xxxx' is not present
* defaultValue:默认值,表示如果请求中没有同名参数的默认值
绑定POJO类型
  • 要求表单中参数名称和controller方法中的POJO形参的实现名称保持一致
绑定集合或者数组类型
  • 简单类型数组:通过HTTP请求批量传递简单类型数据的情况,Controller方法中可以用String[]或者POJO的String[]属性接收(两种方式任选其一),但是不能使用List集合接收。
  • POJO类型集合或者数组:批量传递的请求参数,最终要使用List<POJO>来接收,那么这个List<POJO>必须放在另一个POJO类中。
  • 批量删除场景
- 请求:http://localhot:8080/user/delete?id=1&id=2&id=3
- Controller方法:
  - 方式一:delete(int[] id)   url中的key和参数名称必须一致,参数类型必须是数组。
  - 方式二:delete(DeleteVo vo)	vo中要包含一个数组类型的属性,属性名称必须和url中的key一致。
  • 批量修改场景
- 请求:http://localhot:8080/user/delete?id=1&name=zhangsan&id=2&name=lisi
- Controller方法:
  - update(UpdateVo vo)	只能使用POJO来接收从参数,vo中可以使用数组或者集合来接收参数

参数绑定示例

  • JSP代码:
<%@ 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>参数绑定演示demo</title>
</head>
<body>
	<!-- request请求的内容类型主要分为:K/V类型、Multipart类型、JSON类型 -->
	
	<!-- 1. 将request请求参数,绑定到简单类型(基本类型和String类型)方法参数 -->
	<!-- 1.1 直接绑定 -->
	<a href="${pageContext.request.contextPath}/user/findUserById?id=2&name=Tom">查询用户1</a>
	<!-- 1.2 @RequestParam注解绑定 -->
	<a href="${pageContext.request.contextPath}/user/findUserByUid?uid=1">查询用户2</a>
	
	<!-- 2. 将request请求参数,绑定到POJO类型(简单POJO和包装POJO)方法参数 -->
	<form action="${pageContext.request.contextPath}/user/saveUser" method="post">
		用户名称:<input type="text" name="username"><br/>
		用户性别:<input type="text" name="sex"><br/>
		所属省份:<input type="text" name="addressInfo.provinceName"><br/>
		所属城市:<input type="text" name="addressInfo.cityName"><br/>
		<input type="submit" value="保存">
	</form>
	
	<!-- 3. 将request请求参数,绑定到【元素是简单类型的集合或数组】参数 -->
	<!-- 3.1 使用数组接收 -->
	<a href="${pageContext.request.contextPath}/user/findUserByIdsForArray?id=1&id=2&id=3">根据ID批量查询用户</a>
	<!-- 3.2 使用List接收 -->
	<a href="${pageContext.request.contextPath}/user/findUserByIdsForList?id=1&id=2&id=3">根据ID批量查询用户</a>
	<!-- 3.3 使用Bean的List属性接收 -->
	<a href="${pageContext.request.contextPath}/user/findUserByIdsForBeanList?uid=1&uid=2&uid=3">根据ID批量查询用户</a>
	
	<!-- 4. 将request请求参数,绑定到【元素是POJO类型的List集合或Map集合】参数 -->
	<form action="${pageContext.request.contextPath}/user/updateUser" method="post">
		用户名称:<input type="text" name="username"><br/>
		用户性别:<input type="text" name="sex"><br/>
		<!-- 
			itemList[集合下标]:集合下标必须从0开始
			辅助理解:先将name属性封装到一个Item对象之中,再将该Item对象放入itemList集合的指定下标处
		 -->
		购买商品1名称:<input type="text" name="itemList[0].name"><br/>
		购买商品1价格:<input type="text" name="itemList[0].price"><br/>
		购买商品2名称:<input type="text" name="itemList[1].name"><br/>
		购买商品2价格:<input type="text" name="itemList[1].price"><br/>
		<!-- 
			itemMap['item3']:其中的item3、item4就是Map集合的key
			辅助理解:先将name属性封装到一个Item对象之中,再将该Item对象作为value放入itemMap集合的指定key处
		 -->
		购买商品3名称:<input type="text" name="itemMap['item3'].name"><br/>
		购买商品3价格:<input type="text" name="itemMap['item3'].price"><br/>
		购买商品4名称:<input type="text" name="itemMap['item4'].name"><br/>
		购买商品4价格:<input type="text" name="itemMap['item4'].price"><br/>
		<input type="submit" value="保存">
	</form>
	
	<!-- 5. 将request请求参数,绑定到Date类型方法参数 -->
	<!-- 5.1 请求参数是:【年月日】格式 -->
	<a href="${pageContext.request.contextPath}/user/deleteUserByStringDate?birthday=2018-01-01">根据日期删除用户(String)</a>
	<!-- 5.2 请求参数是:【年月日 时分秒】格式 -->
	<a href="${pageContext.request.contextPath}/user/deleteUserByDate?birthday=2018-01-01 12:10:33">根据日期删除用户(Date)</a>
</body>
</html>
  • PO代码:
public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
	// getter/setter 方法
}
public class UserEx extends User {
	// 演示包装POJO参数绑定
	private Address addressInfo;
	// 演示批量简单类型参数接收
	private List<Integer> uid = new ArrayList<>();
	// 将request请求参数,绑定到【元素是POJO类型的List集合】参数
	private List<Item> itemList = new ArrayList<>();
	// 将request请求参数,绑定到【元素是POJO类型的Map集合】参数
	private Map<String, Item> itemMap = new HashMap<>();
	// getter/setter 方法
}
  • Controller代码:
/**
 * 处理用户信息相关的控制器:用来学习参数绑定
 */
@RestController
@RequestMapping("user")
public class UserController {
	@Autowired
	UserService userService;
	// 1. 将request请求参数,绑定到简单类型(基本类型和String类型)方法参数
	/**
	 * 1.1 直接绑定
	 */
	@RequestMapping("findUserById")
	public User findUserById(Integer id){
		return userService.findUserById(id);
	}
	/**
	 * 1.2 @RequestParam注解绑定
	 */
	@RequestMapping("findUserByUid")
	public List<User> findUserByUid(@RequestParam("uid") List<Integer> uid){
		return userService.findUserByUid(uid);
	}
	
	// 2. 将request请求参数,绑定到POJO类型(简单POJO和包装POJO)方法参数
	@RequestMapping("saveUser")
	public int saveUser(UserEx user){
		return userService.saveUser(user);
	}
	
	// 3. 将request请求参数,绑定到【元素是简单类型的集合或数组】参数
	/**
	 * 3.1 使用数组接收
	 */
	@RequestMapping("findUserByIdsForArray")
	public List<User> findUserByIdsForArray(Integer[] id){
		return userService.findUserByIdsForArray(id);
	}
	/**
	 * 3.2 使用List接收
	 */
	@RequestMapping("findUserByIdsForList")
	public List<User> findUserByIdsForList(@RequestParam("id") List<Integer> ids){
		return userService.findUserByIdsForList(ids);
	}
	/**
	 * 3.3 使用Bean的List属性接收
	 */
	@RequestMapping("findUserByIdsForBeanList")
	public List<User> findUserByIdsForBeanList(UserEx userEx){
		return userService.findUserByIdsForBeanList(userEx);
	}
	
	// 4. 将request请求参数,绑定到【元素是POJO类型的List集合或Map集合】参数
	@RequestMapping("updateUser")
	public UserEx updateUser(UserEx user){
		return user;
	}
	
	// 5. 将request请求参数,绑定到Date类型方法参数
	/**
	 * 5.1 请求参数是:【年月日】格式
	 */
	@RequestMapping("/deleteUserByStringDate")
	public String deleteUserByStringDate(String birthday){
		return birthday;
	}
	/**
	 * 5.2 请求参数是:【年月日 时分秒】格式
	 */
	@RequestMapping("/deleteUserByDate")
	public int deleteUserByDate(Date birthday){
		return userService.deleteUserByDate(birthday);
	}
}

自定义日期参数绑定

  • 对于springmvc无法解析的参数绑定类型,比如【年月日时分秒】格式的日期,绑定到Date类型会报错,此时需要自定义【参数转换器】进行参数绑定。
  • Converter代码:
/**
 * 日期转换器
 */
public class DateConverter implements Converter<String, Date> {
	@Override
	public Date convert(String source) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		try {
			return simpleDateFormat.parse(source);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
  • Converter配置:将Converter配置之后,注册给处理器适配器
<!-- 配置处理器适配器和处理器映射器 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 转换器配置 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<property name="converters">
		<set>
			<bean class="com.yw.springmvc_ssm.component.DateConverter"></bean>
		</set>
	</property>
</bean>

文件类型参数绑定

  • 添加依赖:
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
  • 上传页面:JSP中的form表单需要指定enctype=“multipart/form-data”
  • 配置Multipart解析器:在springmvc.xml中配置multipart类型解析器
<!-- multipart类型解析器,文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!-- 上传文件的最大尺寸:5M -->
	<property name="maxUploadSize" value="5242880"></property>
</bean>
  • Controller代码
/**
 * 文件类型参数绑定
 */
@RestController
@RequestMapping("file")
public class FileController {
	@RequestMapping("upload")
	public String fileUpload(MultipartFile uploadFile) throws Exception{
		// 编写文件上传逻辑(mvc模式和三层结构模式)
		// 三层模式:表现层(controller、action)、业务层(service、biz)、持久层(dao、mapper)
		// MVC模式主要就是来解决表现层的问题的(原始的表现层是使用Servlet编写,即编写业务逻辑,又编写视图展示)
		
		if(uploadFile == null){
			return "文件为空";
		}
		
		// 原始文件名称
		String originalFileName = uploadFile.getOriginalFilename();
		System.out.println(originalFileName);
		// 如果没有文件名称,则上传不成功
		if(originalFileName==null || originalFileName.length()==0){
			return "上传失败";
		}
		// 存放文件的物理路径
		String filePath = "/Volumes/F/MyGitHub/ssm/springmvc-example-parent/uploadFiles";
		// 获取上传文件的扩展名
		String extName = originalFileName.substring(originalFileName.lastIndexOf("."));
		// 新文件的名称
		String newFileName = UUID.randomUUID() + extName;
		// 新的文件
		File newFile = new File(filePath + newFileName);
		// 把上传的文件保存成一个新的文件
		uploadFile.transferTo(newFile);
		// TODO: 同时需要把新的文件名更新到数据库中
		return "文件上传成功";		
	}
}

RESTful支持

HTTP介绍

HTTP协议概述

什么是HTTP协议?

  • HTTP协议是建立在客户端和服务器之间的一个应用层协议,在客户端和服务端之间需要数据的传输,而传输数据的时候,我们要按照指定的规则或者协议去传输数据。
  • HTTP是建立在TCP/IP协议基础之上的一个网络协议,属于网络七层模型中最上层【应用层】的协议,是一个无状态协议(不会记录每次访问时的信息)。
  • HTTP是一个客户端和服务器端请求和应答的标准(TCP),客户端是终端用户,服务器端是网站。

什么是URL/URI?

  • URI:Uniform Resource Identifier,统一资源标识符。它相当于一个网络资源的名称,只是名称的表现形式是/开头的路径形式。
  • URL:Uniform Resource Location,统一资源定位符。与URI的区别:URI是URL的子集。

什么是WEB资源?

  • 通过浏览器可以访问到的所有资源都是web资源,web资源分为静态资源和动态资源。
    • 动态资源是通过后台程序展示页面数据的,比如:Servlet请求。
    • 静态资源的数据是不变的,比如:HTML、JSP、AVI。

HTTP的作用是什么?

  • 就是为了约束客户端和服务器之间传输WEB资源时的格式。

HTTP协议版本?

  • 1.0版本和1.1版本,HTTP1.1可以一个连接传输多个WEB资源。
HTTP协议组成
  • HTTP请求协议信息由三部分组成:请求行、请求头、请求体,简称:行头体
  • 请求行:也叫请求首行,包含四部分(请求方法、URI、协议/版本、回车换行),例如:GET /user.html HTTP/1.1
    • 请求方法:GET、POST等8种。互联网中WEB资源操作也有增删改查方法,它们分别是POST、DELETE、PUT和GET。

在这里插入图片描述

  • 请求头:请求头的信息是以[key:value]形式展示的,一般来说,大多数请求头的信息都不是必须的,我们只需要了解一些常见的请求头信息即可。
  • MIME格式:多用途互联网邮件扩展类型,也叫媒体类型。格式:大类型/小类型,阅读是反过来的,比如text/html,读成html文本。
  • 请求体:也叫做正文。GET请求的请求体是空的,请求参数都是通过请求行传给服务器端;POST请求的请求体可以承载数据,请求头和请求体之间有一个空行作为分割线。
  • 通过表单POST提交的请求体的表现形式主要有三种:
描述
application/x-www-form-urlencoded在发送前编码所有字符(默认),多个参数以&连接,上传文件自能上传文件名
mutipart/form-data不对字符编码,在使用包含文件上传控件的表单时,必须使用该值
text/plain空格转换为“+”加号,但不对特殊字符编码,多个参数不会使用&连接,上传文件自能上传文件名
  • 响应状态码:状态码由三位数字组成,第一个数字定义了响应的类别,共分为五种类别:
* 1xx:指示信息--表示请求已接收,继续处理
* 2xx:成功--表示请求已被成功接收
* 3xx:重定向--要完成请求必须进行更进一步的操作
* 4xx:客户端错误--请求有语法错误或请求无法实现
* 5xx:服务器端错误--服务器未能实现合法的请求
  • 常见的状态码:
    • 200 OK:客户端请求成功
    • 400 BadRequest:客户端请求有语法错误,不能被服务端所理解
    • 401 Unauthorized:请求未经授权,这个状态码必须和WWW-Authenticate报头域一起使用
    • 403 Forbidden:服务器收到请求,但是拒绝提供服务
    • 404 NotFound:请求资源不存在
    • 500 Internal Server Error:服务器发生不可预期的错误
    • 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
GET请求和POST请求的区别
  • 提交数据的方式不同:GET是通过请求行提交请求参数的;POST是通过请求体提交请求参数的。
  • 使用场景不同:GET请求的目的是获取到数据,简单说就是客户端向服务器端要东西;POST请求的目的是给服务器端提交数据,就是客户端向服务器端给东西。
  • 传递参数的大小不同:GET请求时通过请求行中的请求URL传递给客户端的,HTTP协议对请求URL的长度没有限制,但是不同的浏览器对请求URL长度是有限制的。POST请求是通过请求体传递请求参数的,大小比GET方式要大要多。

RESTful简介

什么是REST?

  • REST(Representational State Transfer,(资源)表述性状态转化)描述了一个架构样式的网络系统,比如web应用程序。
  • 它是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
  • 它本身并有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。

什么是RESTful?

  • REST指的是一组架构约束条件和原则,满足这些约束条件和原则的应用程序或设计就是 RESTful。

RESTful的特性?

  • 资源(Resource):网络上的一个实体,或者说网络上的一个具体信息,它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在,可以用一个URI指向它,要获取这个资源,访问它的URI就可以。
  • 表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如:文本可以用txt格式表现,也可以用 html 格式、xml格式、json格式表现,甚至可以采用二进制格式。
  • 状态转化(State Transfer)
    • 每发出一个请求,就代表客户端和服务端的一次交互过程。HTTP协是一个无状态协议,因此如果客户端想要操作服务器,必须通过某种手段让服务器端发生“状态转化”,而这种转化是建立在表现层之上的,就是“表现才能通过状态转化”。
    • 具体说,就是HTTP协议里,4个表示操作方式的动词:GET、POST、PUT、DELETE,分别对应4种基本操作:GET用来获取资源、POST用来新建资源、PUT用来更新资源、DELETE用来删除资源

如何设计RESTful应用程序的API?

  • 路径设计:数据库设计完毕后,基本就可以确定有哪些资源要进行操作,相对应的路径就可以设计出来了。
  • 动词设计:也就是正对资源的具体操作类型,由HTTP动词表示,常用:GET、POST、PUT、DELETE。
  • RESTful的示例:
/account/1 HTTP GET	:得到id = 1 的 account
/account/1 HTTP DELETE	:删除id = 1 的 account
/account/1 HTTP PUT	:更新id = 1 的 account

SpringMVC对RESTful的支持

RESTful的URL路径变量
  • URL-PATTERN:设置为 / ,方便拦截 RESTful 请求
<servlet-mapping>
  <servlet-name>DispathcherServlet</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
  • @PathVariable:可以解析出来URL中的模板变量({id}),URL:http://localhost:8080/item/1/zhangsan
@RequestMapping("{id}/{name}")
@ResponseBody
public Item queryItemById(@PathVariable Integer id, @PathVariable String name){}
RESTful的CRUD
  • @RequestMapping:通过设置method属性值,可以将同一个URL映射到不同的HandlerMethod方法上
  • @GetMapping、@PostMapping、@PutMapping、@DeleteMapping注解同@RequestMapping注解的method属性设置
  • 示例代码:
/**
 * 主要是用来演示springmvc对于RESTful的支持
 */
@RestController
@RequestMapping("rest")
public class RestfulController {
	// SpringMVC 通过路径目标变量{变量名}这种方式,对URL带有参数的情况进行支持
	@RequestMapping("user/{id}/{name}/{sex}")
	public User findUserById(@PathVariable Integer id,
							 @PathVariable String name,
							 @PathVariable String sex){
		User user = new User();
		user.setId(id);
		user.setUsername(name);
		user.setSex(sex);
		return user;
	}
	@RequestMapping(value="user", method=RequestMethod.POST)
	public User saveUser(User user){
		return user;
	}
}
RESTful的资源表述
  • RESTful服务中一个重要的特性就是一种资源可以有多重表现形式,在SpringMVC中可以使用ContentNegotiatingManager这个内容协商管理器来实现这种方式,内容协商的方式有三种:
    • 扩展名:比如 .json表示需要JSON格式数据、.xml表示需要XML格式数据;
    • 请求参数:默认是“format”;
    • 请求头设置Accept参数:比如设置Accept为application/json表示要JSON格式数据
  • 不过现在RESTful响应的数据一般都是JSON格式,所以一般也不使用内容协商管理器,直接使用@ResponseBody注解将数据按照JSON格式返回。
静态资源访问mvc:resources
  • 如果在DispathcherServlet中设置url-pattern为 / ,则必须对静态资源进行访问处理。在springmvc.xml文件中,使用mvc:resources标签,具体如下:
<mvc:resources location="/js/" mapping="/js/"/>
<mvc:resources location="/css/" mapping="/css/"/>
  • SpringMVC会把mapping映射到ResourceHttpRequestHandler,这样静态资源在经过DispathcherServlet转发时就可以找到对应的handler了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

讲文明的喜羊羊拒绝pua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值