yaml 语法
# application.yml
people:
name: _Nice
age: 10
happy: true
birth: 2020/5/6
maps: {k1: v1,k2: v2}
lists:
- code
- music
- girl
dog:
name: 旺财
age: 3
// yml文件属性值注入
package com.kuang.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "people")
public class People {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
public People() {
}
public People(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.lists = lists;
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
使用 @ConfigurationProperties 报红,但实际上可以正常运行。要想解决可以导入如下依赖(注意要有 @Component):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
也可以通过外部 properties 文件和 SPEL 进行属性注入,但我这种方式注入中文乱码就很迷惑,如果不使用 SPEL 导入值就不会乱码,留坑。但大多数情况都是使用 yml 配置,这个了解即可。
name=哈哈哈
age=8
package com.kuang.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@PropertySource("classpath:people.properties")
public class People {
@Value("${name}")
// 使用 @Value("哈哈哈") 就不会乱码
private String name;
@Value("${age}")
private Integer age;
private Boolean happy;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
public People() {
}
public People(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.lists = lists;
this.dog = dog;
}
JSR303校验
处理一段业务逻辑,首先要确保数据输入的正确性,所以需要先对数据进行检查,保证数据在语义上的正确性,再根据数据进行下一步的处理。前端可以通过 js 程序校验数据是否合法,后端同样也需要进行校验。
JSR 303 使用 Bean Validation,即在 Bean 上添加相应的注解,去实现数据校验。这样在执行业务方法前,都会根据注解对数据进行校验,从而减少自定义的校验逻辑,减少代码冗余。下面是其中一部分注解。更高级用法参考其他相关博客。
@Null 被指定的注解元素必须为 Null
@NotNull 任意类型,不能为 Null,但可以为空,比如空数组、空字符串。
@NotBlank 针对字符串,不能为 Null,且去除前后空格后的字符串长度要大于 0。
@NotEmpty 针对字符串、集合、数组,不能为 Null,且长度要大于 0。
@Size 针对字符串、集合、数组,判断长度是否在给定范围内。
@Length 针对字符串,判断长度是否在给定范围内。
@AssertTrue 针对布尔值,用来判断布尔值是否为 true
@AssertFalse 针对布尔值,用来判断布尔值是否为 false
@Max(value) 针对字符串、数值,用来判断是否小于等于某个指定值
@Min(value) 针对字符串、数值,用来判断是否大于等于某个指定值
配置文件位置
配置文件可以放在以上四个位置,注意目录名和文件名是固定的不能改。不同版本的 SpringBoot 对于配置文件位置的优先级规定不同,可以自己测一下。
静态文件
放在 public/resources/static 目录下的静态文件可以被访问到,SpringBoot 会去找这三个目录下的文件,如果不同目录下有同名文件,优先级自测。如 http://localhost:8080/3.js 就可以访问到 3.js 的内容
页面
.html 也可以放在 public/resources/static 目录下直接访问。如果将 .html 放在 templates 目录下,则不能直接访问,需要通过 controller 层访问,跟 springMVC 一样,下面是个例子:
package com.horizon.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class indexController {
@RequestMapping("/test")
public String test() {
return "test";
}
}
然后访问 http://localhost:8080/test 即可跳转到对应的 html 页面,其中在 thymeleafProperties 类中可以看到 thtmeleaf 的实现,其中就有定义路径拼接如下:
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
index.html 除外,可以直接用 localhost:8080 访问,但不能用 localhost:8080/index.html 直接访问
拦截器
return true 代表放行,在配置类里配置拦截哪些请求,见下面扩展 SpringMVC。如果登录成功则在登录页面将登录信息存在 session 里,拦截器检查 session 是否有登录信息来判断是否放行
package com.horizon.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object loginUser = request.getSession().getAttribute("loginUser");
if(loginUser == null) {
request.setAttribute("msg", "请先登录");
request.getRequestDispatcher("/index.html").forward(request, response);
return false;
}
return true;
}
}
扩展SpringMVC
新建一个配置类,加上 @Configuration 注解并实现 WebMvcConfigurer 接口,然后重写里面方法即可实现扩展。注意不能加上 @EnableWebMvc 注解。下面的一个例子是通过 diy 视图控制来实现直接访问 localhost:8080/index.html来访问 templates 目录下的 index.html 页面
package com.horizon.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index.html").setViewName("index");
}
// 配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(
new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html", "/", "/user/login");
}
}
thymeleaf模板引擎
首先导入配置
<html lang="en" xmlns:th="http://www.thymeleaf.org">
一些常用方法
<!--表单-->
<form th:action="@{/emp}" th:method="post"></form>
<!--循环,th:text为填充文本-->
<select name="department.id">
<option th:each="dept:${dps}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"> </option>
</select>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td>
<a th:href="@{/update(id=${emp.getId()})}">编辑</a>
<a th:href="@{/delete(id=${emp.getId()})}">删除</a>
</td>
</tr>
<!--是否选中(默认值)-->
<input th:checked="${emp.getGender()==1}" type="radio" name="gender" value="1"/>
<label>男</label>
<input th:checked="${emp.getGender()==0}" type="radio" name="gender" value="0"/>
<label>女</label>
<select name="department.id">
<option th:selected="${emp.getDepartment().getId()==dept.getId()}" th:each="dept:${dps}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
其他用法见官方文档
整合JDBC
在 application.yml 文件里加入数据库配置
spring:
datasource:
username: root
password: 123
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
然后直接使用 JDBCTemplate 即可,注意要自动装配
package com.kuang.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
@GetMapping("/query")
public List<Map<String, Object>> query() {
String sql = "select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
@GetMapping("/update/{id}")
public void update(@PathVariable("id") int id) {
String sql = "update user set name=?,pwd=? where id=?";
Object[] objects = new Object[3];
objects[0] = "哈哈哈";
objects[1] = "541258";
objects[2] = id;
jdbcTemplate.update(sql, objects);
}
}
整合Mybatis
导入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
在 application.properties 或 application.yml 中配置数据库
# application.properties
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# application.yml
spring:
datasource:
username: root
password: 123
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
定义接口,加上 @Mapper 注解
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserMapper {
List<User> queryUserList();
}
配置 xml 文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
<select id="queryUserList" resultType="user">
select * from user;
</select>
</mapper>
使用
package com.kuang.controller;
import com.kuang.mapper.UserMapper;
import com.kuang.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/query")
public List<User> queryUserList() {
return userMapper.queryUserList();
}
}
目录结构
可能的问题
pom.xml 中 maven 插件爆红,添加一个版本号刷新即可,版本号与 parent 版本号一样
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
</plugins>