Administrator
发布于 2024-10-06 / 56 阅读
0

2、SpringBoot2:快速 Web 开发

本篇介绍 SpringBoot 对 Web 开发的支持。

从上篇文章可知,SpringBoot 对 Web 开发做了很大的优化,包括开发、测试、部署都做了支持。本篇内容介绍 SpirngBoot 对 Web 提供的其他便利。

kspring-boot-starter-web 是 SpringBoot 对 Web 开发的支持,主要包括 Restful、参数校验、使用 Tomcat 作为内嵌容器等功能,接下来一一介绍。

Web开发 

SpringBoot Web开发非常的简单,其中包括常用的json输出、filters、property、log等

json 接口开发

在 SpringBoot 体系中,天然对 Json 支持,在上篇文章中给大家做了简单的演示,这次来深入使用一番。

新建一个项目 spring-boot-web,添加上篇同样的组件依赖,导入项目到 Idea 中。在项目路径下新建 domain 包,在包下新建一个实体类 User,User 信息如下:

package com.example.webdemo.domain;

public class User {

private String name;

private int age;

private String pass;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getPass() {

return pass;

}

public void setPass(String pass) {

this.pass = pass;

}

}

在项目中新建 web 包,并在 web 包下新建一个类 WebController,在类中创建一个方法返回 User,如下:

package com.example.webdemo.web;

import com.example.domain.User;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class WebController {

@RequestMapping("/getUser")

public User getUser(){

User user = new User();

user.setName("欧阳德华");

user.setAge(26);

user.setPass("123456");

return user;

}

}

在 Test 包下新建 WebControllerTest 测试类,对 getUser() 方法进行测试。

package com.example.webdemo;

import com.example.web.WebController;

import org.junit.Before;

import org.junit.Test;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.web.servlet.MockMvc;

import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

@SpringBootTest

public class WebControllerTest {

private MockMvc mockMvc;

@Before

public void setUp() throws Exception{

mockMvc = MockMvcBuilders.standaloneSetup(new WebController()).build();

}

@Test

public void getUser()throws Exception{

mockMvc.perform(MockMvcRequestBuilders.get("/getUser")).andDo(print());

}

}

返回结果如下:


说明 Spring Boot 自动将 User 对象转成了 Json 进行返回。那么如果返回的是一个 list 呢,在 WebController 添加方法 getUsers():

@RequestMapping("/getUsers")

public List<User> getUsers(){

List<User> users = new ArrayList<User>();

User user1 = new User();

user1.setName("蔡文姬");

user1.setAge(8);

user1.setPass("111111");

users.add(user1);

User user2 = new User();

user2.setName("甄姬");

user2.setAge(22);

user2.setPass("222222");

users.add(user2);

return users;

}

在WebControllerTest添加相关测试方法如下:

@Test

public void getUsrs()throws Exception{

mockMvc.perform(MockMvcRequestBuilders.post("/getUsers")).andDo(print());

}

返回内容如下:


说明不管是对象还是集合或者对象嵌套,Spring Boot 均可以将其转化为 Json 字符串,特别适合我们给其他系统提供接口时使用。

请求传参

使用 Spirng Boot 可以轻松的对请求做一些限制,比如为了安全只允许 POST 请求的访问。只需要在方法上添加一个配置即可:

@RequestMapping(value = "/getUser", method = RequestMethod.POST)

public User getUser(){

User user = new User();

user.setName("欧阳德华");

user.setAge(26);

user.setPass("123456");

return user;

}

这时候再以 get 请求去访问,就会返回: Request method 'GET' not supported


Spring Web 层支持多种方法传参,上篇文章中传入一个属性 name,其直接使用对象接收也是支持的。

@RequestMapping(name="/getUser", method= RequestMethod.POST)

public String getUser(User user) {

...

}

这样的写法,只要是 User 的属性都会被自动填充到 user 对象中。还有另外一种传参的方式。

使用 Url 进行传参,这种形式的传参地址栏会更加美观一些。

@RequestMapping(value = "/getUserByName/{name}", method = RequestMethod.GET)

public User getUserByName(@PathVariable String name){

User user = new User();

user.setName(name);

user.setAge(20);

user.setPass("636281");

return user;

}

浏览器访问:http://localhost:8080/getUserByName/Jacky,返回


参数校验

参数校验在我们日常开发中非常常见,最基本的校验有判断属性是否为空、长度是否符合要求等,在传统的开发模式中需要写一堆的 if else 来处理这些逻辑,很繁琐,效率也低。使用 @Valid + BindingResult 就可以优雅地解决这些问题,接下来看看示例:

首先在 WebController 添加一个保存用户的方法 saveUser,参数为 User,现在需要对参数 User 做校验:

@NotEmpty(message="姓名不能为空!")

private String name;

@Max(value = 100,message = "年龄小于38岁!")

@Min(value = 16,message = "必须大于16岁!")

private int age;

@NotEmpty(message = "密码不能为空!")

@Length(min = 6,message = "密码长度不能小于6位!")

private String pass;

对不同的属性,按照规则添加了不同校验内容。

Spring Boot 的参数校验其实是依赖于 hibernate-validator 来进行。现在模拟对参数 User 进行参数校验,使用 @Valid + BindingResult,校验后如果有错误将错误打印出来,代码如下:

@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());

}

}

}

}

添加测试方法进行测试:

@Test

public void saveUser() throws Exception{

mockMvc.perform(MockMvcRequestBuilders.post("/saveUser")

.param("name","")

.param("age","12")

.param("pass","test")

).andDo(print());

}

结果返回:

定义 Filter

我们常常在项目中会使用 Filters 用于记录请求日志、排除有 XSS 威胁的字符、执行权限验证等等。Spring Boot 自动添加了 OrderedCharacterEncodingFilter 和 HiddenHttpMethodFilter,并且可以自定义 Filter。

自定义 Filter 两个步骤:

实现 Filter 接口,实现 Filter 方法 添加@Configuration 注解,将自定义 Filter 加入过滤链

新建 MyFilter 类,使用 doFilter() 方法:

@WebFilter(filterName = "MyFilter")

public class MyFilter implements Filter {

public void destroy() {

}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

HttpServletRequest request = (HttpServletRequest) req;

System.out.println("正在使用自定义过滤器,您访问的地址是:" + request.getRequestURI());

chain.doFilter(req, resp);

}

public void init(FilterConfig config) throws ServletException {

}

}

将自定义 Filter 加入过滤链:

@Configuration

public class WebConfiguration {

@Bean

public RemoteIpFilter remoteIpFilter(){

return new RemoteIpFilter();

}

@Bean

public FilterRegistrationBean testFilterRegistation(){

FilterRegistrationBean registrationBean = new FilterRegistrationBean();

registrationBean.setFilter(new MyFilter());

registrationBean.addUrlPatterns("/*");

registrationBean.addInitParameter("paramName","paramValue");

registrationBean.setName("MyFilter");

registrationBean.setOrder(1);

return registrationBean;

}

}

添加完后启动项目,访问任意的 Url,都会看到控制台打印如下信息:

说明 MyFilter 已经对所有的 Url 进行了监控,在实际使用的过程中,常常利用这个特性进行 session 验证,判断用户是否登录。

自定义 Property

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

配置在 application.properties 中

com.zat.mpaytitle="范总工"

com.zat.gametitle="渣渣辉"

自定义配置类:

@Component

public class ZatProperties {

@Value("${com.zat.mpaytitle}")

private String mpayTitle;

@Value("${com.zat.gametitle}")

private String gameTitle;

public String getMpayTitle() {

return mpayTitle;

}

public void setMpayTitle(String mpayTitle) {

this.mpayTitle = mpayTitle;

}

public String getGameTitle() {

return gameTitle;

}

public void setGameTitle(String gameTitle) {

this.gameTitle = gameTitle;

}

}

写单元测试进行验证:

@RunWith(SpringRunner.class)

@SpringBootTest

public class PropertiesTest {

@Resource

private ZatProperties zatProperties;

@Test

public void TestProperies()throws Exception{

System.out.println("Mpay的Title是:" + zatProperties.getMpayTitle());

System.out.println("Game的Title是:" + zatProperties.getGameTitle());

}

}

运行 PropertiesTest 后输出结果:

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

注意:.propertity里的属性文件名称只能全部用小写英文+"."号分隔,绝对不能用大写英文

配置完成后一定要重新新建一个application.properties