可以一次引入所有扩展能力
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
This is the multi-page printable view of this section. Click here to print.
Restlight
内置了常用的Filter(IP白名单、新建连接数限制、CPU过载保护)、Interceptor(访问日志、参数签名验证)和表单参数解析器可以一次引入所有扩展能力
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
使用新建连接数限制时请先确保引入了依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
当前服务的新建连接数进行QPS限制。超过连接数限制的请求将被拒绝。
使用方式:
#开启新建连接数限制
restlight.server.ext.connection-creation-limit.enable=true
#设置每秒限制4000个新建连接,默认为20000
restlight.server.ext.connection-creation-limit.max-per-second=40000
使用新建连接数限制时请先确保引入了依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
#开启Cpu Load自我保护
restlight.server.ext.cpu-load-protection.enable=true
#cpu负载阈值,默认为80.0D cpu超过此负载之后将开始随机丢弃连接
restlight.server.ext.cpu-load-protection.threshold=80.0D
#初始连接丢弃率,默认为10.0D(0代表0%, 100代表100%, 可以传小数)
restlight.server.ext.cpu-load-protection.initial-discard-rate=10.0D
#最大连接丢弃率,默认为80.0D(0代表0%, 100代表100%, 可以传小数)
restlight.server.ext.cpu-load-protection.max-discard-rate=80.0D
上面的配置将会在cpu负载到达75%时开始随机丢弃20%的新建连接, 随着cpu负载的升高达到100%则将会丢弃80%的连接。
说明:
当cpu负载到达或者超过cpu-load-threshold
的值时开始丢弃连接,初始连接丢弃概率为initial-discard-rate
, 随着cpu负载升高, 丢弃率将随着cpu负载的升高而成正比的升高, 当cpu负载达到100%时丢弃率将达到max-discard-rate
.
使用Restlight访问日志拦截器时请确保已经引入了依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
AccessLog拦截器在每个请求结束后记录访问日志,内容包含:客户端地址、请求协议、请求url(不包含路径参数)、请求方法、请求耗时、响应状态码、响应body大小以及访问时间。使用时需要做如下配置:
#开启AccessLog
restlight.server.ext.accesslog.enable=true
restlight.server.ext.accesslog
开头
配置项 | 默认 | 说明 |
---|---|---|
enable | false | 是否启用 |
directory | logs | 日志文件路径 |
fileName | access.log | 日志文件名 |
charset | 日志编码 | |
rolling | true | 是否按照时间滚动生成文件 |
date-pattern | yyyy-MM-dd | 日期滚动格式,yyyy-MM-dd表示按天为单位滚动,生成的文件名为access.yyyy-MM-dd.log, 仅支持按天和小时为单位滚动,因此可选值:yyyy-MM-dd或者yyyy-MM-dd_HH(注意不要使用yyyy-MM-dd HH, 生成的文件名可能不符合操作系统文件命名规范) |
max-history | 10 | 最大历史文件个数 |
full-uri | false | 是否打印uri中所有的内容(包含url参数) |
引入依赖
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
开启跨域功能
restlight.server.ext.cors.enable=true
更多跨域相关配置
restlight.server.ext.cors.rules[0].anyOrigin=false
restlight.server.ext.cors.rules[0].origins=www.example.com,www.demo.com
restlight.server.ext.cors.rules[0].expose-headers=foo,bar
restlight.server.ext.cors.rules[0].allow-credentials=false
restlight.server.ext.cors.rules[0].allow-methods=GET,POST
restlight.server.ext.cors.rules[0].allow-headers=foo,bar
restlight.server.ext.cors.rules[0].max-age=3600
Restlight
提供了表单参数解析的功能,使用时需要单独引入相应的包:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-multipart-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
使用示例如下:
@Controller
@RequestMapping("/restlight/file/")
public class FileSupportController
// 上传单个文件
@RequestMapping("/upload")
public String fileUpload(@UploadFile MultipartFile multipartFile) throws IOException {
File temp = new File("D:\\" + multipartFile.originalFilename());
multipartFile.transferTo(temp);
return "SUCCESS";
}
// 上传一组文件
@RequestMapping("/uploads")
public String fileUploads(@UploadFile List<MultipartFile> files) throws IOException {
for (MultipartFile file : files) {
File temp = new File("D:\\" + file.originalFilename());
file.transferTo(temp);
}
return "SUCCESS";
}
}
Restlight
默认请求body大小为4MB,当上传文件时需要根据需要调整该值的大小;默认的编码格式为:UTF-8。使用时,也可以通过配置文件改变上述参数值:
#设置请求body大小 4MB = 4 * 1024 * 1024 = 4194304
restlight.server.max-content-length=4194304
#编码方式
restlight.server.ext.multipart.charset=utf-8
#单个文件大小限制,默认-1(没有限制) 4KB = 4 * 1024 = 4096
restlight.server.ext.multipart.max-size=4096
#是否使用临时文件,为true时任何大小的文件都使用临时文件,默认为false
restlight.server.ext.multipart.use-disk=true
#临时文件目录
restlight.server.ext.multipart.temp-dir=D:\\temp
#当multipart-use-disk为false且单个文件大小超过该值时使用临时文件,默认2MB
restlight.server.ext.multipart.memory-threshold=2097152
在需要接收的方法参数上加上@FormParam
注解,如下:
@RequestMapping("/upload")
public String uploadFormParams(@FormParam String formParam0, @FormParam String formParam1) {
return formParam0 + "; " + formParam1;
}
使用Restlight参数签名验证拦截器时请先引入依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-interceptor-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
参数签名验证拦截器可以验证请求参数的签名,防止请求参数被篡改。使用时请做如下配置:
#开启参数签名验证功能的必需配置
restlight.server.ext.sign.enable=true
#调用方ID参数名,默认为appId
restlight.server.ext.sign.app-id-name=appId
#签名秘钥版本参数名,默认为sv
restlight.server.ext.sign.secret-version-name=sv
#请求时间戳参数名,默认为ts
restlight.server.ext.sign.timestamp-name=ts
#请求时间戳有效期:单位秒(默认为0)
restlight.server.ext.sign.expire-seconds=0
#签名参数名称,默认为sign
restlight.server.ext.sign.signature-name=sign
#是否对所有接口进行签名验证(默认为false)
restlight.server.ext.sign.verify-all=true
Restlight提供了两种不同的方式来自定义需要进行签名验证的接口:1. 在全局接口都进行签名验证的情况下,使用@IgnoreSignValidation注解忽略指定接口的签名验证功能;2. 在全局接口都不进行签名验证的前提下,使用@SignValidation注解指定对需要进行签名验证的接口。默认使用方式2。 方式1使用示例:
restlight.server.ext.sign.verify-all=true
@RequestMapping("/index")
@IgnoreSignValidation
public void index() {
TestService.list();
}
如上配置表示:对index()方法之外的其他接口均开启签名验证功能。
方式2使用示例:
restlight.server.ext.sign.verify-all=false
@RequestMapping("/index")
@SignValidation
public void index() {
TestService.list();
}
如上配置表示:只对index()方法对应的接口开启签名验证功能。
Restlight
默认使用HmacSHA1作为验签时原始请求的签名生成方法,当用户使用其它算法可以注入自定义的参数签名验证拦截器,使用示例如下:
@Component
public class CustomizeSignatureValidationFactory extends SignValidationHandlerInterceptorFactory {
public CustomizeSignatureValidationFactory(SecretDistributor distributor) {
super(distributor);
}
@Override
protected AbstractSignatureRouteInterceptor doCreate(SignatureOptions options, SecretDistributor distributor) {
return new AbstractSignatureRouteInterceptor(options, distributor) {
@Override
protected boolean validate(byte[] data, String signature, String sk) {
// customize validation
}
};
}
}
引入依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
使用方式:
#开启Xss过滤
restlight.server.ext.xss.enable=true
#Xss过滤模式,默认escape(转义模式),filter为过滤模式
restlight.server.ext.xss.mode=escape
配置好后自动对所有请求进行转义或者过滤。
支持URL
参数过滤及不完整的Header
过滤
AsyncRequest.getHeader(CharSequence name)
以及AsyncRequest.getHeader(String name)
方法。
Escape
& Filter
模式Escape
模式该模式会对用户请求的 URL
参数 和 Header
进行转义,转义的字符集如下:
转义前 | 转义后 |
---|---|
> | > |
< | < |
" | " |
& | & |
Filter
模式该模式会对用户请求的 URL
参数 和 Header
进行过滤,删除容易引起 Xss 的标签或者表达式,以空串代替,比如 name=<script>...</script>
,过滤以后会直接将 <script>...</script>
以空串替换,即 name=""
,需要以空串替换的标签和表达式如下:
标签或表达式 |
---|
<script>…</script> |
</script> |
<script …> |
src='…' |
src="…" |
eval(…) |
expression(…) |
javascript: |
alert |
onload= |
vbscript: |
使用Restlight内置的IP白名单时请先确保引入了依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-filter-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
IP白名单拦截器可以过滤非法IP的访问。同时支持IP地址和正则表达式两种匹配方式,需要配置的内容如下:
#开启IP白名单拦截器的必需配置
restlight.server.ext.whitelist.enable=true
#IP白名单列表(多值请用逗号分隔,正则表达式regex:开头)
restlight.server.ext.whitelist.ips=10.10.1.1,regex:10.12.*
#缓存最近访问的IP地址(默认1024个)
restlight.server.ext.whitelist.cache-size=1024
#缓存的失效时间(单位:ms,默认为60s)
restlight.server.ext.whitelist.expire=60000
使用Restlight内置的数据校验请先确保引入了依赖:
<dependency>
<groupId>io.esastack</groupId>
<artifactId>restlight-ext-validator-starter</artifactId>
<version>${restlight.version}</version>
</dependency>
使用注解声明对属性的约束
private class Employee {
@NotEmpty
private String name;
@Min(18)
@Max(60)
private int age;
@Email
private String email;
@Length(min = 10, max = 20)
private String address;
// 级联校验
@Valid
private Object cascadingObject;
}
作为方法参数校验, 需要使用@Valid
注解标记被校验的参数
@PostMapping("/add")
public String add(@Valid @RequestBody Employee employee) {
return SUCCESS;
}
作为返回值, 需要使用@Valid
注解标记方法或者参数
@Valid
@ResponseBody
@RequestMapping("/list")
public Employee list1() {
return new Employee("", 16, "", "");
}
或者
@ResponseBody
@RequestMapping("/list")
public @Valid Employee list2() {
return new Employee("", 16, "", "");
}
@Valid
来显示声明需要对该参数进行校验。
直接使用注解
@RequestMapping("/update")
public String update(@RequestParam @NotEmpty String name, @RequestParam @Length(min = 10, max = 20) String newAddress) {
return SUCCESS;
}
使用@ValidGroup
指定校验方法的参数、返回值校验时的分组。该注解只能标注在方法上并且value值只能为接口类(默认为Default.class
)。
Example:
@ValidGroup(Interface.class)
@RequestMapping("/addGroup")
public String addGroup(@Valid @RequestBody Employee employee) {
return SUCCESS;
}
当内置的约束注解不能满足业务需求时,可以使用@Constraint
自定义约束注解,具体实现使用hibernate-validation,使用方式与Spring MVC无差异,示例如下:
自定义约束注解:
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = LogInSuccess.LogInSuccessValidator.class)
@Target(value = {ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Documented
public @interface LogInSuccess {
String message() default "登录校验未通过";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class LogInSuccessValidator implements ConstraintValidator<LogInSuccess, String> {
@Override
public void initialize(LogInSuccess constraintAnnotation) {
// Do nothing
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return false;
}
}
}
使用自定义约束注解:
@RequestMapping("/getId")
public String getId(@RequestParam @LogInSuccess(message = "请先登录") String userName) {
return "SUCCESS";
}
数据校验的异常消息允许自定义并且支持国际化,自定义异常处理消息的步骤如下:
自定义异常消息文件,在classpath路径下加入配置文件,如validation-message.properties
key1=value1
key2=value2
...
配置异常消息文件名,在application中配置异常消息文件名,如:
#该文件名称对应上面定义的validation-message.properties文件
restlight.server.ext.validation.message-file=validation-message
修改约束注解的message属性值,如:
@NotEmpty(message="{key1}")
public String name;
@Min(value=18, message="{key2}")
public int age;
针对不同语言定义不同的异常消息文件,如:
注解 | 功能 | 说明 |
---|---|---|
@AssertFalse | 被注解元素必须为false | |
@AssertTrue | 被注解的元素必须为true | |
@DecimalMax(value) | 被注解的元素必须为一个数字,其值必须小于等于指定的最小值 | |
@DecimalMin(Value) | 被注解的元素必须为一个数字,其值必须大于等于指定的最小值 | |
@Digits(integer=, fraction=) | 被注解的元素必须为一个数字,其值必须在可接受的范围内 | |
@Future | 被注解的元素必须是未来的日期 | |
@Max(value) | 被注解的元素必须为一个数字,其值必须小于等于指定的最大值 | |
@Min(value) | 被注解的元素必须为一个数字,其值必须大于等于指定的最小值 | |
@NotNull | 被注解的元素必须不为null | |
@Null | 被注解的元素必须为null | |
@Past | 被注解的元素必须过去的日期 | |
@Pattern | 被注解的元素必须符合正则表达式 | |
@Size(min=, max=) | 被注解的元素必须在指定的范围(数据类型:String, Collection, Map and arrays) | |
被注解的元素被注释的元素必须是电子邮箱地址 | ||
@NotBlank | 被注解的对象必须为字符串,不能为空,检查时会忽略空格 | |
@NotEmpty | 被注释的对象长度不能为0(数据:String,Collection,Map,arrays) | |
@Length(min=, max=) | 被注解的对象必须是字符串并且长度必须在指定的范围内 | Hibernate扩展注解 |
@Range(min=, max=) | 被注释的元素必须在合适的范围内 (数据:BigDecimal, BigInteger, String, byte, short, int, long and 原始类型的包装类 ) | Hibernate扩展注解 |
@URL(protocol=, host=, port=, regexp=, flags=) | 被注解的对象必须是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件 | Hibernate扩展注解 |
org.hibernate.xxx
的注解。