Spring Boot 对基础 Web 开发的支持(下)2-2

接着上一课我们继续讲解。
 

数据校验
 

在很多时候,当我们要处理一个应用程序的业务逻辑时,数据校验是必须要考虑和面对的事情。应用程序必
须通过某种手段来确保输入进来的数据从语义上来讲是正确的。在 Java 应用程序中,必须要对输入进来的
数据从语义上分析是有效的,也就是数据校验。


输入验证最重要的 Web 开发任务之一,在 Spring MVC 中有两种方式可以验证输入:一种是 Spring 自带
的验证框架,另外一种是利利用 JSR 实现。


JSR 是一个规范文档,指定了一整套 API,通过标注给对象属性添加约束。 Hibernate Validator 就是 JSR 规
范的具体实现, Hibernate Validator 提供了 JSR 规范中所有内置约束注解的实现,以及一些附加的约束注
解,除此之外用户还可以自定义约束注解。


Spring Boot 的参数校验依赖于 hibernate-validator 来进行。使⽤用 Hibernate Validator 校验数据,需要定义一
个接收的数据模型,使用注解的形式描述字段校验的规则,我们以 User 对象为例为大家演示如何使用。


首先在 WebController 添加一个保存的方法 saveUser,参数为 User.
 

@RequestMapping("/saveUser")
public void saveUser(@Valid User user,BindingResult result) {
System.out.println("user:"+user);
if(result.hasErrors()) {
List<ObjectError> list = result.getAllErrors();
for (ObjectError error : list) {
System.out.println(error.getCode()+ "-" + error.getDefaultMessage());
}
}
}
  • @Valid 参数前面添加 @Valid 注解,代表此对象使用了参数校验;
  • BindingResult 参数校验的结果会存储在此对象中,可以根据属性判断是否校验通过,校验不通过可以将错误信息打印出来。

接下来在 User 中给需要校验的参数添加对应的注解,对不同的属性,按照规则添加不同的校验内容。

public class User {
@NotEmpty(message="姓名不能为空")
private String name;
@Max(value = 100, message = "年年龄不能大于100岁")
@Min(value= 18 ,message= "必须年满18岁! " )
private int age;
@NotEmpty(message="密码不能为空")
@Length(min=6,message="密码长度不能小于6位")
private String pass;
//...
}

其中, message="密码不能为空" ,为自定义返回的错误信息。
Hibernate Validator 基本上包含了常用的数据校验,包括校验属性是否为空、长度、大小、特定格式等,完
整的注解可以看下表:

注解应用目标运行时检查Hibernate
元数据影
@Length(min=, max=)属性
(String)
检查字符串长度是否符合范围列长度会
被设到最
大值
@Max(value=)属性(以
numeric 或
者 string 类
型来表示一
个数字)
检查值是否小于或等于最大值对列增加
一个检查
约束
@Min(value=)属性(以
numeric 或
者 string 类
型来表示一
个数字)
检查值是否大于或等于最小值对列增加
一个检查
约束
@NotNull属性检查值是否非空(not null)列不为空
@Past属性(date

calendar)
检查日期是否是过去时对列增加
一个检查
约束
@Future属性(date

calendar)
检查日期是否是将来时

GitChat

@Pattern(regex="regexp",
flag=)
属性
(string)
检查属性是否与给定匹配标志的正则表达式
相匹配
(见 java.util.regex.Pattern )
@Range(min=, max=)属性(以
numeric 或
者 string 类
型来表示一
个数字)
检查值是否在最小和最大值之间(包括临界
值)
对列增加
一个检查
约束
@Size(min=, max=)属性
(array,
collection,
map)
检查元素大小是否在最小和最大值之间(包
括临界值)
@AssertFalse属性检查方法的演算结果是否为 false(对以代
码方式而不是注解表示的约束很有用)
@AssertTrue属性检查方法的演算结果是否为 true(对以代码
方式而不是注解表示的约束很有用)
@Valid属性
(object)
对关联对象递归进行验证。如果对象是集合
或数组,就递归地验证其元素;如果对象是
Map,则递归验证其值元素
@Email属性
(String)
检查字符串是否符合有效的 email 地址规范

添加测试方法,对属性校验进行测试:

 

@Test
public void saveUsers() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/saveUser")
.param("name","")
.param("age","666")
.param("pass","test")
);
}

结果返回:

 

user:name=,age=666,pass=test
Max-年龄不能大于100岁
Length-密码长度不能小于6位
NotEmpty-姓名不能为空

结果显示均已经触发了校验规则,返回了错误信息,在实际使用过程中可以对错误信息进行包装,最后返回
到前端进行展示。


自定义 Filter

 

Filter 也称之为过滤器,可以在前端拦截所有用户的请求,可以认为是 Servlet 的一种加强版, Web 开发人员
通过 Filter 技术,对 Web 服务器管理的所有 Web 资源,例如 JSP、 Servlet、静态图片文件或静态 HTML 文
件等进行拦截,从而实现一些特殊的功能。例如,实现 URL 级别的权限访问控制、过滤敏感词汇、排除有
XSS 威胁的字符、记录请求日志等一些高级功能。


Spring Boot 内置了一些 Filter,比如,处理编码的 OrderedCharacterEncodingFilter 和请求转化的
HiddenHttpMethodFilter,也支持根据我们的需求来可以自定义 Filter。


自定义 Filter 有两种实现方式,第一种是使用 @WebFilter,第二种是使用 FilterRegistrationBean,经过实践
之后发现使用 @WebFilter 自定义的过滤器优先级顺序不能生效,因此推荐使用第二个方案,接下来我们详
细介绍第二种⽅方案。

自定义 Filter 两个步骤:

  • 实现 Filter 接口,实现其中的 doFilter() 方法;
  • 添加 @Configuration 注解,将自定义 Filter 加入过滤链。

新建 MyFilter 类,重写 doFilter() 方法:
 

public class MyFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest srequest, ServletResponse sresponse, Filte
rChain filterChain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) srequest;
System.out.println("this is MyFilter,url :"+request.getRequestURI());
filterChain.doFilter(srequest, sresponse);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}

将自定义 Filter 加入过滤链:
 

@Configuration
public class WebConfiguration {
@Bean
public FilterRegistrationBean testFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*");
registration.setName("MyFilter");
registration.setOrder(6);
return registration;
}
}

添加完后启动项目,在浏览器中输入地址: http://localhost:8080/getUsers,就会看到控制台打印如下信息:
 

this is MyFilter, url :/xxx

说明 MyFilter 已经对所有的 URL 进行了监控。当有多个过滤器时可以通过设置 Order 属性来决定它们的执
行顺序, Order 值越小优先级越高。我们复制上面的 MyFilter 重命名为 MyFilter2,在 WebConfiguration 中
添加 MyFilter2 的配置:
 

public FilterRegistrationBean test2FilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter2());
registration.addUrlPatterns("/*");
registration.setName("MyFilter2");
registration.setOrder(1);
return registration;
}

将 MyFilter 的 Order 属性设置为 6,将 MyFilter 2 的 Order 属性设置为 1,重新启动项目,在浏览器中输入
地址: http://localhost:8080/getUsers,就会看到控制台打印如下信息:
 

this is MyFilter2,url :/getUsers
this is MyFilter,url :/getUsers

可以发现过滤器 MyFilter 2 因为 Order 值设置得低,会优先被执行。


配置文件

 

在 Web 开发的过程中,经常需要自定义一些配置文件,如何使用呢?
在 application.properties 中配置:
 

neo.title=纯洁的微笑
neo.description=分享技术,品味生活

Spring Boot 也支持 Yaml 语法书写,比如上面的配置内容可以写到 application.yml 文件中,格式如下:
 

neo:
title: 纯洁的微笑
description: 分享技术,品味生活

在选择两种语法时, Yaml 语法更加简洁, properties 使用更加广泛,团队中保持一致即可。内容配置完成
后,需要自定义一个对象来接收配置内容。
 

注:同时存在 application.yml 和 application.properties,并且里面配置相同, application.properties 的配置会覆盖 application.yml

读取单个配置项

 

当需要从配置文件加载单个配置内容时,只需要使用 @Value 属性即可,新建 PropertiesTest 测试类进行测
试。

@RunWith(SpringRunner.class)
@SpringBootTest
public class PropertiesTest {
@Value("${neo.title}")
private String title;
@Test
public void testSingle() {
Assert.assertEquals(title,"纯洁的微笑");
}
}
  • @Value("${neo.title}") 会默认读取 application.properties 或者 application.yml 文件中的 neo.title 配置属性值,并赋值给 title。
  • Assert.assertEquals 是判断属性值是否和目标值一致。

执行测试用例例运行正常,说明属性值加载成功。
 

读取多个配置

 

通常在项目中使用配置文件时,往需要加载多个配置项,比如数据库连接参数等,通常会定义一个对象来
接收多个配置项,方便在项目中使用。比如定义一个 NeoProperties 对象,来接收所有以 neo 开头的配置内
容。
 

@Component
@ConfigurationProperties(prefix="neo")
public class NeoProperties {
private String title;
private String description;
//省略略getter settet⽅方法
}
  • @Component 的定义为实例,方便在 Spring Boot 项目中引用;
  • @ConfigurationProperties(prefix="neo"),表示以 neo 开头的属性会自动赋值到对象的属性中,比如,neo.title 会自动赋值到对象属性 title 中。

写单元测试进行验证,使用属性时直接将 NeoProperties 对象注入即可。
 

@Resource
private NeoProperties properties;
@Test
public void testMore() throws Exception {
System.out.println("title:"+properties.getTitle());
System.out.println("description:"+properties.getDescription());
}

运行 test 后输出结果:
 

title:纯洁的微笑
description:分享技术,品味生活

自定义配置文件

 

有时候需要自定义配置文件,以便和系统使用的 application.properties 文件区分开,避免混淆。 Spring Boot
对这种情况也有很好的支持。
在 resources 目录下创建一个 other.properties 文件,内容如下:
 

other.title=keep smile
other.blog=www.ityouknow.com

和上面一样定义一个对象来接收配置文件的内容:
 

@Component
@ConfigurationProperties(prefix="other")
@PropertySource("classpath:other.properties")
public class OtherProperties {
private String title;
private String blog;
//省略略getter settet⽅方法
}

对比上面读取多个配置示例,多了一个注解来指明配置文件地址:
@PropertySource("classpath:other.properties"),同样创建一个测试方法,检测是否正确加载了外部配置文
件。
 

@Test
public void testOther() throws Exception {
System.out.println("title:"+otherProperties.getTitle());
System.out.println("blog:"+otherProperties.getBlog());
}

运行 test 后输出结果:
 

title:my title
blog:www.ityouknow.com

说明自定义配置文件加载成功。


如果测试中出现中文乱码,可按照以下方法进行设置:


依次单击 File | Settings | Editor | File Encodings 命令,将 Properties Files (*.properties) 下的 Default
encoding for properties files 设置为 UTF-8,勾选 Transparent native-to-ascii conversion 复选框。

 

总结

 

Spring Boot 集成了参数校验、内嵌容器、 Restful、 JSON 等内容,这些技术在我们进行 Web 开发中必不可
少。 Spring Boot 对这些技术进行了包装,让我们在 Web 项目开发过程中非常容易地使用这些技术,降低了
开发 Web 项目的技术难度。
点击这⾥下载源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值