一、关于RESTful
RESTful也可以简称为REST,是一种设计软件的风格。
RESTful既不是规定,也不是规范。
RESTful风格的典型表现主要有:
-
处理请求后是响应正文的
-
将具有唯一性的参数值设计在URL中
-
根据请求访问数据的方式,使用不用的请求方式
-
如果尝试添加数据,使用
POST
请求方式 -
如果尝试删除数据,使用
DELETE
请求方式 -
如果尝试修改数据,使用
PUT
请求方式 -
如果尝试查询数据,使用
GET
请求方式 -
这种做法在复杂的业务系统中并不适用
-
在设计RESTful风格的URL时,建议的做法是:
-
查询某数据的列表:
/数据类型的复数
,并使用GET
请求方式,例如/albums
-
查询某1个数据(通常根据id):
/数据类型的复数/id值
,并使用GET
请求方式,例如/albums/9527
-
对某1个数据进行操作(增、删、改):
/数据类型的复数/id值/操作
,并使用POST
请求方式,,例如/albums/9527/delete
二、
关于响应正文的结果
通常,需要使用自定义类,作为处理请求的方法、处理异常的方法的返回值类型。
响应到客户端的数据中,应该包含“业务状态码”,以便于客户端迅速判断操作成功与否,为了规范的管理业务状态码的值,在根包下创建web.ServiceCode
枚举类型:
package cn.tedu.csmall.product.web;
/**
* 业务状态码的枚举
*
* @author java@tedu.cn
* @version 0.0.1
*/
public enum ServiceCode {
OK(20000),
ERR_NOT_FOUND(40400),
ERR_CONFLICT(40900);
private Integer value;
ServiceCode(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
}
并且,修改ServiceException
异常类的代码,要求此类异常的对象中包含业务状态码,可以通过构造方法进行限制:
package cn.tedu.csmall.product.ex;
import cn.tedu.csmall.product.web.ServiceCode;
/**
* 业务异常
*
* @author java@tedu.cn
* @version 0.0.1
*/
public class ServiceException extends RuntimeException {
private ServiceCode serviceCode;
public ServiceException(ServiceCode serviceCode, String message) {
super(message);
this.serviceCode = serviceCode;
}
public ServiceCode getServiceCode() {
return serviceCode;
}
}
然后,原本业务逻辑层中抛出异常的代码将报错,需要在创建异常对象时传入业务状态码参数,例如:
throw new ServiceException(ServiceCode.ERR_CONFLICT,
"添加相册失败,尝试添加的相册名称已经被占用!");
接下来,还需要使用自定义类型,表示响应到客户端的数据,则在根包下创建web.JsonResult
类:
package cn.tedu.csmall.product.web;
import lombok.Data;
import java.io.Serializable;
@Data
public class JsonResult implements Serializable {
/**
* 业务状态码的值
*/
private Integer state;
/**
* 操作失败时的提示文本
*/
private String message;
public static JsonResult ok() {
JsonResult jsonResult = new JsonResult();
jsonResult.state = ServiceCode.OK.getValue();
return jsonResult;
}
public static JsonResult fail(ServiceCode serviceCode, String message) {
JsonResult jsonResult = new JsonResult();
jsonResult.state = serviceCode.getValue();
jsonResult.message = message;
return jsonResult;
}
}
在实际处理请求和异常时,Spring MVC框架会将方法返回的JsonResult
对象转换成JSON格式的字符串。
例如:处理请求的代码:
@RequestMapping("/add-new")
public JsonResult addNew(AlbumAddNewDTO albumAddNewDTO) {
log.debug("开始处理【添加相册】的请求,参数:{}", albumAddNewDTO);
albumService.addNew(albumAddNewDTO);
return JsonResult.ok();
}
例如:处理异常的代码:
@ExceptionHandler
public JsonResult handleServiceException(ServiceException e) {
log.debug("捕获到ServiceException:{}", e.getMessage());
return JsonResult.fail(e.getServiceCode(), e.getMessage());
}
通常,不需要在JSON结果中包含为null
的属性,所以,可以在application.properties
/ application.yml
中进行配置:
application.properties配置示例 :
# JSON结果中将不包含为null的属性
spring.jackson.default-property-inclusion=non_nul
application.yml配置示例 :
# Spring相关配置
spring:
# Jackson框架相关配置
jackson:
# JSON结果中是否包含为null的属性的默认配置
default-property-inclusion: non_null
三、实现前后端交互
目前,后端(服务器端)项目使用默认端口8080
,建议调整,可以通过配置文件中的server.port
属性来指定。
例如,在application-dev.yml
中添加配置:
# 服务端口
server:
port: 9080
再次启动项目,通过启动时的日志,可以看到后端项目启动在9080
端口。
然后,还需要在后端项目中配置允许跨域访问,则需要在实现了WebMvcConfigurer
接口的配置类中,通过重写addCorsMappings()
方法进行配置!
则在根包下创建config.WebMvcConfiguration
类,实现WebMvcConfigurer
接口,添加@Configuration
注解,并重写方法配置允许跨域访问:
package cn.tedu.csmall.product.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Spring MVC的配置类
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
public WebMvcConfiguration() {
System.out.println("创建配置类:WebMvcConfiguration");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}