精华内容
下载资源
问答
  • Restful风格详解

    2021-03-09 10:26:11
    SpringMVC Restful风格及实例、参数的转换 一、Restful风格 1、Restful风格的介绍 Restful 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。...

    SpringMVC Restful风格及实例、参数的转换
    一、Restful风格
    1、Restful风格的介绍
    Restful 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

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

    Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。

    在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 协议,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。

    干货(简单明了):

    Restful是一种设计风格。对于我们Web开发人员来说。就是使用一个url地址表示一个唯一的资源。然后把原来的请求参数加入到请求资源地址中。然后原来请求的增,删,改,查操作。改为使用HTTP协议中请求方式GET、POST、PUT、DELETE表示。

    把请求参数加入到请求的资源地址中
    原来的增,删,改,查。使用HTTP请求方式,POST、DELETE、PUT、GET分别一一对应。
    二、如何学习restful风格,这里需要明确两点:
    1、就是把传统的请求参数加入到请求地址是什么样子?
    传统的方式是:

    比如:http://ip:port/工程名/资源名?请求参数

    举例:http://127.0.0.1:8080/springmvc/book?action=delete&id=1

    restful风格是:

    比如:http://ip:port/工程名/资源名/请求参数/请求参数

    举例:http://127.0.0.1:8080/springmvc/book/1

    请求的动作删除由请求方式delete决定

    2、restful风格中请求方式GET、POST、PUT、DELETE分别表示查、增、改、删。

    GET请求		                             对应             查询
    http://ip:port/工程名/book/1		HTTP请求GET		表示要查询id为1的图书
    http://ip:port/工程名/book		    HTTP请求GET		表示查询全部的图书
    
    POST请求	对应	添加
    http://ip:port/工程名/book		    HTTP请求POST	表示要添加一个图书
    
    PUT请求		对应	修改
    http://ip:port/工程名/book/1		HTTP请求PUT		表示要修改id为1的图书信息
    
    DELETE请求	对应	删除
    http://ip:port/工程名/book/1		HTTP请求DELETE		表示要删除id为1的图书信息
    

    3、SpringMVC中如何发送GET请求、POST请求、PUT请求、DELETE请求
    我们知道发起GET请求和POST请求,只需要在表单的form标签中,设置method=”get” 就是GET请求。

    设置form标签的method=”post”。就会发起POST请求。而PUT请求和DELETE请求。要如何发起呢。

    要有post请求的form标签
    在form表单中,添加一个额外的隐藏域_method=”PUT”或_method=”DELETE”
    在web.xml中配置一个Filter过滤器org.springframework.web.filter.HiddenHttpMethodFilter(注意,这个Filter一定要在处理乱码的Filter后面)

       <!-- 负责把隐藏域中的put,改为请求的put请求 -->
    <filter>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    

    三、Restful风格的Controller如何实现
    1、Controller实现代码

    @Controller
    public class RestfulController {
    
    	@RequestMapping(value="/book/1",method=RequestMethod.GET)
    	public String queryBookById() {
    		System.out.println("根据id查询一本图书");
    		return "/restful.jsp";
    	}
    	
    	@RequestMapping(value="/book",method=RequestMethod.GET)
    	public String queryBooks() {
    		System.out.println("查询全部图书");
    		return "/restful.jsp";
    	}
    	
    	@RequestMapping(value="/book",method=RequestMethod.POST)
    	public String addBook() {
    		System.out.println("post请求  添加图书");
    		return "/restful.jsp";
    	}
    	
    	@RequestMapping(value="/book/1",method=RequestMethod.PUT)
    	public String updateBook() {
    		System.out.println("修改图书");
    		return "/restful.jsp";
    	}
    	
    	@RequestMapping(value="/book/1",method=RequestMethod.DELETE)
    	public String deleteBook() {
    		System.out.println("删除图书");
    		return "/restful.jsp";
    	}
    	
    }
    

    2、restful风格的jsp页面

    
    ```html
    <%@ 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>Insert title here</title>
    	</head>
    	<body>
    		<a href="${ pageContext.request.contextPath }/book/1">查询一本图书</a>
    		<a href="${ pageContext.request.contextPath }/book">查询全部图书</a>
    		<form action="${ pageContext.request.contextPath }/book" method="post">
    			<input type="submit" value="post添加图书"/>
    		</form>
    		
    		<form action="${ pageContext.request.contextPath }/book/1" method="post">
    			<!-- 表示这是put请求 -->
    			<input type="hidden" name="_method" value="PUT"/>
    			<input type="submit" value="put修改图书"/>
    		</form>
    		
    		<form action="${ pageContext.request.contextPath }/book/1" method="post">
    			<!-- 表示这是DELETE请求 -->
    			<input type="hidden" name="_method" value="DELETE"/>
    			<input type="submit" value="DELETE 删除图书"/>
    		</form>
    	</body>
    </html>
    

    在这里插入图片描述

    四、Restful风格在高版本Tomcat中无法转发到jsp页面
    在Tomcat8之后的一些高版本,使用restful风格访问然后转发到jsp页面。就会有如下的错误提示:
    在这里插入图片描述
    解决有两个方法:

    1、在需要跳转去的页面中设置当前是错误页面isErrorPage=“true”
    在这里插入图片描述
    2、在put或delete方法中,使用重定向返回

    五、@PathVariable 路径参数获取
    前面我们已经知道如何编写和配置restful风格的请求和控制器。

    那么 现在的问题是。如何接收restful风格请求的参数。比如前面的id值。

    第一种情况,一个path参数:

     /**
     * @PathVariable 注解表示取路径参数的值。<br/>
     * 	value="/book/{id}" 这里我们把id写成了{id}这是路径参数<br/>
     *  @PathVariable(name="id") 这里的name属性表示把路径参数id的值注入到请求方法的id参数中
     */
    @RequestMapping(value="/book/{id}",method=RequestMethod.GET)
    public String queryBookById(@PathVariable(name="id") Integer id) {
    	System.out.println("根据id查询一本图书。 id ====>>>> " + id);
    	return "/restful.jsp";
    }
    

    第二种情况,多个path参数:

       /**
     * @PathVariable 注解表示取路径参数的值。<br/>
     *               value="/book/{id}" 这里我们把id写成了{id}这是路径参数<br/>
     * @PathVariable(name="id") 这里的name属性表示把路径参数id的值注入到请求方法的id参数中<br/>
     * 	name的属性,表示取路径中哪个参数。默认情况下。参数名是name的值<br/>
     */
    @RequestMapping(value = "/book/{id}/{abc}", method = RequestMethod.GET)
    public String queryBookById(@PathVariable(name = "id") Integer id,
    		@PathVariable(name = "abc") String abc) {
    	System.out.println("根据id查询一本图书。 id ====>>>> " + id);
    	System.out.println("abc ===>>>> " + abc);
    	return "/restful.jsp";
    }
    

    在这里插入图片描述

    六、Restful风格实现的CRUD图书
    把前面的传统请求方式的图书的CRUD换成刚刚讲的Restful风格的图书模块的CRUD。只需要修改页面端的请求方式和地址,以及服务器端Controller的接收。

    1、Restful风格的crud工程的搭建
    在这里插入图片描述
    2、列表功能实现
    Controller中的代码:

     /**
     * 查询全部图书
     * 
     * @return
     */
    @RequestMapping(value = "/book", method = RequestMethod.GET)
    public ModelAndView list() {
    	// 2 转发到book/bookList.jsp页面
    	ModelAndView modelAndView = new ModelAndView("bookList");
    	// 1 查询全部的图书,保存到request域中
    	modelAndView.addObject("bookList", bookService.queryBooks());
    
    	return modelAndView;
    }
    

    请求方式:

    图书管理

    3、删除功能实现
    Controller中的代码:

       @RequestMapping(value = "/book/{id}",method=RequestMethod.DELETE)
    public ModelAndView delete(@PathVariable(name="id") Integer id) {
    	// 调用BookService删除图书
    	bookService.deleteBookById(id);
    	// 重定向 到图书列表管理页面
    	return new ModelAndView("redirect:/book");
    }
    

    到web.xml中去配置 支持restful风格的Filter过滤器

      <!-- 配置支持restful的Filter过滤器 -->
    <filter>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    

    bookList.jsp中,需要修改提交的方式:

     <td>
    		<!-- 表示啥也不干 -->
    		<a class="deleteA" itemId="${ book.id }" href="javascript:void(0);">删除</a><a href="${ pageContext.request.contextPath }/book/getBook?id=${book.id}">修改</a>
    		<form id="item_${ book.id }" action="${ pageContext.request.contextPath }/book/${book.id}" method="post">
    			<input type="hidden" name="_method" value="DELETE" />
    		</form>
    	    </td>
    
        <script type="text/javascript">
    	$(function(){
    		// 给删除绑定单击事件
    		$("a.deleteA").click(function(){
    		    // 提示用户确认操作
    		    if ( confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】吗?")){
    			// 点击删除,提交form表单
    			// submit(function(){})是给表单的提交事件添加功能
    			// submit() 让表单提交
    			$("#item_" + $(this).attr("itemId")).submit();
    				}
    			});
    		});
    </script>
    

    在这里插入图片描述
    4、添加功能实现

       @RequestMapping(value = "/book", method = RequestMethod.POST)
    public ModelAndView add(Book book) {
    	// 1 调用bookService保存
    	bookService.addBook(book);
    	// 2 重定向回图书列表管理页面
    	return new ModelAndView("redirect:/book");
    }
    

    bookEdit.jsp页面请求方式需要调整:
    在这里插入图片描述
    5、更新功能实现
    更新图书分为两个步骤:

    查询需要更新的图书,填充到更新页面
    提交请求,发送数据给服务器更新保存修改。
    5.1、查询需要更新的图书,填充到更新页面

    @RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
    public ModelAndView getBook(@PathVariable(name = "id") Integer id) {
    	ModelAndView modelAndView = new ModelAndView();
    
    	// 模型 是需要修改的图书===调用BookService.queryBookById
    	modelAndView.addObject("book", bookService.queryBookById(id));
    	// 设置跳转的页面
    	modelAndView.setViewName("bookEdit");
    
    	return modelAndView;
    }
    

    5.2、提交请求,发送数据给服务器更新保存修改。

     @RequestMapping(value = "/book/{id}",method=RequestMethod.PUT)
    public ModelAndView update(@PathVariable Integer id, Book book) {
    	// 保存修改
    	bookService.updateBook(book);
    	// 跳到图书列表管理页面
    	return new ModelAndView("redirect:/book");
    }
    

    bookEdit.jsp页面的修改

    <center>
    	<h3>添加图书</h3>
    	<c:if test="${ not empty requestScope.book }">
    		<form action="${ pageContext.request.contextPath }/book/${requestScope.book.id}" method="post">
    	</c:if>
    	<c:if test="${ empty requestScope.book }">
    		<form action="${ pageContext.request.contextPath }/book" method="post">
    	</c:if>
    			
    			
    		<c:if test="${ not empty requestScope.book }">
    			<input type="hidden" name="_method" value="PUT"/>
    		</c:if>
    		<input type="hidden" name="id" value="${ requestScope.book.id }"/>
    		<table>
    			<tr>
    				<td>书名</td>
    				<td><input name="name" type="text" value="${ requestScope.book.name }"/></td>
    			</tr>
    			<tr>
    				<td>作者</td>
    				<td><input name="author" type="text" value="${ requestScope.book.author }" /></td>
    			</tr>
    			<tr>
    				<td>价格</td>
    				<td><input name="price" type="text" value="${ requestScope.book.price }" /></td>
    			</tr>
    			<tr>
    				<td>销量</td>
    				<td><input name="sales" type="text" value="${ requestScope.book.sales }" /></td>
    			</tr>
    			<tr>
    				<td>库存</td>
    				<td><input name="stock" type="text" value="${ requestScope.book.stock }"/></td>
    			</tr>
    			<tr>
    				<td align="center" colspan="2">
    					<input type="submit" />
    				</td>
    			</tr>
    		</table>
    	</form>
    </center>
    

    6、字符集的Filter一定要在Restful的Filter前面

    CharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter


    encoding
    UTF-8


    forceRequestEncoding
    true


    forceResponseEncoding
    true



    CharacterEncodingFilter
    /*

    <!-- 配置支持restful的Filter过滤器 -->
    <filter>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>HiddenHttpMethodFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    

    七、SpringMVC标签库
    1、搭建SpringMVC开发环境
    在这里插入图片描述
    2、创建对象模型Person对象

    public class Person {
    	private Integer id;
    	private String name;
    	private Date birthDate;
    	private String email;
    	private BigDecimal salary;
    

    PersonController控制器代码:

    @Controller
    public class PersonController {
    
    	@RequestMapping(value="/toAddPerson")
    	public String toAddPerson(Map<String, Object> map) {
    		System.out.println("经过Controller控制器");
    		map.put("person", new Person());//
    		return "/person/addPerson.jsp";
    	}
    	
    	@RequestMapping("/addPerson")
    	public String addPerson(Person person) {
    		System.out.println("添加用户:" + person);
    		return "/index.jsp";
    	}
    	
    }
    

    addPerson.jsp页面

        <body>
    	添加用户
    	<!-- 
    		action		提交的地址
    		method		请求的方式
    		modelAttribute	SpringMVC的标签库,需要跟隐含模型中一个对象相对应
    			modelAttribute="person"一定要和隐含模型中的key相对应
    			也就是Person用户模块,隐含模型中的key是person,表单的modelAttribute属性值也是person
    			如果是图书模块,隐含模型中的key是book,表单的modelAttribute属性值也是book
    	 -->
    	<form:form action="${ pageContext.request.contextPath }/addPerson" 
    		modelAttribute="person" method="post">
    		<!-- 每个input 的path属性值要跟模型的属性名相对应 -->
    		id <form:input path="id"/><br/>
    		name <form:input path="name"/><br/>
    		birthDate <form:input path="birthDate"/><br/>
    		email <form:input path="email"/><br/>
    		salary <form:input path="salary"/><br/>
    		<input type="submit" />
    	</form:form>
    </body>
    

    八、自定义参数转换器
    1、WebDataBinder类介绍
    在SpringMVC中有WebDataBinder类。这个类专门用来负责将请求参数类型转换。以及请求参数数据验证,错误信息绑定等功能。

    WebDataBinder会调用各种类型转换器,得到属性相对应类型的值。然后再注入到属性中(调用setXxxx方法)

    在WebDataBinder类中有三个组件分别处理三种不同的功能。

        conversionService 负责处理参数类型转换。把请求的参数转换成为Controller中的方法参数值。
    

    converters 在ConversionService组件中需要各种类型转换器,在conversionService组件中需要依赖于各种转换器类去实现转换工作。

         validators 负责验证传入的参数值是否合法。
    
         bindingResult 负责接收验证后的错误信息。
    

    下图展示了WebDataBinder、ConversionService、Converter的关系。
    在这里插入图片描述

    如果我们要自定义请求参数的类型转换器。需要实现

    org.springframework.core.convert.converter.Converter<S,T>接口。

    然后注入到ConversionService组件中。最后再将ConversionService注入到WebDataBinder中。

    创建ConversionService组件,需要配置

    org.springframework.format.support.FormattingConversionServiceFactoryBean对象。

    2、自定义String到java.util.Date类型转换器

    public class MyStringToDate implements Converter<String, Date> {
    	
    	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    	
    	/**
    	 * convert方法负责转换<br/>
    	 * 		source客户端发送过来的值<br/>
    	 * 		Date转换之后的结果
    	 */
    	@Override
    	public Date convert(String source) {
    		if (source == null) {
    			return null;
    		}
    		source = source.trim();
    		try {
    			// 调用转换器
    			return sdf.parse(source);
    		} catch (ParseException e) {
    			e.printStackTrace();
    			throw new IllegalArgumentException("Invalid java.util.Date value '" + source + "'");
    		}
    		
    	}
    
    }
    

    到ApplicationContext.xml中去配置,并使用

    <!-- 配置一个类型转换器组件 -->
    	<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    		<!-- 把你自定义的类型转换器注入到ConversionService组件中 -->
    		<property name="converters">
    			<set>
    				<bean class="com.webcode.converter.MyStringToDate"/>
    			</set>
    		</property>
    	</bean>
    	
    	
    	<!-- springMVC的标配 -->
    	<mvc:default-servlet-handler/>
    	<!-- SpringMVC中的高级功能
    			conversion-service="conversionService" 将你自己配置的类型转换器,注入到SpringMVC的系统中
    	 -->
    	<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    

    3、@DateTimeFormat注解类型转换器
    我们也可以像上面。在类的Date类型的属性上标上注解。就可以自动将String类型转换成为Date数据

    pattern属性表示 日期的格式。最完成的格式是:yyyy-MM-dd hh:mm:ss

     yyyy    表示年份必须是4位
        MM	    表示月份必须是2位
        dd	    表示日期必须是2位
    
        hh	    表示小时,必须是2位
        mm	    表示分钟,必须是2位
        ss	    表示秒钟,必须是2

    九、较验器----参数的有效性验证Validate----Hibernate
    在JavaEE6.0中,定义了很多的验证规范。这些规范统称为:JSR303验证规范。

    而这些规范的实现。我们使用现在业内比较认可的Hibernate-Validate验证

    @AssertTrue      用于boolean字段,该字段只能为true  
    
    @AssertFalse
    
    该字段的值只能为false
    
    @CreditCardNumber
    
    对信用卡号进行一个大致的验证
    
    @DecimalMax
    
    只能小于或等于该值
    
    @DecimalMin
    
    只能大于或等于该值
    
    @Digits(integer=,fraction=)
    
    检查是否是一种数字的整数、分数,小数位数的数字
    
    @Email
    
    检查是否是一个有效的email地址
    
    @Future
    
    检查该字段的日期是否是属于将来的日期
    
    @Length(min=,max=)
    
    检查所属的字段的长度是否在min和max之间,只能用于字符串
    
    @Max
    
    该字段的值只能小于或等于该值
    
    @Min
    
    该字段的值只能大于或等于该值
    
    @NotNull
    
    不能为null
    
    @NotBlank
    
    不能为空,检查时会将空格忽略
    
    @NotEmpty
    
    不能为空,这里的空是指空字符串
    
    @Null
    
    检查该字段为空
    
    @Past
    
    检查该字段的日期是在过去
    
    @Pattern(regex=,flag=)
    
    被注释的元素必须符合指定的正则表达式
    
    @Range(min=,max=,message=)
    
    被注释的元素必须在合适的范围内
    
    @Size(min=, max=)
    
    检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map@URL(protocol=,host,port)
    

    检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件

    使用Hiberante的验证器较验数据分以下步骤:
    入Hibernate验证的jar包
    hibernate-validator-5.0.0.CR2.jar

        hibernate-validator-annotation-processor-5.0.0.CR2.jar
    
        classmate-0.8.0.jar
    
        jboss-logging-3.1.1.GA.jar
    
        validation-api-1.1.0.CR1.jar
    
    2. 在实体bean对象的属性上使用校验的注解
    

    在这里插入图片描述
    3. 在Controller的方法参数上,给需要验证的bean对象。添加验证注解@Valid,以及在验证对象后跟一个BindingResult 对象用于接收验证的错误信息

    /**
     * @Valid当前方法的person参数我要做数据较验<br/>
     * BindingResult用来接收前面一个对象的错误信息
     */
    @RequestMapping("/addPerson")
    public String addPerson(@Valid Person person, BindingResult personBindingResult) {
    	if (personBindingResult.hasErrors()) {
    		personBindingResult.getAllErrors().forEach(System.out::println);
    		return "/person/addPerson.jsp";
    	}
    	System.out.println("添加用户:" + person);
    	return "/index.jsp";
    }
    
     4. 在SpringMVC的form表单字段后,使用<form:errors path="字段名" />输出对应字段的错误信息
    
    <form:form action="${ pageContext.request.contextPath }/addPerson" 
    		modelAttribute="person" method="post">
    		<!-- 每个input 的path属性值要跟模型的属性名相对应 -->
    		id:<form:input path="id"/><form:errors path="id" /><br/>
    		name:<form:input path="name"/><form:errors path="name" /><br/>
    		birthDate:<form:input path="birthDate"/><form:errors path="birthDate" /><br/>
    		email:<form:input path="email"/><form:errors path="email" /><br/>
    		salary:<form:input path="salary"/><form:errors path="salary" /><br/>
    		<input type="submit" />
    </form:form>
    

    十、自定义错误信息的回显
    1、错误消息规则:
    这是校验错误的key规则:

    格式1:	        Pattern.bean.property
    说明:		校验格式.隐含模型包.属性名
    示例:		Email.person.email		person对象的email属性验证Email格式失败
    
    格式2:	        Pattern.property
    说明:		校验格式.属性名
    示例:		Email.email			任何对象的email属性验证Email格式失败
    
    格式3:	        Pattern.javaType
    说明:		校验格式.字段数据类型
    示例:		Email.java.lang.String		任何String类型的属性验证Email格式失败
    
    key4:		Pattern
    说明:		校验格式
    示例:		Email				校验Email格式失败
    

    参数转换失败的key规则:

    格式1:		typeMismatch.bean.property
    说明:		类型不匹配.隐含模型包.属性名
    示例:		typeMismatch.person.birthDate	person对象的birthDate属性转换失败
    
    格式2:		typeMismatch.property
    说明:		类型不匹配.属性名
    示例:		typeMismach.birthDate		任何对象的birthDate属性转换失败
    
    格式3:	        typeMismatch.javaType
    说明:		类型不匹配.字段数据类型
    示例:		typeMismach.java.util.Date	Java.util.Date类型转换失败
    
    格式4:	        typeMismatch
    说明:		类型不匹配
    示例:		typeMismach			字段类型转换失败
    

    2、在源码目录下配置错误信息的属性配置文件
    在这里插入图片描述
    Past=\u8FD9\u4E2A\u65F6\u95F4\u4E0D\u5BF9
    typeMismatch.java.util.Date=\u975E\u6CD5\u8F93\u5165
    Length=\u957F\u5EA6\u5FC5\u987B\u662F 5 \u5230 12 \u4F4D
    Email=\u4E0D\u597D\u597D\u5E72\u6D3B\u660E\u5929\u6CA1\u996D\u5403
    Min=\u4E0D\u80FD\u5C0F\u4E8E 3000
    typeMismatch.salary=\u5DE5\u8D44\u8F93\u5165\u4E0D\u5BF9

    3、在application.xml中配置属性信息

     <!-- 
    	org.springframework.context.support.ResourceBundleMessageSource可以做加载properties属性配置文件使用,
    	还可以做国际化
     -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    	<!-- 
    		basename配置文件名,但不带后缀
    	 -->
    	<property name="basename" value="errors"/>
    </bean>
    
    使用占位符{数字}
    

    在这里插入图片描述
    对于SpringMvc模型来说,传值是框架做的工作。我们只需要写好数字即可。

    第一个参数Spring传入的是验证的属性名

    展开全文
  • RestFul风格

    2021-10-29 12:14:54
    restful风格的注解 变量上的注解:@PathVariable 方法上的注解 @PostMapping("/h1/{a}/{b}") <==========> @RequestMapping(path = "/h1/{a}/{b}",method = RequestMethod.POST) @GetMapping() @PutMapping() ...

    RestFul的优势:简洁,高效,安全 还能实现url的复用

    restful风格的注解

    变量上的注解:@PathVariable

    方法上的注解

    @PostMapping("/h1/{a}/{b}") <==========> @RequestMapping(path = "/h1/{a}/{b}",method = RequestMethod.POST)
    @GetMapping()
    @PutMapping()
    @DeleteMapping()
    @PatchMapping()
    

    首先要知道最初的传递参数的方式?a=1&b=2 ,这样的传参,暴露了我们的参数是不安全的,而restful风格的传参是/1/2,只是传递了值。

    再写一遍web.xml文件和springmvc-servlet.xml文件,其实在我们的开发中这两个配置文件基本上是不需要在做改变的

    web.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
        <!--注册DispatcherServlet 本质就是一个servlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
            <!--加载springmvc-servlet.xml文件-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
    
            <!--配置web.xml文件的启动级别-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

    springmvc-servlet.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/mvc
                http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--扫描特定包下的注解-->
        <context:component-scan base-package="com.zkw.restful"/>
        <!--过滤静态资源-->
        <mvc:default-servlet-handler/>
        <!--mvc注解驱动-->
        <mvc:annotation-driven/>
    
        <!--视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    

    hello.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    ${result}
    </body>
    </html>
    

    RestfulController.java

    package com.zkw.restful;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/restful")
    public class RestfulController {
    
        @RequestMapping(path = "/h1/{a}/{b}",method = RequestMethod.POST)
        public String Restful(@PathVariable int a, @PathVariable String b, Model model){
            model.addAttribute("result","结果为"+(a+b));
            return "hello";
        }
    
       @GetMapping("/h1/{a}/{b}")
        public String Restful(@PathVariable int a, @PathVariable int b, Model model){
            model.addAttribute("result","结果为"+(a+b));
            return "hello";
        }
    
        //原始的风格
        @RequestMapping("/h2")
        public String Restful(String a, int b, Model model){
            model.addAttribute("result","结果为"+(a+b));
            return "hello";
        }
    
    }
    

    解释一下,在类上边的@RequestMapping("/restful")与这个类下边方法上的所有@RequestMapping("/h2")和 @GetMapping("/h1/{a}/{b}")是父子关系,相当于你要想访问这各类里边的方法,首先要先访问这个类。

    原始风格的结果为

    在这里插入图片描述

    先说一下,它默认的提交方式是get,当我使用restful风格访问的时候,它走得是 @GetMapping("/h1/{a}/{b}")这个

    在这里插入图片描述

    最后再说一下url的复用,当我在另一个页面上使用post提交表单的时候它请求的方法是第一个

    首先写一个测试页面test.jsp

    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <form action="/springmvc_04_restful_war_exploded/restful/h1/1/2" method="post">
        <input type="submit">
    </form>
    </body>
    </html>
    
    

    结果为

    在这里插入图片描述

    展开全文
  • RESTful 风格

    2021-03-24 17:30:39
    RESTful 就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 RESTful 风格的好处:简洁(路径更加简洁)、安全(不暴露...

    一、概念

    RESTful 就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    RESTful 风格的好处:简洁(路径更加简洁)、安全(不暴露参数,隐藏了程序中的信息)、高效(支持缓存)。

    二、功能

    • 资源:互联网所有的事物都可以被抽象为资源
    • 资源操作:使用 POST、DELETE、PUT、GET,使用不同方法对资源进行操作
    • 分别对应 添加、删除、修改、查询

    三、传统方式操作资源

    通过不同的参数来实现不同的效果!方法单一,POST 和 GET

    • http://127.0.0.1/item/queryItem.action?id=1 查询,GET
    • http://127.0.0.1/item/saveItem.action 新增,POST
    • http://127.0.0.1/item/updateItem.action 更新,POST
    • http://127.0.0.1/item/deleteItem.action?id=1 删除,GET 或 POST

    四、使用 RESTful 操作资源

    可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

    • http://127.0.0.1/item/1 查询,GET
    • http://127.0.0.1/item 新增,POST
    • http://127.0.0.1/item 更新,PUT
    • http://127.0.0.1/item/1 删除,DELETE

    五、报错处理

    1、如果报错405,检查请求方式是否有问题。我们使用浏览器地址栏进行访问默认是 GET 请求,会有可能报错405。所有的地址栏请求默认都会是 HTTP GET 类型的

    展开全文
  • RESTful风格API详解

    2021-01-27 20:00:47
    在学习RESTful 风格接口之前,即使你不知道它是什么,但你肯定会好奇它能解决什么问题?有什么应用场景?听完下面描述我想你就会明白: 在互联网并没有完全流行的初期,移动端也没有那么盛行,页面请求和并发量也不...

    在学习RESTful 风格接口之前,即使你不知道它是什么,但你肯定会好奇它能解决什么问题?有什么应用场景?听完下面描述我想你就会明白:

    在互联网并没有完全流行的初期,移动端也没有那么盛行,页面请求和并发量也不高,那时候人们对接口的要求没那么高,一些动态页面(jsp)就能满足绝大多数的使用需求。

    在这里插入图片描述

    但是随着互联网和移动设备的发展,人们对Web应用的使用需求也增加,传统的动态页面由于低效率而渐渐被HTML+JavaScript(Ajax)的前后端分离所取代,并且安卓、IOS、小程序等形式客户端层出不穷,客户端的种类出现多元化,而客户端和服务端就需要接口进行通信,但接口的规范性就又成了一个问题:

    在这里插入图片描述

    所以一套结构清晰、符合标准、易于理解、扩展方便让大部分人都能够理解接受的接口风格就显得越来越重要,而RESTful风格的接口(RESTful API)刚好有以上特点,就逐渐被实践应用而变得流行起来。

    在这里插入图片描述

    现在,RESTful是目前最流行的接口设计规范,在很多公司有着广泛的应用,其中Github 的API设计就是很标准的RESTful API,你可以参考学习。

    在开发实践中我们很多人可能还是使用传统API进行请求交互,很多人其实并不特别了解RESTful API,对RESTful API的认知可能会停留在:

    • 面向资源类型的
    • 是一种风格
    • (误区)接口传递参数使用斜杠(/)分割而不用问号(?)传参。

    而其实一个很大的误区不要认为没有查询字符串就是RESTful API,也不要认为用了查询字符串就不是RESTful API,更不要认为用了JSON传输的API就是RESTful API。

    本篇将带你了解RESTful并用SpringBoot实战RESTful API.

    一、REST介绍

    REST涉及一些概念性的东西可能比较多,在实战RESTful API之前,要对REST相关的知识有个系统的认知。

    REST的诞生

    REST(英文:Representational State Transfer,简称REST,直译过来表现层状态转换)是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    它首次出现在 2000 年 Roy Thomas Fielding 的博士论文中,这篇论文定义并详细介绍了表述性状态转移(Representational State Transfer,REST)的架构风格,并且描述了 如何使用 REST 来指导现代 Web 架构的设计和开发。用他自己的原话说:

    我写这篇文章的目的是:在符合架构原理前提下,理解和评估基于网络的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。

    需要注意的是REST并没有一个明确的标准,而更像是一种设计的风格,满足这种设计风格的程序或接口我们称之为RESTful(从单词字面来看就是一个形容词)。所以RESTful API 就是满足REST架构风格的接口。

    在这里插入图片描述

    Fielding博士答辩

    Fielding博士当时提出的是REST架构在很久的时间内并没有被关注太多,而近些年REST在国内才变得越来越流行。下面开始详细学习REST架构特征。

    REST架构特征

    既然知道REST和RESTful的联系和区别,现在就要开始好好了解RESTful的一些约束条件和规则,RESTful是一种风格而不是标准,而这个风格大致有以下几个主要特征:

    以资源为基础 :资源可以是一个图片、音乐、一个XML格式、HTML格式或者JSON格式等网络上的一个实体,除了一些二进制的资源外普通的文本资源更多以JSON为载体、面向用户的一组数据(通常从数据库中查询而得到)。

    统一接口: 对资源的操作包括获取、创建、修改和删除,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。换言而知,使用RESTful风格的接口但从接口上你可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断。具体的HTTP方法和方法含义如下:

    • GET(SELECT):从服务器取出资源(一项或多项)。
    • POST(CREATE):在服务器新建一个资源。
    • PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
    • PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
    • DELETE(DELETE):从服务器删除资源。

    当然也有很多在具体使用的时候使用PUT表示更新。从请求的流程来看,RESTful API和传统API大致架构如下:

    在这里插入图片描述

    URI指向资源:URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。URI包括URL和URN,在这里更多时候可能代指URL(统一资源定位符)。RESTful是面向资源的,每种资源可能由一个或多个URI对应,但一个URI只指向一种资源。

    无状态:服务器不能保存客户端的信息, 每一次从客户端发送的请求中,要包含所有必须的状态信息,会话信息由客户端保存, 服务器端根据这些状态信息来处理请求。当客户端可以切换到一个新状态的时候发送请求信息, 当一个或者多个请求被发送之后, 客户端就处于一个状态变迁过程中。每一个应用的状态描述可以被客户端用来初始化下一次的状态变迁。

    REST架构限制条件

    Fielding在论文中提出REST架构的6个限制条件,也可称为RESTful 6大原则, 标准的REST约束应满足以下6个原则:

    客户端-服务端(Client-Server): 这个更专注客户端和服务端的分离,服务端独立可更好服务于前端、安卓、IOS等客户端设备。

    无状态(Stateless):服务端不保存客户端状态,客户端保存状态信息每次请求携带状态信息。

    可缓存性(Cacheability) :服务端需回复是否可以缓存以让客户端甄别是否缓存提高效率。

    统一接口(Uniform Interface):通过一定原则设计接口降低耦合,简化系统架构,这是RESTful设计的基本出发点。当然这个内容除了上述特点提到部分具体内容比较多详细了解可以参考这篇REST论文内容。

    分层系统(Layered System):客户端无法直接知道连接的到终端还是中间设备,分层允许你灵活的部署服务端项目。

    按需代码(Code-On-Demand,可选):按需代码允许我们灵活的发送一些看似特殊的代码给客户端例如JavaScript代码。

    REST架构的一些风格和限制条件就先介绍到这里,后面就对RESTful风格API具体介绍。

    二、RESTful API设计规范

    既然了解了RESTful的一些规则和特性,那么具体该怎么去设计一个RESTful API呢?要从URL路径、HTTP请求动词、状态码和返回结果等方面详细考虑。至于其他的方面例如错误处理、过滤信息等规范这里就不详细介绍了。

    URL设计规范

    URL为统一资源定位器 ,接口属于服务端资源,首先要通过URL这个定位到资源才能去访问,而通常一个完整的URL组成由以下几个部分构成:

    URI = scheme "://" host  ":"  port "/" path [ "?" query ][ "#" fragment ]
    

    scheme: 指底层用的协议,如http、https、ftp
    host: 服务器的IP地址或者域名
    port: 端口,http默认为80端口
    path: 访问资源的路径,就是各种web 框架中定义的route路由
    query: 查询字符串,为发送给服务器的参数,在这里更多发送数据分页、排序等参数。
    fragment: 锚点,定位到页面的资源

    我们在设计API时URL的path是需要认真考虑的,而RESTful对path的设计做了一些规范,通常一个RESTful API的path组成如下:

    /{version}/{resources}/{resource_id}
    

    version:API版本号,有些版本号放置在头信息中也可以,通过控制版本号有利于应用迭代。
    resources:资源,RESTful API推荐用小写英文单词的复数形式。
    resource_id:资源的id,访问或操作该资源。

    当然,有时候可能资源级别较大,其下还可细分很多子资源也可以灵活设计URL的path,例如:

    /{version}/{resources}/{resource_id}/{subresources}/{subresource_id}
    

    此外,有时可能增删改查无法满足业务要求,可以在URL末尾加上action,例如

    /{version}/{resources}/{resource_id}/action
    

    其中action就是对资源的操作。

    从大体样式了解URL路径组成之后,对于RESTful API的URL具体设计的规范如下:

    1. 不用大写字母,所有单词使用英文且小写。
    2. 连字符用中杠"-“而不用下杠”_"
    3. 正确使用 "/"表示层级关系,URL的层级不要过深,并且越靠前的层级应该相对越稳定
    4. 结尾不要包含正斜杠分隔符"/"
    5. URL中不出现动词,用请求方式表示动作
    6. 资源表示用复数不要用单数
    7. 不要使用文件扩展名

    HTTP动词

    在RESTful API中,不同的HTTP请求方法有各自的含义,这里就展示GET,POST,PUT,DELETE几种请求API的设计与含义分析。针对不同操作,具体的含义如下:

    GET /collection:从服务器查询资源的列表(数组)
    GET /collection/resource:从服务器查询单个资源
    POST /collection:在服务器创建新的资源
    PUT /collection/resource:更新服务器资源
    DELETE /collection/resource:从服务器删除资源
    

    在非RESTful风格的API中,我们通常使用GET请求和POST请求完成增删改查以及其他操作,查询和删除一般使用GET方式请求,更新和插入一般使用POST请求。从请求方式上无法知道API具体是干嘛的,所有在URL上都会有操作的动词来表示API进行的动作,例如:query,add,update,delete等等。

    而RESTful风格的API则要求在URL上都以名词的方式出现,从几种请求方式上就可以看出想要进行的操作,这点与非RESTful风格的API形成鲜明对比。

    在谈及GET,POST,PUT,DELETE的时候,就必须提一下接口的安全性和幂等性,其中安全性是指方法不会修改资源状态,即读的为安全的,写的操作为非安全的。而幂等性的意思是操作一次和操作多次的最终效果相同,客户端重复调用也只返回同一个结果。

    上述四个HTTP请求方法的安全性和幂等性如下:

    HTTP Method安全性幂等性解释
    GET安全幂等读操作安全,查询一次多次结果一致
    POST非安全非幂等写操作非安全,每多插入一次都会出现新结果
    PUT非安全幂等写操作非安全,一次和多次更新结果一致
    DELETE非安全幂等写操作非安全,一次和多次删除结果一致

    状态码和返回数据

    服务端处理完成后客户端也可能不知道具体成功了还是失败了,服务器响应时,包含状态码和返回数据两个部分。

    状态码

    我们首先要正确使用各类状态码来表示该请求的处理执行结果。状态码主要分为五大类:

    1xx:相关信息
    2xx:操作成功
    3xx:重定向
    4xx:客户端错误
    5xx:服务器错误

    每一大类有若干小类,状态码的种类比较多,而主要常用状态码罗列在下面:

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*]:表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

    返回结果

    针对不同操作,服务器向用户返回数据,而各个团队或公司封装的返回实体类也不同,但都返回JSON格式数据给客户端。

    三、一个RESTful API案例

    上面讲了RESTful理论知识,下面动手实现一个小案例吧!

    预备

    在本案例的实战中,我们访问的RESTful接口都是对数据库真实的操作,新建数据库,创建一个数据库和表(根据自己喜好)。

    选择Maven依赖的时候,只需要勾选其中Spring的Web模块、MySQL驱动以及MyBatis框架。

    本案例的POJO创建Dog.java实体对象,其具体构造为:

    package com.restfuldemo.pojo;
    
    public class Dog {
        private int id;//唯一id标识
        private String name;//名称
        private  int age;//年龄
        //省略get set
    }
    

    上面创建好了项目,我们就开始构建RESTful风格的API。在具体构建RESTful API的时候,需要对各种请求有更细致的认知,当然,本案例在实现各种请求的时候为了演示的便捷并没有完全遵循RESTful API规范,例如版本号等信息这里就不添加了,案例更侧重于使用SpringBoot实现这个接口。

    本案例实现对dog资源的增删改查,如下是非RESTful 和RESTful接口对比:

    API name非 RESTfulRESTful
    获取dog/dogs/query/{dogid}GET: /dogs/{dogid}
    插入dog/dogs/addPOST: /dogs
    更新dog/dogs/update/{dogid}PUT:/dogs/{dogid}
    删除dog/dods/delete/{dogid}DELETE:/dogs/{dogid}

    另外在使用postman进行发送请求的时候,有三种常用的文件类型传递到后端:

    在这里插入图片描述

    form-data :就是form表单中的multipart/form-data,会将表单数据处理为一条信息,用特定标签符将一条条信息分割开,而这个文件类型通常用来上传二进制文件。
    x-www-form-urlencoded:就是application/x-www-form-urlencoded,是form表单默认的encType,form表单会将表单内的数据转换为键值对,这种格式不能上传文件。

    raw:可以上传任意格式的文本,可以上传Text,JSON,XML等,但目前大部分还是上传JSON格式数据。当后端需要接收JSON格式数据处理的时候,可以采用这种格式来测试。

    因为GET请求查询参数在URL上,其他类型请求使用x-www-form-urlencoded方式向后端传值。

    GET POST PUT DELETE请求

    GET请求用来获取资源:GET请求会向数据库发索取数据的请求,从而来获取资源,该请求就像数据库的select操作一样,只是用来查询数据,不会影响资源的内容。无论进行多少次操作,结果都是一样的。

    并且GET请求会把请求的参数附加在URL后面,但是不同的浏览器对其有不同的大小长度限制。

    在本案例中,我们设计两个GET请求的API。
    GET /dogs :用来返回dog资源的列表。
    GET /dogs/{dogid} :用来查询此id的单个dog资源。

    POST请求用来新增一个资源 : POST请求向服务器发送数据,但是该请求会改变数据的内容(新添),就像数据库的insert操作一样,会创建新的内容。且POST请求的请求参数都是请求体中,其大小是没有限制的。

    在本案例中,我们设计以下POST请求的API。
    POST /dogs :服务端新增一个dog资源。

    PUT请求用来更新资源,PUT请求是向服务器端发送数据的, 与POST请求不同的是,PUT请求侧重于数据的修改 ,就像数据库中update一样,而POST请求侧重于数据的增加。

    在本案例中,我们设计以下POST请求的API。
    PUT /dogs/{dogid} :用来更新此id的单个dog资源。

    DELETE 请求用来删除资源,DELETE请求用途和它字面意思一致,用来删除资源。和数据库中delete相对应。

    在本案例中,我们设计以下DELETE请求的API。
    DELETE /dogs/{dogid} :用来删除此id的单个dog资源。

    对应的Mapper文件为:

    package com.restfuldemo.mapper;
    
    import com.restfuldemo.pojo.Dog;
    import org.apache.ibatis.annotations.*;
    import java.util.List;
    
    @Mapper
    public interface DogMapper {
    
        @Select("select * from dog")
        List<Dog> getAllDog();
    
        @Select("select * from dog where id=#{id}")
        Dog getDogById(@Param("id") int id);
    
        @Insert("insert into dog (name,age) values (#{name},#{age})")
        boolean addDog(Dog dog);
    
        @Update("update dog set name=#{name},age=#{age} where id=#{id}")
        boolean updateDog(Dog dog);
    
        @Delete("delete  from dog where id=#{id}")
        boolean deleteDogById(int id);
    }
    

    对应controller文件为:

    package com.restfuldemo.controller;
    
    import com.restfuldemo.mapper.DogMapper;
    import com.restfuldemo.pojo.Dog;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.Arrays;
    import java.util.List;
    
    @RestController
    public class TestController {
    
        @Autowired(required = false)
        DogMapper dogMapper;
    
        @GetMapping("dogs")
        public List<Dog> getDogs()
        {
            return  dogMapper.getAllDog();
        }
    
        @GetMapping("dogs/{id}")
        public Dog getDogById(@PathVariable("id") int id)
        {
            Dog dog=dogMapper.getDogById(id);
            return  dog;
        }
        @PostMapping("dogs")
        public boolean addDog(Dog dog)
        {
            return dogMapper.addDog(dog);
        }
        @PutMapping("dogs/{id}")
        public boolean updateDog(@PathVariable("id")int id,@RequestParam("name")String name,@RequestParam("age")int age)
        {
    
            Dog dog=dogMapper.getDogById(id);
            dog.setName(name);
            dog.setAge(age);
            return  dogMapper.updateDog(dog);
        }
    
        @DeleteMapping("dogs/{id}")
        public boolean deleteDog(@PathVariable("id") int id)
        {
            return  dogMapper.deleteDogById(id);
        }
    }
    

    经过笔者测试一切都是ok的,如果要项目源文件请联系笔者发你哈!

    总结

    RESTful风格的API 固然很好很规范,但大多数互联网公司并没有按照或者完全按照其规则来设计,因为REST是一种风格,而不是一种约束或规则,过于理想的RESTful API 会付出太多的成本。

    比如RESTful API也有一些缺点

    • 比如操作方式繁琐,RESTful API通常根据GET、POST、PUT、DELETE 来区分操作资源的动作,而HTTP Method 本身不可直接见,是隐藏的,而如果将动作放到URL的path上反而清晰可见,更利于团队的理解和交流。
    • 并且有些浏览器对GET,POST之外的请求支持不太友好,还需要特殊额外的处理。
    • 过分强调资源,而实际业务API可能有各种需求比较复杂,单单使用资源的增删改查可能并不能有效满足使用需求,强行使用RESTful风格API只会增加开发难度和成本。

    所以,当你或你们的技术团队在设计API的时候,如果使用场景和REST风格很匹配,那么你们可以采用RESTful 风格API。但是如果业务需求和RESTful风格API不太匹配或者很麻烦,那也可以不用RESTful风格API或者可以借鉴一下,毕竟无论那种风格的API都是为了方便团队开发、协商以及管理,不能墨守成规。

    在这里插入图片描述

    到这里RESTful API的介绍和实战就结束啦,本篇首先从RESTful的一些特点进行介绍,再到SpringBoot实战RESTful API,最后也说了一些RESTful API并不完美的地方,相信睿智的你对RESTful 一定有了很深刻的理解。在以后项目的API设计上定能有所优化。

    不同的人对RESTful API可能有着不同的理解,但存在即合理,RESTful API有着其鲜明的优势和特点,目前也是一种API设计的主要选型之一,所以掌握和理解RESTful API还是相当重要的!

    展开全文
  • RestFul风格详解

    千次阅读 多人点赞 2021-03-11 16:52:16
    文章目录一、前言二、什么是RestFul风格三、传统风格与RestFul风格对比1. 传统方式操作资源2. RestFul方式操作资源四、RestFul代码演示1.代码展示2.拓展情景五、使用method属性指定请求类型六、总结 一、前言 该技术...
  • RestFul风格传参

    千次阅读 2021-01-04 21:50:27
    RestFul风格就是所有参数都由/传递,而不是传统的?xx&xx形式 例如:写一个Controller: package controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import...
  • Restful风格的URL请求

    2021-03-17 16:18:17
    pattern> filter-mapping> b:在 @RequesetMapping 注解用指定 method 的方式来匹配 url /** * restful风格的用户列表 * @return */ @RequestMapping(value="/users",method = RequestMethod.GET) public @...
  • Restful风格怎么实现

    2021-07-14 15:09:12
    RestFul 风格 概念 Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 比较 传统方式操作资源 :通过不同的参数来...
  • restful风格API

    2021-04-12 21:58:24
    个人对restful风格API的理解即遵循restful风格和期设计原则设计的API 一、协议 API与用户的通信协议,总是使用HTTPs协议。 二、域名 应该尽量将API部署在专用域名之下。https://api.example.com 如果确定API很简单...
  • Restful风格接口浅析

    2020-12-24 20:08:58
    为什么使用RESTful1.JSP技术可以让我们在页面中嵌入Java代码,但是这样的技术实际上限制了我们的开发效率,因为需要我们Java工程师将html转换为jsp页面,并写一些脚本代码,或者前端代码。这样会严重限制我们的开发...
  • VUE使用axios封装RESTful风格 本文章讲述axios的使用、封装代码、restful风格、接口定义规则知识点。可以根据本文章拓展自己的业务。源代码 文章目录VUE使用axios封装RESTful风格前言一、使用axios1.代码2.知识点二...
  • RESTful风格

    2021-02-12 21:43:55
    是Web服务的一种新的架构风格(一种思想)。 RESTful架构的主要原则 对网络上所有的资源都有一个资源标志符。 对资源的操作不会改变标识符。 同一资源有多种表现形式(xml、json) 所有操作都是无状态的(Stateless...
  • restful风格案例

    2021-03-18 17:29:26
    RestFul风格案例理解一、原则:通过四种不同的请求方式来表示CRUD操作问题:页面请求只支持get/post方式,并不支持其他方式,如何处理?二、实际操作时代码1.html2.handler3.想要修改_method用其他的name替换,如何...
  • RestFul风格的理解

    2021-10-14 23:07:27
    平常经常听到RestFul相关的内容有时候说是RestFul架构、有时候说是RestFul风格,有时候还会拿它与RPC来做对比,那么他到底是什么呢?一直以来我也不是很明白说是说理解的是是而非,真正对RestFul有一个较为全面的...
  • restFul风格:在超链接进行删除操作时,需要阻止超链接的跳转, 并创建一个表单,有隐藏输入框name为_method,value为DELETE, 与超链接的单击事件绑定,将超链接的href赋值给表单的action, 并submit().进行提交, 即可实现...
  • postman测试restful风格

    2021-05-12 23:26:08
    RESTful是一种代码风格, 路径代表资源 路径中有参数 不同的功能使用不同的http请求方式(get post put delete) 一般应用在前后端分离的项目中 @PathVariable 截取路径中的参数 不能使用id=111来传递参数,会报错 ....
  • Restful风格: 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 URL定义...
  • RestFul 风格

    2021-05-09 08:21:09
    Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 功能 资源:互联网所有的事物都可以被抽象为资源 资源操作:...
  • 在本教程中,我将基于Spring 2.2.6版本实现一个基于Restful风格的文件上传与下载APIs。 文章已经收录至独立博客,点击左下角阅读原文前往! Part1环境 JDK: Java 1.8 Framework: Spring Boot 2.2.6(Only Using ...
  • restful风格与url请求

    2021-03-23 16:56:17
    restful风格 http://ip:端口号/控制器访问路径/参数1/参数2、 http://localhost:9001/brand/search/1/5 分页操作 controller层: 传入参数是必须为参数添加注解@PathVariable(“请求的参数名”) 服务中的参数信息 ...
  • 传统风格要四个地址 add delete update (post) find (get)如果是put和delete...而restful风格 student即可 然后 用get post delete putMapping即可 不需要写额外的地址 这个可以用?传参 也可以用地址传参 ...
  • 1 接口名称 用户注册接口 2 接口描述 用户信息注册 用户可以通过 手机号/邮箱 进行注册 同一个 手机号/邮箱只能注册一个账号 3 请求地址 {apiAddress}/api/user/signup 4 请求方式 POST 5 请求参数 ...是
  • 文章目录Spring JSON数据交互和RESTful风格1.什么是JSON2.JSON数据结构1.对象结构2.数组结构3.JSON数据转换事例RESTful 风格 Spring JSON数据交互和RESTful风格 1.什么是JSON JSON(JavaScript Object Notation, JS ...
  • 什么是Restful风格接口?

    千次阅读 2020-12-24 10:02:06
    1.定义:Restful风格的API是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。 明确:他只是种代码风格的约束,而不是说非要这样干。 2.各个...
  • springboot Restful风格get请求接口

    千次阅读 2020-12-23 11:13:43
    springboot Restful风格get请求接口 1.参数直接在路径中 package com.example.demo.controller; import com.example.demo.model.Phone; import com.example.demo.model.User; import org.springframework.web.bind....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,544
精华内容 23,817
关键字:

restful风格