一、springBoot入门
1.springboot简介
简化spring的框架
整个spring技术栈的大集合
J2EE开发一站式解决方案
2.微服务
微服务:架构风格
一个应用应该是一组小型服务:通过http的方式进行沟通
每一个功能元素最终都是一个可独立替换或独立升级的软件单元
单体应用:All In One
3.HelloWorld
一个功能:浏览器发送hello请求 服务器接收请求并处理 ,响应helloworld字符串;
1)、创建maven项目
使用maven3.3.6版本 3.6.2会报错
2)、导包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3)、编写主程序启动springboot
package com.atguigu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*
@SpringBootApplication 标注一个主程序类 说明他是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args){
//Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
4 )、编写相关Controller和Service
package com.atguigu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello world";
}
}
5)、直接运行可以出结果
6)、简化部署
1简化部署必须导入springboot 插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2导入插件之后 点击打包
3将应用直接打成jar包 在控制台可以java -jar jar路径 的命令直接运行
不必配置tomcat springboot运行或打包都会自带tomcat环境
4.HelloWorld探究
1)、POM文件
2)、父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
他的父项目是
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
他是真正管理springboot应用里的所有依赖
以后我们导入的依赖是不需要写版本号的(不在这里的才需要写)
3)、导入的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-web:web启动器
spring-boot-starter:各种启动器场景启动器 :我们导入了web模块需要的组件
spring-boot将所有功能场景抽取出来 做成一个个启动器 ,只需要导入要用的启动器,她所依赖的会自动导入,要用什么功能就导入什么
2)、主程序类
package com.atguigu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*
@SpringBootApplication 标注一个主程序类 说明他是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args){
//Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@SpringBootApplication:标注的类说明是spring boot的主配置类 spring boot就应该运行这个类的main方法来运行spring boot应用
点进注解看一下
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {。。。}
@SpringBootConfiguration:springboot配置类;
标注在某个类上表示这是springboot的配置类,这个注解在点下去是@Configuration 也就是spring的注解 在点下去是一个@componment组件
@EnableAutoConfiguration;开启自动配置功能
以前spring配置的东西springboot帮我们配置 ,EnableAutoConfiguration告诉springboot打开自动配置 这样配置才能生效
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class);
spring的底层注解,作用是给容器导入指定组件
将主配置类(@springbootapplication标注的类)所在包及下面所有组件扫 描到spring容器中 这就是为什么controller能被扫进来的原因
@Import(EnableAutoConfigurationImportSelector.class);
给容器中导入组件??
EnableAutoConfigurationImportSelector;导入哪些组建的选择器
将需要导入的组件以全类名的方式返回,然后添加到容器中
会给容器添加非常多的自动配置类(xxxAutoConfiguratiion)
有个这些自动配置 免去了我们手动编写配置注入功能组件的工作
这个类包含了j2EE所有功能都被配置好了
5.使用spring initializer 快速创建Spring Boot
创建号springboot:
主程序已经被创建好,我们只需要写业务
resources文件夹中目录结构
static :js css img
tamplates:保存所有模板页面(springboot默认jar包使用内嵌tomcat,默认不支持jsp页面)可以使用模板引擎(thymeleaf)
application。properties:springboot应用的配置文件 可以修改默认设置
@RestController 相当于 @Controller和@ResponseBody的合体
二 配置文件
1.配置文件
SpringBoot有一个全局配置文件
*application.propertier 优先级最高 如果不指定 都读取这里的内容
*application.yml
配置文件作用就是修改默认配置 比如修改端口号
YAML语言:
以前的配置文件 XXX.xml
YAML以数据为中心 比json和xml更适合做配置文件
YAML:语法
server:
port: 8090
XML
<server>
<port>8090</port>
</server>
2.yaml语法
1)、基本语法
k:空格v(表示键值对 空格必须有)不能用tab
以空格控制层级关系 对齐的就是同一级
2)、 值的写法
字面量:(数字,字符串,布尔值)
k: v
字符串不用加上单引号或者双引号
“ ”:表示会转义字符串中的特殊字符
‘ ’ :不会转义字符串中的特殊字符
对象
friends:
name: lisi
age: 18
行内写法
friends: {name: lisi,age: 18}
数组
animal:
- cat
- pig
- dog
行内写法
animal: [cat,pig,dog]
3.yaml给bean赋值
导包 yaml为bean赋值的依赖包而且yaml为bean属性赋值就会有提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
写bean 此处不带要写getset和tostring
public class Person {
private String name;
private Integer age;
private boolean flag;
private Date date;
private Map<String,Object> map ;
private List<Object> list;
private Dog dog;
}
写yaml
server:
port: 8090
person:
name: 张三
age: 18
flag: true
date: 2020/2/2
map: {k1: v1,k2: v2}
list:
- lisi
- zhaoliu
dog:
name: huanggou
age: 18
测试
package com.example.springboot02;
import com.example.springboot02.bean.Person;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/*
@RunWith带表使用springboot的测试类 不用junit的
*/
@RunWith(SpringRunner.class)
@SpringBootTest
class Springboot02ApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
4.properties给bean赋值
person.age=18
person.date=2017/18/18
person.flag=false
person.name=李嘉伟
person.map.k1=v1
person.list=1,2,3
person.dog.name=sad
person.dog.age=15
1在properties中配置这些属性之后输出出来可能出现乱码
2如果yaml也存在会优先使用 properties的内容 因为paoperties是全局配置文件
是因为idea 编码是utf-8 而文件编码是另一种 在设置中更改编码即可 如果还是乱码 删了文件重建
5.@Value
@value(“李嘉伟”)在spring中已经使用过 单独给某个属性赋值
@Value("${person.name}") 从properties文件中拿到值在赋值给属性 或者拿文件的值 跟mybatis获取jdbc连接那个一样 如果用这个语法写 没找到就报错
@Value(#{2*6}) 也能写spel表达式 会自动计算在赋值
@Value 不支持赋值对象类型 就算从配置文件拿到了对象类型也不能赋值
6.@value和@ConfigurationProperties(prefix = “”)的区别
松散绑定:如果属性名是name 配置文件写个Name=李四 这样也能识别 @value 必须写配置文件一样的属性
spel:@Value(#{2*6})@value 支持 配置文件里不能这么写
数据校验:@Validated 说明一个类下的字段要校验 @Email 校验 字段是不是邮件格式 如果用@value赋值 不会校验
复杂类型:@Value 不支持赋值对象类型 就算从配置文件拿到了对象类型也不能赋值
如果只是获取配置文件的基本类型就用@Value
7.@PropertySource
@PropertySource(value = {"classpath:Person.properties"})
加载指定的配置文件 @ConfigurationProperties默认从全局配置文件中获取内容 如果所有的东西都放到全局配置文件就有点乱 所以我们把一些和全局不相关的配置放到别的配置文件 @PropertySource 就是用来读取指定配置文件的
注意:@ConfigurationProperties 还得加上 不能省略 而且全局配置文件不能写关于该类的赋值 否则还是会读全局配置 因为全局配置优先
8.@ImportSource
我们自己写了一个spring的配置文件 springboot无法识别 我们需要在springboot应用类类上加一个注解
@ImportSource(value={" classpath:bean.xml"})
9.配置文件的优先级
这四个位置处都配置了不同的端口号 按照优先级覆盖 不相同的属性都会都加入 相同的属性按优先级覆盖
10.外部配置加载顺序
springboot也可以从以下位置加载配置文件 高优先级会覆盖低优先级 所有配置互补
1)、命令工行参数
java -jar spring-config-0.0.1-SNAPSHOT.jar --server.port=8090
2)、jar包外部
命令执行jar包 会自动执行 jar包外部的配置文件
11.自动配置原理
三 日志
1.日志框架
我们选用 日志接口是SLF4J
日志的实现类是 Logback
springboot底层是spring框架 spring默认的日志是JClspringboot
springboot变成了 SLEF4j和Logback
2.SELF4J使用
1如何在系统中使用SELF4J
以后再开发的时候 日志记录方法的调用 ,不应该调用实现类的方法 ,而是调用日志抽象层的方法
导入SELF4J的jar包
3.SpringBoot使用日志
springboot项目默认导入了loging包
依赖关系:
使用到其他框架 其他框架使用的日志不一样 一定要把其他框架的默认日志依赖移除掉
使用
package com.lijiawei.log;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootLogApplicationTests {
//获取日志
Logger logger = LoggerFactory.getLogger(getClass());
@Test
void contextLoads() {
//日志的级别 由低到高 调整日志级别 以后就只输出设置的级别以上的
logger.trace(" 这是trace日志");
logger.debug("这是debug日志");
logger.info("这是info信息");
logger.warn("这是warn日志");
logger.error("这是error日志");
}
}
设置一些属性在全局配置中
#更改日志级别 指定那个包下
logging.level.com.lijiawei=trace
#当前项目下生成文件保存日志
logging.file=spring.log
或者创建一个文件 以后写logback-spring.xml 这样可以使用高级功能
四springboot与web开发
1.springboot静态资源的映射规则
1)、webjars
所有/webjars/** 都去classpath:/META-INF/resources/webjars/找资源
webjars:以jar包的方式引入资源
要引入JQuery或BootStrao去https://www.webjars.org/ 找对应的jar包
jquery的
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
我们引入了JQuery的jar包 会自动形成springboot能识别的目录结构
访问路径 localhost:8080/webjars/jquery/3.3.1/jquery.js
2)、/**访问任何资源
自己写的静态文件去哪里找呢?
"classpath:/META-INF/resources/"
"classpath:resources/"
"classpath:static/"
"classpath:public/"
"/"根路径
3)、欢迎页
默认寻找静态资源下(上面的几个路径)的所有index.html页面 优先级由高到低 找到就显示
4)、网页图标
直接把图片放到静态资源路径下 按优先级寻找 找到就显示
2.模板引擎thymeleaf
导包 在springboot2.2.4以上默认用的thymeleaf版本是3.0.11
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
thymeleaf语法
thymeleaf顶替了一个视图解析器 前缀 ”classpath:/templates“ 后缀.html
thymeleaf第一次使用
package com.example.demo01.contaoller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
//现在我们不用写视图解析只需要直接返回文件名 在templates写html文件 springboot自动试图解析
@RequestMapping("demo")
public String show1(){
return "success";
}
}
1)、thymeleaf获取值
在控制器设置的值 html不是jsp不能用内置对象获取设置的值 在html中使用thymeleaf获取值
1导入thymeleaf的名称空间、
<html lang="en" xmlns:th="http://www.thymeleaf.org">
2使用thymeleaf
controller
package com.example.demo01.contaoller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class HelloController {
@RequestMapping("demo")
public String show1(Map<String,Object> map){
map.put("age",1);//设置一个值 一会在html中获取
return "success";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>成功</h1>
<!--th:text="" 将div里的文本内容设置为指定的值-->
<div th:text="${age}"></div>
</body>
</html>
2)、语法规则
th:text="" 改变当前元素的文本内容
th:each 会把当前所在标签创建n个
th:text给给这个标签的内容赋值
<h1 th:text="${ag}" th:each="ag:${age}"></h1>
//行内赋值语法 俩个中括号 或者【()】 这代表转义
<h2 th:each="ag:${age}">[[${ag}]]</h2>
表达式:
${…}获取变量值
1 对象的属性 调用方法
2使用内置的基本对象
3内置的工具对象
*{} 选择表达式
和${…}一样 但有个补充功能 可以先获取对象 之后调用属性值的时候写*{属性值} ${…}得对象名。属性名这么写
#{} 获取国际化内容 或者获取thymeleaf内置对象
@{} 定义url链接 写在a标签一般
3.spring MVC自动配置
1自动配置了springmvc的视图解析器
-ContentNegotiatingViewResolver 组合所有视图解析器 通过它 我们写一个视图解析器 这个类就会自动 组合 进去 这就达到了定制视图解析器的效果
2静态资源文件夹路径
3首页
4Convert 转换器 作用是 将提交的int类型转换成Integer 把true转换成boolean类型 等等
5formatter 格式化器 2017-2-2装成date类型
6HttpMessageConvert 将User----json
定制所有自动配置的东西 只需要注册到容器 springboot在检查所有组件的时候 如果有用户写的就会使用用户写的
4.定制
package com.example.demo01.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
//不想用springboot自动配置好的 想自己定制 就要把这个类注册到容器 并继承WebMvcConfigurationSupport
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//WebMvcConfigurationSupport类下全是自动配置好的 要定制哪一个就重写哪一个方法
@Override
//比如重写视图转发
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送aaaa请求 跳转到success页面
registry.addViewController("/aaaa").setViewName("success");
}
}
定制的配置 会覆盖springboot的自动配置 但是 没有覆盖的还会生效 如果加了@EnableWebMvc 相当于全面接管springboot 所有自动配置不生效 回到ssm最原始的地方 所有配置都自己配
五CRUD案例
1.导入文件
在把资源导入之后会遇到几个问题
1 访问8080地址 无法跳转到首页 解决:不屑controller 我们自己接管写一个类 哪些个请求跳转到哪个页面
package com.lijiawei.demo.MyConfig;
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 MyConifg implements WebMvcConfigurer {
@Override
//比如重写视图转发
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送aaaa请求 跳转到success页面
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/").setViewName("index");
}
}
2发现还是无法打开网页 是因为没有导入thymeleafjar包
2 打开主页 无css样式 是因为没访问到静态资源 在主页 获取地址用 @{}把html引用的css连接引用过来 用thymeleaf语法 就要导入名称空间
3如果还是没有样式 可能是模板引擎缓存的问题 在配置文件中关闭缓存 在springboot2.2.4 之后不用关这个
spring.thymeleaf.cache=false
4首页没有图片还是 用thymeleaf 语法 把图片链接 引用即可 到此 主页显示正常 其他页面同理全部thymeleaf
2.国际化
注意 国际化之前 把propertier的编码设置成utf-8
1)、创建文件
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
2)、引入文件
在全局配置文件 配置 国际化文件 文件名去掉 语言和国家代码
spring.messages.basename=i18n.login
3)、写入文件
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Signin Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<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>
<label class="sr-only">Username</label>
<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only" >Password</label>
<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" > [[#{login.remember}]]
</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">中文</a>
<a class="btn btn-sm">English</a>
</form>
</body>
</html>
4)、点击按钮实现国际化
国际化原理 springboot有个类 LocaleResolver (获取区域信息对象) 该类默认会根据请求头获取区域信息
我们自己写一个LocaleResolver 改变他的默认行为
在html页面给 按钮添加一些信息
<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>
重写国际化方法
package com.lijiawei.demo.compoment;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
//重写 必须实现LocaleResolver接口
public class MyLocaleResolver implements LocaleResolver {
//重写解析区域信息的方法
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取按钮带来的参数
String s = httpServletRequest.getParameter("l");
//如果有参数 返回新的Locale 如果没有参数 返回人家自己的 以免空指针
Locale locale =Locale.getDefault();
//判断参数是否为空
if(!StringUtils.isEmpty(s)){
//传过来的参数以下划线分割 语言代码和国家代码 我们分别保存
String [] split = s.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
}
将重写的类注册到组件中 使用@bean 必须在配置类
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
3.登录
接下来做登录 登录成功跳转 使用servlet拦截
登录页面 提交数据 在表单action 写一个servlet 在去controller判断请求带来的数据 做出跳转行为
1)、注意
如果登陆失败 重新加载页面时 样式会改变 因为在html中样式没有加绝对路径/
在servlet设置了一个值 如果登陆失败 就显示内容 否则不显示
<p style="color: red" th:text="${log_status}" th:if="${not #strings.isEmpty(log_status)}" ></p>
2)、注意
登录成功之后 如果在刷新页面会出现405错误 是因为登陆的时候 表单时post方式提交的 ,登录之后如果再刷新页面就是以get方式重复提交了表单 为防止表单重复提交 我们使用重定向的方式跳转到成功页面
4.拦截
如果直接访问 主页面 会跳过登录页面 所以做一个拦截器进行登陆检查
我们写一个拦截器
package com.lijiawei.demo.compoment;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
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 o =request.getSession().getAttribute("LoginUser");
if(o==null){
//说明未登录 未登录就要跳转到主页面
request.setAttribute("message","请先登录");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else {
//以登录 直接放行
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
在配置类重写拦截器
@Override
public void addInterceptors(InterceptorRegistry registry){
//制定拦截那个请求 写的是拦截任意请求 在排除首页 和登陆请求 和样式 要不然就废了
registry.addInterceptor(new LoginHandlerinterceptor()).addPathPatterns("/**")
.excludePathPatterns("/index.html","/user/login","/static");
}
5.Restful风格crud员工列表
要是用restful必须手动开启 自动配置
spring.mvc.hiddenmethod.filter.enabled=true
普通url地址 | restful风格url地址 | |
---|---|---|
查询 | getEmp | emp -----GET |
添加 | getEmp?XXXXXX | emp ------POST |
修改 | updataEmp?id=XXX | emp/id- ------PUT |
删除 | delete | emp/id --------DELETE |
1 thymeleaf抽取公共片段
我们要将顶部导航和 左侧导航抽取
<div th:fragment="片段名"></div
2引用 将标签 和内容全部替换:
引用有三种方式
replace 将要引用的标签和内容全部替换 并删除当前自己的变迁
insert 将要引入的内容和标签加入到当前标签下
include 将要引用的内容包含进来 除去标签
<div th:replace"~{模板名::片段名}"></div>
1 上面写了抽取公共页面片段 我们继续优化 把 每个页面的公共部分抽取到另一个页面 在引入即可
显示员工列表 在list页面
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.id}"></td>
<td th:text="${emp.last_name}"></td>
<td th:text="${emp.email}"></td>
//使用内置对象 将事件贬称
<td th:text="${#dates.format(emp.brithday)}"></td>
<td th:text="${emp.department.departmentName}"></td>
</tr>
</tbody>
员工添加
日期列 值支持2019/5/5 以/分割的 传- . 什么的都错
在配置文件自己定义格式
spring.mvc.date-format=yyyy-MM-dd HH:mm
6错误处理机制
1)springboot默认错误处理机制
1访问一个不存在的也面时 返回一个默认错误页面
1)、原理:
可以参照rMvcAutoConfiguration类 错误处理的自动配置
给容器中添加了以下组件
1DefaultErrorAttributes
这个类帮我们在页面共享信息
2ErrorPageCustomizer
@Value("{error.path:/error}")
private String path = 'error'; 系统出现错误以后来到error请求 进行处理
3BasicErrorController
一旦系统出现4XX 5XX ErrorPageCustomizer就会生效 他会定制错误的响应规则 来到/error请求 BasicErrorController 处理该请求 根据浏览器头部信息 又俩个处理方式 一个返回错误页面一个 返回josn数据
4 DefaultErrorViewResolver
错误之后这个类决定的那个去那个页面
2)、定制错误响应页面
1)在有模板引擎的情况下 :error/状态码 会自动寻找到这里
错误的状态码非常多 每个状态吗写一个页面很麻烦 那么如何做呢?
DefaultErrorViewResolver 类定义了 4xx 和5xx 以4或5开头的错误 会进入4xx.html或5xx.html 我们直接写一个文件4xx.html 这样只要是4开头的错误状态吗都会来到这个页面
如果精确到就是404错误 就会去404.html 如果是其他4开头的就去4xx.html 比如生日类型提交了个asd 就会4xx
如何拿到具体的错误信息呢?
DefaultErrorAttributes 这个类记录着错误信息
1 timestamp 时间戳
2 status 状态码
3 error 错误提示
4exception 异常对象
5message 异常消息
5erros JSR0303校验的错误
有了这些数据 我们在在4xx页面中 拿到具体内容
2) 没有模板引擎 也可以放在静态在原文件夹下
3)上面提到了 处理错误页面you俩个方式
当客户端访问网站出现错误的时候 返回的不是 错误页面 而是JSON 格式的错误信息
六 嵌入式servlet容器
springboot默认使用tomcat 作为嵌入式的servlet容器
1.如何定制和修改tomcat
1)修改server有关的配置 比如端口号 去properties文件设置
#通用的设置
server.XXX=XXX
#修改tomcat的设置
server.tomcat.XXX=XXX
2) 编写一个类修改配置
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> MyServletConfig () {
WebServerFactoryCustomizer<ConfigurableWebServerFactory> c =(a)->a.setPort(8011);
return c;
}
2.如何注册servlet三大组件【Servlet,Filter,Lisenter】
由于springboot默认以jar包方式启动嵌入式的servlet容器来启东springboot的web应用 没有web.xml 文件
ServletRegistrationBean
1)、注册servlet
package com.lijiawei.demo.servlet;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你好");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
加入容器
//注册一个自己的servlet 指定拦截的请求
@Bean
public ServletRegistrationBean myservlet(){
return new ServletRegistrationBean(new MyServlet(),"/hello");
}
2)、注册Filter
自己写的拦截器必须继承Filter
@Bean
public FilterRegistrationBean myfilter(){
FilterRegistrationBean filterRegistrationBean new FilterRegistrationBean();
//注册自己的拦截器
filterRegistrationBean.setFilter(new MyFilter);
//设置拦截多个请求
filterRegistrationBean.set设置拦截多个请求UrlPatterns(Arrays.asList("hello","world")) ;
return filterRegistrationBean;
}
3)、注册Filter
自己写的监听器 实现 ServletContextListener
@Bean
public ServletListenerRegistroationBean myfilter(){
//构造器 直接初测自己的监听器
ServletListenerRegistroationBean servletListenerRegistroationBean = new ServletListenerRegistroationBean(new MyListener);
return servletListenerRegistroationBean;
}
七 Docker
1、简介
Docker是一个开源的应用容器引擎
Docker支持将软件编异成一个镜像:然后在镜像中配置好软件,将镜像发布出去,其他使用者可以直接使用这个镜像
运行中的这个镜像成为容器 容器启动非常快速的
2、核心概念
docker主机:安装了docker的程序就叫docker主机(docker直接安装在操作系统上)
docker客户端:连接docker进行操作
docker仓库:保存打包好的软件镜像
docker容器:镜像启动后的实例成为容器
使用docker步骤
1)、安装docker
2)、去docker仓库找到这个软件的镜像
3)、使用docker运行这个镜像,这个镜像就会产生一个docker容器
4)、对容器的停止就是对这个软件的停止
3、安装centos7
阿里云镜像地址:http://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1908.iso
选择 CentOS-7-x86_64-DVD-1908.iso 这个版本下载
1)、网络配置
5、安装docker
Linux 安装Docker 需要内核3.10版本以上(centos就是3.10以上)
查看当前内核版本 uname -r
升级内核 yum update
安装docker yum install docker
启动docker systemctl start docker
开机自启动docker systemctl enable docker
关闭docker: systemctl stop docker
6、常见操作
1)、镜像操作
搜索 :仓库的mysql docker search mysql(名字)
下载 :docker pull mysql(名字) 默认下载最新版本
docker pull mysql:版本号 (下载指定版本)
查看下载的镜像:docker images
删除指定镜像:docker rmi id(查看下载的镜像的时候有id信息)
2)、容器操作
软件镜像(qq的安装程序)运行镜像----产生一个容器(运行的qq)
镜像启动运行:docker run --name mytomcat -d tomcat
查看正在运行的容器 :docker ps
停止正在运行的容器:docker stop ID(名字也行)
查看运行和退出的所有容器:docker ps -a
容器启动 docker start 容器id
删除容器 docker rm 容器id
3)、端口映射
当运行tomcat的时候 在window下访问8080是失败的 因为没有做端口映射
在启动容器的时候要端口映射 docker run -d p 8888:8080 tomcat
-d代表后台运行
-p主机端口映射到容器端口 在window下访问8888即可访问到容器的8080端口
7、启动mysql
上面说过这么启动 docker run --name mytomcat -d mysql 但是如果这么启动mysql就会启动失败
因为没有指定mysql密码 正确命令
docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
你以为这就可以访问了么? 错 没有做端口映射 weindow无法访问 所以还要写端口映射
docker run -p 3306:3306 --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.5
使用mysql5.5 新版的会出错 最后使用navcat链接
八 数据访问
1.原生jdbc
1)、JDBC
1)springboot访问数据源
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.75.129/test?serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
- 测试
package com.lijiawei.demo1;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class Demo1ApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
}
输出
class com.zaxxer.hikari.HikariDataSource
HikariProxyConnection@1294058862 wrapping com.mysql.cj.jdbc.ConnectionImpl@726aa968
可能会出现时区错误 在url后加 serverTimezone=UTC
默认以class com.zaxxer.hikari.HikariDataSource 作为数据源
2)、操作数据库
springboot自动配置了jdbctamplate操作数据库
package com.lijiawei.demo1.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JDBCController {
@Autowired
JdbcTemplate jdbcTemplate;
@RequestMapping("/hello")
@ResponseBody
public String method(){
String sql = "create table student(id int(10))";
jdbcTemplate.execute(sql);
return "success";
}
}
上面代码的@Autowired将yam文件属性自动注入 JdbcTemplate 这个类直接操作数据库
2.整合Druid数据源
1)、介绍
druid和HikariDataSource 数据源是现在最快的俩个数据源 druid是阿里巴巴旗下开源项目 druid有强大的监控功能 记录了执行过那些sql操作 效果 和 时间等各种详细信息
2)、使用
导包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
创建druid配置类
package com.lijiawei.demo1.Config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
//后台监控
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台有人登陆 设置一个账号密码
HashMap<String,String> initParameters =new HashMap<>();
initParameters.put("loginUsername","admin");//key不能写别的
initParameters.put("loginPassword","123456");//key不能写别的
//允许谁可以访问 空代表任何人 也可以写具体的
initParameters.put("allow","");
bean.setInitParameters(initParameters);
return bean;
}
}
覆盖springboot默认的数据源 并赋值
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.75.129/test?serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
#引入druid数据源 覆盖掉默认的HikariDataSource 数据源
type: com.alibaba.druid.pool.DruidDataSource
#配置druid数据源
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 6000
timeBetweenEvictionRunsMillis: 30000
#配置监控统计拦截的filters stat :监控统计 log4j :日志记录 wall:防御sql注入
filters: stat,wall,log4j
maxPoolpreparedStatmentPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
全部完成之后 配置 直接访问 http://localhost:8080/druid 会跳出登录界面 登陆之后
3.整合mybatis
导包
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
pojo层和 mapper接口
package com.example.demo.mapper;
import com.example.demo.pojo.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
//这个注解表示这是一个mybatis的mapper类
@Mapper
//相当于@compoment 万能组件 @Repository 具体一点而已
@Repository
public interface BookMapper {
public List<Book> querybooks() ;
}
mapper
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybayis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 绑定一个Dao/Mapper接口 相当于实现该接口-->
<mapper namespace="com.example.demo.mapper.BookMapper">
<select id="querybooks" resultType="Book">
select * from book
</select>
</mapper>
properties
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#整合mybatis
#给这个包下的类起别名 类名小写
mybatis.type-aliases-package=com.example.demo.pojo
#mapper注册
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
controller
package com.example.demo.Controller;
import com.example.demo.mapper.BookMapper;
import com.example.demo.pojo.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class myconfig {
@Autowired
BookMapper bookMapper;
@GetMapping("/hello")
@ResponseBody
public List<Book> query(){
List<Book> list =bookMapper.querybooks();
return list;
}
}