对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。
Sping Data 官网:https://spring.io/projects/spring-data
数据库相关的启动器 :可以参考官方文档:
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
添加依赖pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--添加了该依赖就要连接数据库不然会报错-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--thymeleaf模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
配置文件application.yaml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
banner.txt(springboot启动项目的图标)
命名为banner.txt文件,放在resources目录下
* * * *
* *
* * ___
* * | | |
* _________## * / \ | |
@\\\\\\\\\## * | |--o|===|-|
* @@@\\\\\\\\##\ \|/|/ |---| |d|
@@ @@\\\\\\\\\\\ \|\\|//|/ * / \ |w|
* @@@@@@@\\\\\\\\\\\ \|\|/|/ | U | |b|
@@@@@@@@@----------| \\|// | S |=| |
__ @@ @@@ @@__________| \|/ | A | | |
____|_@|_ @@@@@@@@@__________| \|/ |_______| |_|
=|__ _____ |= @@@@ .@@@__________| | |@| |@| | |
____0_____0__\|/__@@@@__@@@__________|_\|/__|___\|/__\|/___________|_|_
-- 北纬
实体类Employee.java
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Employee {
private Integer id;
private String name;
private String pwd;
private String email;
private int sex;// 0:女 1:男
private String departmentID;
private Department department;
private Date birth;
}
mapper接口EmployeeMapper.java
@Repository
@Mapper
public interface EmployeeMapper {
//查询所有员工
public List<Employee> selectAllEmp();
//添加员工信息
public void addEmp(Employee employee);
//删除员工信息
public void deleteEmp(int id);
//通过id查询员工信息
public Employee selectEmpById(int id);
//更新员工信息
public void updateEmp(Employee employee);
}
映射文件EmployeeMapper.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.example.helloword.mapper.EmployeeMapper"> <!-- 一般为数据表在持久层对应接口的完整路径 -->
<!-- 查询数据表中所有数据,这相标签的id值要与数据表对应接口中的查询方法的名称要一样 -->
<select id="selectAllEmp" resultType="com.example.helloword.entity.Employee">
select * from springboot.emp
</select>
<insert id="addEmp" parameterType="com.example.helloword.entity.Employee">
insert into emp(name,pwd,email,sex,departmentID,birth) values(#{name},#{pwd},#{email},#{sex},#{departmentID},#{birth})
</insert>
<delete id="deleteEmp" parameterType="int">
delete from emp where id=#{id}
</delete>
<select id="selectEmpById" resultType="com.example.helloword.entity.Employee">
select * from emp where id=#{id}
</select>
<update id="updateEmp" parameterType="com.example.helloword.entity.Employee">
update emp set
name=#{name},pwd=#{pwd},email=#{email},sex=#{sex},birth=#{birth} where id=#{id}
</update>
</mapper>
业务层接口EmployeeService.java
public interface EmpService {
//查询所有员工
public List<Employee> selectAllEmp();
//添加员工信息
public void addEmp(Employee employee);
//删除员工信息
public void deleteEmp(int id);
//通过id查询员工信息
public Employee selectEmpById(int id);
//更新员工信息
public void updateEmp(Employee employee);
}
业务层实现类EmployeeServiceImpl.java
@Service("empService ")
public class EmpServiceImpl implements EmpService {
@Autowired
EmployeeMapper employeeMapper;
@Override
public List<Employee> selectAllEmp() {
return employeeMapper.selectAllEmp();
}
@Override
public void addEmp(Employee employee) {
employeeMapper.addEmp(employee);
}
@Override
public void deleteEmp(int id) {
employeeMapper.deleteEmp(id);
}
@Override
public Employee selectEmpById(int id) {
return employeeMapper.selectEmpById(id);
}
@Override
public void updateEmp(Employee employee) {
employeeMapper.updateEmp(employee);
}
}
控制层EmployeeController.java
@Controller
@ComponentScan(basePackages = {"com.example.helloword.config"})
public class EmployeeController {
@Autowired
EmployeeMapper employeeMapper;
@Autowired
DepartmentSerive departmentSerive;
@Autowired
EmpService empService;
//查询所有的员工信息
@GetMapping("/emps")
public String queryEmp(Model model){
List<Employee> empList = employeeMapper.selectAllEmp();
model.addAttribute("emps",empList);
for(Employee employee:empList){
System.out.println("遍历employee:"+employee);
System.out.println("遍历employee.getDepartmentID():===>"+employee.getBirth());
}
return "emp/list";
}
//查询部门号
@GetMapping("/emp")
public String selectDepartment(Model model){
List<Department> departments = departmentSerive.selectAllDepartment();
for(Department department:departments){
System.out.println("遍历department:====="+department);
}
model.addAttribute("departments",departments);
return "emp/add";
}
//添加员工信息
@PostMapping("/emp")
public String addEmp(HttpServletRequest request,Employee employee){
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
String birth = request.getParameter("birth");
String departmentid = request.getParameter("department.id");
System.out.println("密码:"+pwd+";用户名:"+name+";出生日期:"+birth+";departmentid:"+departmentid);
/*empService.addEmp(employee);*/
employeeMapper.addEmp(employee);
System.out.println("添加数据成功!");
return "redirect:/emps";
}
//删除员工信息
@GetMapping("/deleteEmp/{id}")
public String deleteEmp(@PathVariable("id") int id){
empService.deleteEmp(id);
System.out.println("删除员工数据成功!");
return "redirect:/emps";
}
//修改员工页面
@GetMapping("/updateEmp/{id}")
public String updateEmp(@PathVariable("id")int id,Model model){
Employee employee = employeeMapper.selectEmpById(id);
System.out.println("Did:"+employee.getDepartmentID());
model.addAttribute("employee",employee);
return "emp/update";
}
@PostMapping("/updateEmp")
public String updateEmp(Employee employee){
empService.updateEmp(employee);
return "redirect:/emps";
}
}
添加了thymeleaf模板引擎并启动IndexController控制器就可以跳转到index.html页面了
登录拦截配置类MyMvcConfig.java
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
/**
* 配置服务器启动自动跳转到index.html页面中
* @param registry
*/
//配置服务器启动自动跳转到index.html页面中
@Override
public void addViewControllers(ViewControllerRegistry registry){
/*配置一个服务器启动自动跳转到首页登录页面*/
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
/*setViewName("dashboard")对应dashboard.html,相当于起一个别名为main.html*/
registry.addViewController("/main.html").setViewName("dashboard");
}
//自定义的国际化组件
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
/*配置拦截器请求Bean*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**");
}
}
LoginHandlerInterceptor.java
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功后,应该有一个用户的session
Object loginUser = request.getSession().getAttribute("loginUser");
if(loginUser==null){
//没有登录,跳转到登录页面
request.setAttribute("msg","没有权限,请先登录!");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}
else {
return true;
}
}
}
Thymeleaf模板引擎的使用
Thymeleaf 官网:https://www.thymeleaf.org/
Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf
Spring官方文档:找到我们对应的版本
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
thymeleaf依赖导入
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Thymeleaf 语法学习
要学习语法,还是参考官网文档最为准确,我们找到对应的版本看一下;
Thymeleaf 官网:https://www.thymeleaf.org/ , 简单看一下官网!我们去下载Thymeleaf的官方文档!
- 我们做个最简单的练习 :我们需要查出一些数据,在页面中展示
@RequestMapping("/t1")
public String test1(Model model){
//存入数据
model.addAttribute("msg","Hello,Thymeleaf");
//classpath:/templates/test.html
return "test";
}
- 我们要使用thymeleaf,需要在html文件中导入命名空间的约束,方便提示。
- 我们可以去官方文档的#3中看一下命名空间拿来过来:
xmlns:th="http://www.thymeleaf.org"
- 我们去编写下前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>狂神说</title>
</head>
<body>
<h1>测试页面</h1>
<!--th:text就是将div中的内容设置为它指定的值,和之前学习的Vue一样-->
<div th:text="${msg}"></div>
</body>
</html>
- 我们编写一个Controller,放一些数据
@RequestMapping("/t2")
public String test2(Map<String,Object> map){
//存入数据
map.put("msg","<h1>Hello</h1>");
map.put("users", Arrays.asList("qinjiang","kuangshen"));
//classpath:/templates/test.html
return "test";
}
- 测试页面取出数据
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>狂神说</title>
</head>
<body>
<h1>测试页面</h1>
<div th:text="${msg}"></div>
<!--不转义-->
<div th:utext="${msg}"></div>
<!--遍历数据-->
<!--th:each每次遍历都会生成当前这个标签:官网#9-->
<h4 th:each="user :${users}" th:text="${user}"></h4>
<h4>
<!--行内写法:官网#12-->
<span th:each="user:${users}">[[${user}]]</span>
</h4>
</body>
</html>
拓展SpringMVC
修改SpringBoot的默认配置
这么多的自动配置,原理都是一样的,通过这个WebMVC的自动配置原理分析,我们要学会一种学习方式,通过源码探究,得出结论
SpringBoot的底层,大量用到了这些设计细节思想,所以,没事需要多阅读源码!得出结论;
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;
如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!