文章目录
一、SpringBoot详解
1、初始SpringBoot
SpringBoot它是一个javaweb的开发框架
SpringBoot以约定大于配置的核心思想,默认帮助我们进行可很多设置,多数SpringBoot应用只需要很少的Spring配置。它集成了大量的第三方库配置
2、第一个SpringBoot程序
- 可以在https://start.spring.io/官网去创建项目
- 在idea中直接创建项目(推荐)
- 新建工程Spring Initializr.
- Spring Boot 2.7.7(Spring Boot 3.0 使用 Java 17作为最低版本)
- SDK版本1.8
- java版本8
- 项目主程序XXXApplication.java的同级目录创建controller
更改项目端口号:
application.properties配置文件中更改server.port=8081
更改banner:
在resources目录下,创建banner.txt,内容为需要显示的banner
3、自动装配原理
3.1 pom.xml
- spring-boot-dependencies核心依赖在父工程中
- 我们在引入springboot依赖时,不需要指定版本,因为父工程的pom中配置了相应版本号
3.2 启动器
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
-
启动器就是springboot的启动场景
-
比如spring-boot-starter-web,帮我们自动导入web环境所有依赖
-
springboot会将所有的功能场景,都变成一个个启动器
-
启动器https://docs.spring.io/spring-boot/docs/2.7.7/reference/html/using.html#using
3.3 主程序
//该注解为必须的
@SpringBootApplication
public class SpringBoot01Application {
public static void main(String[] args) {
//使用该语句启动springboot项目
SpringApplication.run(SpringBoot01Application.class, args);
}
}
注解:
@SpringBootApplication
@SpringBootConfiguration//springboot的配置
@Configuration//spring配置类
@Component//说明是一个组件
@EnableAutoConfiguration//自动配置
@AutoConfigurationPackage//自动配置包
@Import({Registrar.class})//导入,自动配置包这个类的内部类Registrar
@Import({AutoConfigurationImportSelector.class})//导入,自动配置导入选择器类
自动配置的核心配置文件:
spring-boot-autoconfigure-2.7.7的jar包下META-INF/spring.factories文件(2.7版本中弃用)
SpringApplication做了四个事情:
- 推断应用的类型是普通项目还是web项目
- 查找并加载所有可用初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行主类
4、Yaml讲解
springboot的全局配置文件
- application.properties
- key=value
- application.yaml
- key:空格value
server:
port: 8080
#普通的key-value
name: lisa
#对象
student:
name: lisa
age: 3
#对象行内写法
student1: {name: lisa,age: 3}
#数组
pets:
- cat
- dog
- pig
#数组行内写法
pets1: [cat,dog,pig]
yaml可以给实体类赋值
Dog.java
@Component
public class Dog {
private String name;
private int age;
}
Person.java
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
application.yaml
person:
name: lisa${random.uuid}
age: 32
happy: false
birth: 2013/2/3
maps: {k1: v1,k2: v2}
lists:
- code
- music
- read
dog:
name: 阿旺
age: 3
测试类
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
5、配置文件位置
配置文件参考配置地址:https://docs.spring.io/spring-boot/docs/2.7.7/reference/html/application-properties.html#appendix.application-properties
配置文件放置的位置(按优先级排列):
- file:./config/(项目根目录下的config文件夹下)
- file:./(项目根目录下)
- classpath:/config/(resources目录下的config文件夹下)
- classpath:/(resources目录下)
主要要关注XXXAutoConfiguration和XXXProperties,两种文件,来参考去在配置文件中配置
6、SpringBoot Web开发
6.1 静态资源导入
源码:
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//如果有自定义配置,默认路径则失效
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
导入方式一(不推荐):
使用webjars
classpath:/META-INF/resources/
什么是webjars:意思就是以maven的方式引入web的jar包,访问时地址/webjars/
映射为/META-INF/resources/webjars/
导入方式二:(以下目录放置静态文件1.js,直接在http://localhost:8080/1.js可访问)
classpath为项目根目录下的resources
- classpath:/resources/
- classpath:/static/
- classpath:/public/
6.2 首页和图标定制
在静态资源目录下的index.html会被当做首页
在templates下的页面,只能通过controller访问
-
使用templates下的文件时,需要使用thymeleaf依赖,不然报错
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
图标放在static文件夹下
需要图标的网页引入<link rel="icon" href="favicon.ico">
6.3 thymeleaf模板引擎
文档:https://www.thymeleaf.org/documentation.html
使用前需要导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
其次在html中需要导入命名空间xmlns:th="http://www.thymeleaf.org"
thymeleaf语法
- 简单表达式:
- Variable Expressions:
${...}
- Selection Variable Expressions:
*{...}
- Message Expressions:
#{...}
- Link URL Expressions:
@{...}
- Fragment Expressions:
~{...}
- Variable Expressions:
- Literals
- Text literals:
'one text'
,'Another one!'
,… - Number literals:
0
,34
,3.0
,12.3
,… - Boolean literals:
true
,false
- Null literal:
null
- Literal tokens:
one
,sometext
,main
,…
- Text literals:
- Text operations:
- String concatenation:
+
- Literal substitutions:
|The name is ${name}|
- String concatenation:
- Arithmetic operations:
- Binary operators:
+
,-
,*
,/
,%
- Minus sign (unary operator):
-
- Binary operators:
- Boolean operations:
- Binary operators:
and
,or
- Boolean negation (unary operator):
!
,not
- Binary operators:
- Comparisons and equality:
- Comparators:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - Equality operators:
==
,!=
(eq
,ne
)
- Comparators:
- Conditional operators:
- If-then:
(if) ? (then)
- If-then-else:
(if) ? (then) : (else)
- Default:
(value) ?: (defaultvalue)
- If-then:
<p>[[${msg}]]</p>
<p th:text="${msg}"></p>
<p th:utext="${msg}"></p>
<h1 th:each="item:${list}" th:text="${item}"></h1>
代码复用
<div th:fragment="sidebar">一堆代码</div>定义侧边栏,该代码所在文件1.html
<div th:insert="~{1.html::sidebar}"></div>插入侧边栏,该代码所在文件2.html
6.4 扩展MVC配置
- 编写一个@Configuration注解的类
- 该类实现WebMvcConfigurer接口
- 并且不能标注@EnableWebMvc注解
- 一般配置类写在config包下
package com.daban.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 {
//视图跳转,通过kk请求,跳转到test页面
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/kk").setViewName("test");
}
}
7、员工管理系统
7.1 创建页面,模拟数据库数据
-
pojo.Department.java
-
package com.daban.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Department { private Integer id; private String departmentName; }
-
-
pojo.Employee.java
-
package com.daban.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @NoArgsConstructor public class Employee { private Integer id; private String lastName; private String email; private Integer gender; private Department department; private Date birth; public Employee(Integer id, String lastName, String email, Integer gender, Department department) { this.id = id; this.lastName = lastName; this.email = email; this.gender = gender; this.department = department; this.birth = new Date(); } }
-
-
dao.DepartmentDao.java
-
package com.daban.dao; import com.daban.pojo.Department; import org.springframework.stereotype.Repository; import java.util.Collection; import java.util.HashMap; import java.util.Map; @Repository public class DepartmentDao { private static Map<Integer, Department> department = null; static { department = new HashMap<Integer, Department>(); department.put(101,new Department(101,"教学部")); department.put(102,new Department(102,"市场部")); department.put(103,new Department(103,"教研部")); department.put(104,new Department(104,"运营部")); department.put(105,new Department(105,"后勤部")); } //获得所有部门信息 public Collection<Department> getDepartment(){ return department.values(); } //通过id获取部门 public Department getDepartmentById(Integer id){ return department.get(id); } }
-
-
dao.EmployeeDao.java
-
package com.daban.dao; import com.daban.pojo.Department; import com.daban.pojo.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.util.Collection; import java.util.HashMap; import java.util.Map; @Repository public class EmployeeDao { private static Map<Integer, Employee> employees = null; @Autowired private DepartmentDao departmentDao; static { employees = new HashMap<Integer, Employee>(); employees.put(101,new Employee(1001,"AA","12345@qq.com",1,new Department(101,"教学部"))); employees.put(102,new Employee(1002,"BB","12345@qq.com",0,new Department(102,"市场部"))); employees.put(103,new Employee(1003,"CC","12345@qq.com",0,new Department(103,"教研部"))); employees.put(104,new Employee(1004,"DD","12345@qq.com",1,new Department(104,"运营部"))); employees.put(105,new Employee(1005,"EE","12345@qq.com",0,new Department(105,"后勤部"))); } //主键自增 private static Integer initId = 1006; //增加一个员工 public void addEmployee(Employee employee){ if(employee.getId()==null){ employee.setId(initId++); } employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId())); employees.put(employee.getId(),employee); } //查询全部员工 public Collection<Employee> getAll(){ return employees.values(); } //通过id查询员工 public Employee getEmployeeById(Integer id){ return employees.get(id); } //删除员工 public void delete(Integer id){ employees.remove(id); } }
-
-
页面文件
- https://github.com/twbs/bootstrap/releases/download/v5.3.0-alpha1/bootstrap-5.3.0-alpha1-examples.zip
- 下载后解压文件中的dashboard和sign-in
7.2 首页
首页使用配置类来做
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
}
}
7.3 页面国际化(多语言)
-
创建各语言文件
-
resources文件夹下创建i18n文件夹,里面创建三个文件
-
#全局配置文件application.properties中配置国际化参数 spring.messages.basename=i18n.login
-
#创建如下三个文件,可以在idea的Resource Bundle中可以同步编辑三个文件 #login.properties login.signin=登陆 login.password=密码 login.remember=记住我 login.tip=请登陆 login.username=用户名 #login_zh_CN.properties login.signin=sign in login.password=password login.remember=Remember me login.tip=please sign in login.username=username #login_en_US.properties login.signin=登陆 login.password=密码 login.remember=记住我 login.tip=请登陆 login.username=用户名
-
-
html文件绑定
-
html文件中使用#{}来绑定相应字段
-
<h1 class="h3 mb-3 fw-normal" th:text="#{login.tip}">Please sign in</h1> <label for="floatingInput" th:text="#{login.username}">Username</label> <label for="floatingPassword" th:text="#{login.password}">Password</label> <button class="w-100 btn btn-lg btn-primary" type="submit" th:text="#{login.signin}">Sign in</button> <span th:text="#{login.remember}">Remember me</span>
-
-
设置中英文切换按钮
-
<a class="btn btn-sm" th:href="@{/index(l='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/index(l='en_US')}">English</a>
-
-
创建一个类MyLocaleResolver
-
package com.daban.config; import org.springframework.web.servlet.LocaleResolver; import org.thymeleaf.util.StringUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { String language = request.getParameter("l"); Locale locale = Locale.getDefault(); if(!StringUtils.isEmpty(language)){ String[] s = language.split("_"); locale = new Locale(s[0], s[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } }
-
-
在MyMvcConfig类中注册
-
MyMvcConfig类参见《6.4扩展MVC配置》
-
@Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); }
-
7.4 登陆功能
登陆controller
package com.daban.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.util.StringUtils;
@Controller
public class LoginController {
@RequestMapping("/login")
public String login(String username, String password, Model model){
System.out.println(username+password);
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
model.addAttribute("msg","用户名或密码不能为空");
return "index";
}
else if (username.equals("admin") && password.equals("123")){
session.setAttribute("loginUser",username);
return "redirect:main.html";
}else {
model.addAttribute("msg","输入的用户名或密码有误");
return "index";
}
}
}
地址映射
package com.daban.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
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("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
//自定义的国际化就生效
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
7.5 登陆拦截器
写一个拦截器类
package com.daban.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor 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").forward(request,response);
return false;
}else {
return true;
}
}
}
MyMvcConfig类里增加
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
//过滤使不经过拦截器
.excludePathPatterns("/index","/","/login","/css/**","/js/**","/img/**");
}
7.6 展示员工列表
1、提取公共页面
-
代码复用 <div th:fragment="sidebar">一堆代码</div>定义侧边栏,该代码所在文件1.html <div th:insert="~{1.html::sidebar}"></div>插入侧边栏,该代码所在文件2.html 或<div th:replace="~{1.html::sidebar}"></div>插入侧边栏,该代码所在文件2.html
2、如果要传递参数
使用()即可<div th:replace="~{1.html::sidebar(active="list.html")}"></div>
3、使用传递的参数
<a th:class="${active=='list.html'?'nav-link active': 'nav-link'}"/>
意思就是如果active==list.html,class属性为nav-link active,否则为nav-link
4、列表循环展示
<tr th:each="item:${emps}">
<td th:text="${item.getId()}"></td>
<td th:text="${item.getLastName()}"></td>
<td th:text="${item.getEmail()}"></td>
<td th:text="${item.getGender()==0?'女':'男'}"></td>
<td th:text="${item.getDepartment().getDepartmentName()}"></td>
<td th:text="${#dates.format(item.getBirth(),'yyyy-MM-dd')}"></td>
<td>
<a class="btn btn-sm btn-primary" th:href="">编辑</a>
<a class="btn btn-sm btn-danger" th:href="">删除</a>
</td>
</tr>
7.7 增加员工
要点:
-
在全局配置文件中
spring.mvc.format.date=yyyy/MM/dd
,设置时间格式 -
表单字段是一个对象,只需要把id传递
-
<div class="form-group"> <label>部门</label> <select name="department.id" class="form-control"> <option th:each="item:${departments}" th:text="${item.getDepartmentName()}" th:value="${item.getId()}"> </option> </select> </div>
-
7.8 修改员工信息
要点:
-
链接传递参数
-
<a class="btn btn-sm btn-primary" th:href="@{/toUpdate(id=${item.getId()})}">编辑</a>
-
-
单选框的数据回显
-
<input type="radio" th:checked="${emps.getGender()==0}" class="form-check-input" name="gender" value="0">
-
-
下拉框数据回显
-
<select name="department.id" class="form-control"> <option th:selected="${item.getId() ==emps.getDepartment().getId()}" th:each="item:${departments}" th:text="${item.getDepartmentName()}" th:value="${item.getId()}"> </option> </select>
-
-
表单隐藏域的提交
-
<input type="hidden" th:value="${emps.getId()}" name="id" class="form-control">
-
7.9 删除员工及404
删除:
@RequestMapping("/delete")
public String delete(Integer id){
//Employee employee = employeeDao.getEmployeeById(id);
employeeDao.delete(id);
return "redirect:/emps";
}
404:
404功能就是在templates目录下创建一个error文件夹,里面放置404.html就可以,其他500了类似
注销:
@RequestMapping("/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:index";
}