狂神说SpringBoot
狂神说SpringBoot
P1 这阶段该如何学习
学路线思维导图介绍(重复看)
P2 什么是SpringBoot
SpringBoot介绍(重复看)
P3 什么是微服务架构
Spring官网介绍介绍(重复看)
P4 第一个SpringBoot程序
官网下载SpringBoot项目到idea运行
SpringBoot官网: https://spring.io/projects/spring-boot
点击 Quickstart Your Project 跳到下面的Spring的初始化界面网页
https://start.spring.io/
直接idea创建SpringBoot并运行
启动器删掉注解会报错使用不了
打包成jar到控制台运行
P5 IDEA快速创建及彩蛋
提到启动器
彩蛋是控制台输出佛祖
P6 Springboot自动装配原理
带看Springboot源码,建议回看《注解和反射》视频(重复看)
P7 了解下主启动类怎么运行
Springboot运行的步骤流程图(重复看)
P8 yaml语法讲解
properties属性文件的简便版
P9 给属性赋值的几种方式
yaml给实体类赋值
P10 JSR303校验
数据校验
P11 多环境配置及配置文件位置
可配dev和test环境
配置文件位置优先级:./config > ./ > ./src/main/resources/config > .src/main/resources
P12 自动配置原理再理解
源码阅读
P13 web开发探究
P14 静态资源导入探究
new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
改路径:#spring.mvc.static-path-pattern=/hello/,classpath:/kuang/
P15 首页和图标定制
在templates目录下的所有页面。只能通过controller来跳转
这个需要模板引擎的支持! thymeleaf
图标:命名favicon.ico文件放到资源目录下就可以了
P16 thymeleaf模板引擎
导入依赖:spring-boot-starter-thymeleaf
thymeleaf在线帮助文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#using-texts
<html xmlns:th="http://www.thymeleaf.org">
P17 Thymeleaf语法
导入代码片段:th:insert
被导入代码片段:th:replace
普通文本值:th:text
转义Html标签:th:utext
P18 MVC配置原理
翻原码
P19 扩展SpringMVc
//如果你想diy一些定制化的功能,只要写这个组件,然后将它交给springboot,springboot就会帮我们自动装配
//扩展 springmvc
@Configuration
@EnableWebMvc//这是导入了一个类:DelegatingWebMvcConfiguration:从容器中获取所有的webmvcconfig; 加了这个注解自动配置就会失效
public class MyMvcConfig implements WebMvcConfigurer {
//如果我们要扩展springmvc,官方建议我们这样去做
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/kuang").setViewName("index.html");
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry)
{
WebMvcConfigurer.super.addInterceptors(registry);
}
// @Bean //自动装配
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//public interface ViewResolver 实现了视图解析器接口的类,我们可以把她看做视图解析器
//自定义了一个自己的视图解析器MyViewResolver
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String s, Locale locale) throws Exception {
return null;
}
}
}
P20 员工管理系统:准备工作
创建pojo
模拟dao层数据
P21 员工管理系统:首页实现
模板资源地址:https://getbootstrap.com/docs/4.0/examples/
<link th:href="@{./css/bootstrap.min.css}" rel="stylesheet">
P22 员工管理系统:国际化
- 文件夹名字:internationalization - i18n
- 文件名字:login.properties
- 文件名字:login_zh_CN.properties
- 文件名字:login_en_US.properties
- 配置属性文件(application.properties): spring.messages.basename=i18n.login
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获得请求中语言的参数
String language = httpServletRequest.getParameter("l");
Locale locale = Locale.getDefault();//如果没有就使用默认的
//如果请求的链接携带了国际化的参数
if(!StringUtils.isEmpty(language)){
//zh_CH
String[] split = language.split("_");
//国家,地区
locale = new Locale(split[0],split[1]);
}
return locale;
}
}
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
P23 员工管理系统:登录功能实现
@Controller
public class LoginController {
@RequestMapping("user/login")
public String login(@RequestParam("username") String username, @RequestParam("password")String password, Model model){
//具体业务:
if(!StringUtils.isEmpty(username)&& "123456".equals(password)){
return "redirect:/main.html";
}else{
//告诉用户,你登录失败了
model.addAttribute("msg","用户名或密码错误");
return "index";
}
}
}
<body class="text-center">
<form class="form-signin" th:action="@{/user/login}">
<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!--如果msg为空则不显示消息-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label for="inputEmail" class="sr-only" th:text="#{login.username}">Username</label>
<input name="username" type="text" id="inputEmail" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<label for="inputPassword" class="sr-only" th:text="#{login.password}">Password</label>
<input name="password" type="password" id="inputPassword" class="form-control" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" th:text="#{login.remember}"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
</form>
</body>
p24 员工管理系统:登录拦截器
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;
}else{
return true;
}
}
}
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index.html","/","/user/login","/js/**","/css/**","/img/**");
}
}
p25 员工管理系统:展示员工列表
创建commons/commons.html文件
<!--顶部导航栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0"th:fragment="topbar">
<!--侧边栏-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
<!--如果是main页面就高亮-->
<a th:class="${active=='main.html'?'nav-link active':'nav-link'}" t th:href="@{/emps}">
<!--如果是list页面就高亮-->
<a th:class="${active=='list.html'?'nav-link active':'nav-link'}" t th:href="@{/emps}">
<!--顶部导航栏-->
<div th:replace="~{commons/commons::topbar}"></div>
<!--main页面侧边栏-->
<div th:replace="~{commons/commons::sidebar(active='main.html')}"></div>
<!--list页面侧边栏-->
<div th:replace="~{commons/commons::sidebar(active='list.html')}"></div>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td>[[${emp.getLastName()}]]</td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()==0 ?'男':'女'}"></td>
<td th:text="${emp.getDepartment().getDepartmentName()}"></td>
<td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
<td>
<button class="btn btn-sm btn-primary">编辑</button>
<button class="btn btn-sm btn-danger">删除</button>
</td>
</tr>
</tbody>
p26 员工管理系统:增加员工实现
<form th:action="@{/emp}" method="post">
<div class="form-group">
<label>LastName</label>
<input type="text" class="form-control" name="lastName" placeholder="kuangshen">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" name="email" placeholder="24736743@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select class="form-control" name="department.id">
<option th:each="dept:${departments}"th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input type="text" class="form-control" name="birth" placeholder="2022/3/2">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
p27 员工管理系统:修改员工信息
//员工的修改页面
@GetMapping ("/emp/{id}")
public String toUpdateEmp(@PathVariable("id") Integer id,Model model){
//查出原来的数据
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employee);
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/update";
}
@PostMapping("/updateEmp")
public String updateEmp(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
<form th:action="@{/updateEmp}" method="post">
<input type="hidden" th:value="${emp.getId()}" name="id">
<div class="form-group">
<label>LastName</label>
<input th:value="${emp.getLastName()}" type="text" class="form-control" name="lastName" placeholder="kuangshen">
</div>
<div class="form-group">
<label>Email</label>
<input th:value="${emp.getEmail()}" type="email" class="form-control" name="email" placeholder="24736743@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input th:checked="${emp.getGender()==1}" class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input th:checked="${emp.getGender()==0}" class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select class="form-control" name="department.id">
<option th:selected="${dept.getId()==emp.getDepartment().getId()}" th:each="dept:${departments}"th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}" type="text" class="form-control" name="birth" placeholder="2022/3/2">
</div>
<button type="submit" class="btn btn-primary">修改</button>
</form>
p28 员工管理系统:删除及404处理
删除
@GetMapping ("/delemp/{id}")
public String deleteEmp(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}
<a class="btn btn-sm btn-danger" th:href="@{|/delemp/${emp.getId()}|}">删除</a>
直接创建/error/404.html,报错就会自动跳到该页面
p29 聊聊该如何写-个网站
p30 回顾及这周安排
p31 整合jdbc使用
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/smbms?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
p32 整合Druid数据源
#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
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
//后台监控 :web.xml,ServletRegistrationBean
//因为springBoot 内置了 servlet容器,所以没有web.xml,替代方法:ServletRegistrationBean
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台需要有人登录,账号密码配置
HashMap<String, String> initParameters = new HashMap<>();
//增加配置
initParameters.put("loginUsername","admin");//登录key 是固定的 loginUsername loginPassword
initParameters.put("loginPassword","123456");
//允许谁可以访问
initParameters.put("allow","");
//禁止谁能访问 initParameters.put("kuangshen","192.168.11.123");
bean.setInitParameters(initParameters);//设置初始化参数
return bean;
}
// filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//可以过滤哪些请求呢?
HashMap<String, String> initParameters = new HashMap<>();
//这些东西不进行统计~
initParameters.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
return bean;
}
}
p33 整合mybaties框架
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&Unicode=characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 整合mybatis
mybatis.type-aliases-package=com.kuang.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
//这个注解表示了这是一个 mybatis 的 mapper 类;
@Mapper
@Repository //spring关联
public interface UserMapper {
List<User> queryUserList();
User queryUserById(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
<?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>
<select id="queryUserById" resultType="User">
select * from user where id = #{id}
</select>
<insert id="addUser" parameterType="User">
insert into user(id,name,pwd)values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="int">
update user set name = #{name},pwd=#{pwd} where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)