文章目录
SpringBoot
- pom.xml
每个springboot项目中都要引入父项目
在spring-boot-starter-parent 的 父项目 spring-boot-dependencies里有各种依赖的版本控制
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.1</version></parent><!--
在spring-boot-starter-parent 的 父项目 spring-boot-dependencies
里有各种依赖的版本控制
--><dependencies><!-- spring-boot的场景启动器,关联该场景里的常用jar包 --><!-- web场景启动器里 关联的有 日志,内嵌tomcat,json等 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- 配置属性类跟配置文件绑定的处理器 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
入门程序
spring-boot的场景启动器,关联该场景里的常用jar包
web场景启动器里 关联的有 日志,内嵌tomcat,json等
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
- application.properties
server.port=8080
server.servlet.context-path=/ls
- handler
@RestController//返回jsonpublicclassHelloHandler{@RequestMapping("/hello")publicStringhello(){return"springboot入门程序-hello!";}}
- 创建启动类/向导类/主程序 - -
注意包结构 :主包结构下 创建
@SpringBootApplication//默认扫描所在包里的子包里的 各类注解publicclassMyRunner{publicstaticvoidmain(String[] args){SpringApplication.run(MyRunner.class, args);}}
- SpringBootApplication注解上 被SpringBootConfiguration 标注
- SpringBootConfiguration 被 Configuration标注
- Configuration 是 spring中的配置类,也是被扫描为组件的一个注解
- Configuration注解上 被 Component 标注 会被扫描为spring容器里的组件/bean
- 运行主程序,在浏览器输入localhost:8080/ls/hello即可访问
- 添加
spring-boot-maven-plugin
到pom.xml
创建可执行jar
- 停止程序
- 添加插件
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
- 运行maven 的打包命令
- 将jar拷贝入桌面文件夹abc内 (模拟任意文件夹)
- 使用命令运行jar
java -jar sbt001-1.0-SNAPSHOT.jar
java -jar -Dserver.port=8090 sbt001-1.0-SNAPSHOT.jar
依赖管理
1.jar包版本
每个SringBoot项目都需要引入父项目
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version></parent>
ctrl单击spring-boot-starter-parent查看父项目发现: 父项目 还有一个 父项目
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.6.6</version></parent>
ctrl单击spring-boot-dependencies查看,发现几乎声明了开发中常用各种jar的版本号:
<properties><activemq.version>5.16.1</activemq.version><antlr2.version>2.7.7</antlr2.version><appengine-sdk.version>1.9.86</appengine-sdk.version><artemis.version>2.15.0</artemis.version><aspectj.version>1.9.6</aspectj.version>
......
- 版本号自动被父项目进行管理dependencyManagement ,在导包时可以不写版本号
- 可以自行指定版本号
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>
- 可以在自己项目的pom中指定版本号属性
<properties><mysql.version>5.1.47</mysql.version></properties>
2.场景启动器
springboot中有很多 形如: spring-boot-starter-XXX 的场景启动器 , 他会自动把XXX场景需要的所有jar包一同依赖进来.
<!-- 引入web场景相关的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
ctrl+单击 spring-boot-starter-web 可以看到 web场景的很多依赖被加入.
helloworld 的自动配置
- 自动引入并配置好了内嵌的tomcat
- 自动引入并配置好了web常见组件. 比如 示例里的中文没有乱码说明已经配置好了字符编码过滤器
publicstaticvoidmain(String[] args){ConfigurableApplicationContext context =SpringApplication.run(MainInitiator.class, args);String[] beanDefinitionNames = context.getBeanDefinitionNames();for(String name : beanDefinitionNames){System.out.println(name);}}
在打印的容器中组件名的时候,我们发现了: 各种viewResolver , multipartResolver,dispatcherServlet,characterEncodingFilter,jackson等组件.
- 默认的包结构 约定>配置 目前必须这么做.
主程序(向导/启动类)所在包下及其子包里 带有注解的组件 都才会被扫描到容器中.
- 各种配置都有默认配置
比如: tomcat的端口号8080
我们可以在resources目录下的 application.properties文件中进行修改
server.port=8088
在我们写的时候发现有快捷键提示. ctrl单击:server.port 跳转到配置属性类中: 转到setter方法
@ConfigurationProperties(
prefix ="server",
ignoreUnknownFields =true)publicclassServerProperties{privateInteger port;......
@ConfigurationProperties :配置属性类 , 前缀是server, springboot会自动绑定到属性配置文件中
而配置属性类 的 信息 会被 系统读取 .
- 按需加载自动配置.
注: 在配置文件中 配置: debug=true 则可以在启动界面中看到 条件评估报告: 哪些场景装配了.哪些场景没装配,缺少了哪些条件等
容器功能里的几个注解
1.@Configuration @SpringBootConfiguration
@AutoConfiguration 配置类
2.@Import
@Import注解 可以给容器中导入某个组件
@Import(value ={Random.class,Date.class})@ConfigurationpublicclassMyConfig{...
默认的组件的名字 全路径类名 eg: java.util.Random
注: 一般的bean的id或名字 为 类名小写 比如 myRunner
3.@Conditional
满足指定的条件才生效. 可以添加到类或方法上
4.配置绑定
- 配置文件里使用一些前缀 可以 直接绑定到配置属性类里的属性
或
- 在 application.properties 中
- handler
- 成功运行
SpringInitializr
使用IDEA 的SpringInitializr 快速创建 springBoot应用 必须联网
- 此处改为2.7.1,删除java17版本,使用java8
- 目录结构
yml/yaml
- YAML 的配置文件后缀为 .yml
- 使用缩进和换行表示层级关系
yml
server:port:8082# 属性和属性值之间 使用 冒号 空格 隔开servlet:context-path:'/ls'# 字符串可以使用引号 或 不使用
cat:name:'tomcat'weight: 2.2D
dog:nick: 旺财
age:5#beauty:name:'李思'age:28model:truecat:name:'大花猫'weight: 3.3D
birthday: 2000/01/12 # yml里日期格式必须为 yyyy/MM/dd#数组 list set 都有两种写法hobbys:['冬泳','羽毛球','烹饪']foods:- 大白菜
- 胡萝卜
- 冬枣
salarys:[1000.0F,555.5F,6666.8F]# map或对象 都有两种写法sizes:height: 177cm
weight: 55.9kg
eye:4.9# 对象可以用{}jason格式 也可使用缩进列出的格式dogs:big:[{'nick':'大黄','age':7},{'nick':'二黄','age':6},{'nick':'小黄','age':5}]small:-{'nick':'蝴蝶1号','age':1}-{'nick':'蝴蝶2号','age':2}-nick:'蝴蝶3号'age:3
controller
@RestControllerpublicclassYMLController{@AutowiredprivateCat cat;@AutowiredprivateDog dog;@AutowiredprivateBeauty beauty;@RequestMapping("/demo")publicMap<String,Object>demo(){Map<String,Object> map =newHashMap<>();
map.put("猫数据",cat);
map.put("狗数据",dog);
map.put("美女数据",beauty);return map;}}
在浏览器访问: http://localhost:8082/ls/demo
SpringMVC自动配置
1: springboot引入web场景以后, 会自动配置一些 springmvc的配置, 能够应对绝大多数的web场景.
2: 如果我们想继续使用 springboot的默认配置 , 以及还能自己添加一些配置, 那么我们可以
- 使用@Configration 和 @Bean 自己做配置类 ,添加组件
- 或实现 WebMvcConfirgure接口, 重写方法或添加 一些组件进去.
- 或使用mvc已经绑定的前缀的配置属性类 在 配置文件里更改默认配置
3: 如果我们想弃用springboot的mvc的所有默认配置, 全面接管mvc场景的配置, 使用**@Configration + @EnableWebMvc**
WebMvcAutoConfigration 自动配置类有一个条件是 : spring容器里不能有这个类型的组件: WebMvcConfigurationSupport
@EnableWebMvc 注解:
发现 自动向spring容器添加一个组件: DelegatingWebMvcConfiguration
DelegatingWebMvcConfiguration 是 WebMvcConfigurationSupport 的子类型
静态资源
A.默认的静态资源目录
在static下的index.html会被默认访问
改变默认的静态资源路径:
# 配置springboot静态资源 存放的位置 为 类路径下的my文件夹下的(原来的static里的index.html就访问不了)spring:web:resources:static-locations:['classpath:/my/']# 配置springboot静态资源的 访问路径mvc:static-path-pattern:'/a/**'
B. WebJars 了解
除了前面提到的“标准”静态资源位置外,Webjars内容也有特殊情况。
/webjars/**
如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。
在 webjars的网站上:https://www.webjars.org/ 搜索 jquery的jar包依赖 添加到 pom中
必须添加下面这个:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
<buttonid="btn"type="button">点击</button><scriptsrc="/ls/webjars/jquery/3.7.1/jquery.slim.js"></script><script>$("#btn").click(function(){alert(1+2+3+4);})</script>
C.默认欢迎页面
Spring Boot支持静态和模板欢迎页面。它首先
index.html
在配置的静态内容位置中查找文件。如果找不到,它将寻找一个
index
模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。
模板欢迎页: 走控制层,经视图解析器得到的欢迎页.
①.静态欢迎页
在static目录下 放入 index.html , 不使用任何的自定义的: 静态资源访问前缀 的前提下,
则可以测试看到默认欢迎页.
②.controller处理 /index请求 转发到 欢迎页 后面说到模板时再说.
请求参数处理
A.restful风格
- html
<formaction="/ls/user"method="post"><inputname="username"value="POST请求"/><inputtype="submit"value="POST请求"/></form><formaction="/ls/user"method="post"><inputname="username"value="PUT请求"/><inputtype="hidden"name="_method"value="PUT"/><inputtype="submit"value="PUT请求"/></form><formaction="/ls/user"method="post"><inputname="username"value="DELETE请求"/><inputtype="hidden"name="_method"value="DELETE"/><inputtype="submit"value="DELETE请求"/></form>
- yml
spring:mvc:hiddenmethod:filter:enabled:true
- controller
@GetMapping("/user")publicStringget(){return"restful风格的get请求完成!";}@PostMapping("/user")publicStringpost(String username){return"restful风格的post请求完成! - "+username;}@PutMapping("/user")publicStringput(String username){return"restful风格的put请求完成! - "+username;}@DeleteMapping("/user")publicStringdelete(String username){return"restful风格的delete请求完成! - "+username;}
○ 让 mvc自动配置的restful过滤器失效,向容器里自己添加一个
@ConfigurationpublicclassMyConfig{@BeanpublicHiddenHttpMethodFilterhiddenHttpMethodFilter(){HiddenHttpMethodFilter hiddenHttpMethodFilter =newHiddenHttpMethodFilter();
hiddenHttpMethodFilter.setMethodParam("mym");return hiddenHttpMethodFilter;}}
<h3><ahref="/ls/user">GET请求</a></h3><formaction="/ls/user"method="post"><inputname="username"value="POST请求"/><inputtype="submit"value="POST请求"/></form><formaction="/ls/user"method="post"><inputname="username"value="PUT请求"/><inputtype="hidden"name="mym"value="PUT"/> 使用mym
<inputtype="submit"value="PUT请求"/></form><formaction="/ls/user"method="post"><inputname="username"value="DELETE请求"/><inputtype="hidden"name="mym"value="DELETE"/><inputtype="submit"value="DELETE请求"/></form>
B.自定义类型转换器
在WebMvcConfigurer接口中可以进行很多配置. 下面添加自定义类型转换器: (Converter只用于 请求参数绑定到handler方法入参, 不会对配置文件里的有作用.)
- html
<h3><ahref="/ls/user/2000-01-01">GET请求</a></h3>
- 转换器
@ConfigurationpublicclassMyConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddFormatters(FormatterRegistry registry){
registry.addConverter(newConverter<String,Date>(){@OverridepublicDateconvert(String source){SimpleDateFormat sdf =newSimpleDateFormat("yyyy-MM-dd");try{Date date = sdf.parse(source);return date;}catch(ParseException e){
e.printStackTrace();thrownewRuntimeException("不符合转换的日期格式! source = "+source);}}});}}
- controller
数据访问
每一个XXXX-starter-XXX 都会有一个 XXXautoConfigration的类 做自动配置.一般自动配置类 还 绑定了在配置文件中的某个前缀
1.默认连接池是 Hikari 默认配置了JdbcTemplate
- 添加 JDBC 启动器 - 连接池的自动配置类 : DataSourceAutoConfigruation
- 加入mysql的驱动 依赖 -
- 修改配置文件 -
- 在 test包下 进行测试 -
@ResourceprivateJdbcTemplate template;@TestvoidcontextLoads(){String sql ="select count(*) cs from worker";Integer integer = template.queryForObject(sql,Integer.class);System.out.println(integer);}
2.修改连接池为 Druid
- 引入 druid的 starter -
- 修改配置文件 -
监控功能的访问路径 是 /druid/index.html
- controller
druid里有内置的DataSource,可以自动注入
@AutowiredprivateDataSource dataSource;@ResponseBody@RequestMapping("/workers")publicList<Worker>workers(){JdbcTemplate template =newJdbcTemplate(dataSource);String sql ="select * from worker";List<Worker> workers = template.query(sql,newBeanPropertyRowMapper<>(Worker.class));return workers;}
3.springboot的配置文件
1.可以放置 4个位置 加载顺序 由上到下
2.多配置文件形式
多配置文件形式 采用 application-xxx.yml xxx表示不同阶段
如: dev prod test
dev: 开发环境
prod: 生产环境
test: 测试环境
3.
- application.yml里 使用 - - - 多文档形式
删除三个阶段的配置文件
日志
1.Log4j 介绍
Log4j是Apache是apache旗下的一款开源的日志框架,通过在项目中使用Log4j,我们可以控制信息输出到控制台,文件、甚至是数据库中。我们可以控制每一条日志的输出格式。通过定义日志的输出级别,可以更灵活的控制日志的输出过程。方便项目调试。
2.Log4j组件
log4j主要由Loggers(日志记录器),Appenders(输出器),和Layout(日志格式化器)。其中Loggers控制日志输出级别和日志是否输出;Appenders指定日志的输出方式(输出到控制台,文件等);Layout控制日志输出的格式。
Loggers:
日志记录器,负责收集处理日志记录,实例的命名是类"XX"的全限定类名,Loggers的名字大小写铭感,其命名有继承机制:例如:name为org.apache.commons的logger会继承为name为org.apache的logger。
Log4j中有一个特殊的logger叫做"root",它是所有logger的根。也就意味着其他所有的logger都会直接会间接的继承root。root的logger可以用Logger.getRootLogger()方法获取。但是,自log4j1.2版以来,Logger类已经取代了Category类,对于熟悉早期版本的log4j的来说,Logger类可以被视为Category的别名。
Appensers:
Appensers用来指定日志输出到哪个地方,可以同时指定日志输出目的地,Log4j常用的输出目的地有一下几种:
ConsoleAppender: 将日志输出到控制台
FileAppender: 将日志输出到文件
DailyRollingFileAppender:将日志输出到一个文件,并且每天输出到一个新的文件。
RollingFileAppender:将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定的尺寸时,会自动把文件改名,同时产生一个新的文件。
JDBCAppender:将日志信息保存到数据库。
Layouts:
布局器Layouts用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。Log4j常用的Layouts:
HTMLLayout: 格式化日志输出HTML表格形式
SimpleLayout: 简单的日志输出格式化,打印的日志格式为(info - message)
PatternLayout:最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式。
3.案例
4.使用log4j & 日志适配
- 使用log4j - 添加jar包,将lib文件夹添加为库 - - log4j.properties(建在src下)
# 级别 , 自定义的输出源
log4j.rootLogger=INFO,myConsole
# 输出源的配置
# 控制台输出
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
# 输出布局采用正则布局
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
# 正则布局格式
log4j.appender.myConsole.layout.ConversionPattern=%p [%t] %l %m%n
- java
publicclassShow{// 日志对象publicstaticLogger logger =Logger.getLogger(Show.class);publicstaticvoidmain(String[] args)throwsInterruptedException{int cnt =0;for(int i =1; i <=100; i++){try{int div =newRandom().nextInt(3);// 0 1 2
logger.info("次数: "+ i);int result =100/ div;//日志输出
logger.info("结果: "+ result);// slf4j里的日志输出可以使用{}占位符}catch(ArithmeticException e){
logger.error(e.getMessage());
cnt++;}Thread.sleep(1300);}
logger.info("出现异常次数 即 随机到0的次数 : "+ cnt);}}
- 输出 -
- 使用slf4j门面 - jar - - log4j.properties
# 级别 , 自定义的输出源
log4j.rootLogger=INFO,myConsole,myScrollFile
# myFile
#log4j.appender.myFile=org.apache.log4j.FileAppender
#log4j.appender.myFile.layout=org.apache.log4j.PatternLayout
#log4j.appender.myFile.layout.ConversionPattern=%p [%t] %l %m%n
#log4j.appender.myFile.File=logs/my.log
#log4j.appender.myFile.Append=true
log4j.appender.myScrollFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.myScrollFile.layout=org.apache.log4j.PatternLayout
log4j.appender.myScrollFile.layout.ConversionPattern=%p [%t] %l - %d - %m%n
log4j.appender.myScrollFile.File=logs/my.log
log4j.appender.myScrollFile.Append=true
log4j.appender.myScrollFile.DatePattern='.'yyyy-MM-dd-HH-mm
- 在项目下建包logs
- Show
publicclassShow{// 日志对象//public static Logger logger = Logger.getLogger(Show.class);publicstaticLogger logger =LoggerFactory.getLogger(Show.class);publicstaticvoidmain(String[] args)throwsInterruptedException{int cnt =0;for(int i =1; i <=100; i++){try{int div =newRandom().nextInt(3);// 0 1 2
logger.info("次数: "+ i);int result =100/ div;//日志输出
logger.info("结果: {}",result);// slf4j里的日志输出可以使用{}占位符}catch(ArithmeticException e){
logger.error(e.getMessage());
cnt++;}Thread.sleep(1300);}
logger.info("出现异常次数 即 随机到0的次数 : {}",cnt);}}
- 输出 -
- 在SpringBoot中使用logbak - 在resource下添加logbak-spring.xml- 在application.xml中添加
logging:
config: 'classpath:logbak-spring.xml'
thymeleaf
springboot 默认不支持 JSP , 推荐使用thymeleaf.
使用详情参考使用文档
入门程序
- pom.xml
- 查看ThymeleafAutoConfiguration
- 查看ThymeleafProperties -
- 在 ThHelloConytroller
@ControllerpublicclassThHelloController{@AutowiredprivateBeauty beauty;@RequestMapping("/thindex")publicStringthindex(){return"thindex";}}
- thindex
<h2><ath:href="@{/thhello}">thymeleaf入门</a></h2>
- ThHelloController
@ControllerpublicclassThHelloController{@AutowiredprivateBeauty beauty;@RequestMapping("/thhello")publicStringthhello(ModelMap map){
map.addAttribute("msg","thymeleaf入门程序");
map.addAttribute("beauty",beauty);return"success";}}
- success.html
<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>Title</title></head><body><h2>文本中直接获取数据是: [[${msg}]]</h2><h2>在标签里的数据是:<spanth:text="${msg}"></span></h2><h2>美女名字: <spanth:text="${beauty.name}"></span></h2><h2>美女年龄: <spanth:text="${beauty.age}"></span></h2><h2>美女是不是模特: <spanth:text="${beauty.model}"></span></h2><h2>美女生日: <spanth:text="${beauty.birthday}"></span></h2><h2>美女的猫: <spanth:text="${beauty.cat.name}"></span></h2><!-- 数组,list,set 遍历写法一致 --><pth:each="food,stat:${beauty.foods}"><spanth:text="${stat.count}"></span> : <spanth:text="${food}"></span></p><hr/><hr/><pth:each="entry:${beauty.sizes}">
[[${entry.key}]] - <spanth:text="${entry.value}"></span></p><hr/><hr/><divth:each="item:${beauty.dogs}"><spanth:text="${item.key}"></span><br/><pth:each="dog:${item.value}"><spanth:text="${dog.nick}"></span> - <spanth:text="${dog.age}"></span></p></div><hr/><hr/><h2th:if="${beauty.model}">美女是模特</h2><h2th:unless="${beauty.age != 28}">大学老师</h2><hr/><hr/><divth:switch="${beauty.age}"><pth:case="20">小学生</p><pth:case="24">大学生</p><pth:case="28">博士生</p><pth:case="32">院士</p></div></body></html>
几个基本功能
1. 新建项目-登录
- 使用初始化向导创建项目,勾选必要的场景依赖
- 将静态资源加入项目
- 将login.html放入templates目录下 并引入thymeleaf的命名空间 xmlns:th=“http://www.thymeleaf.org”
- 创建 跳转登录页的controller 方法
@ControllerpublicclassIndexController{/**
* 跳转登录页
* @return
*/@GetMapping(path ={"/","/login"})publicStringloginPage(){return"login";}
- 将index.html放入templates目录下 并引入thymeleaf的命名空间
- 修改login.html中登录表单的属性
<formclass="form-signin"th:action="@{/login}"method="post">
- 创建 处理登录 并 跳转首页的controller 方法
@PostMapping(value ={"/login"})publicStringindexPage(User user,HttpSession session,Model model){if(!StringUtils.isEmpty(user.getUsername())&&!StringUtils.isEmpty(user.getPassword())){
session.setAttribute("user", user);}else{
model.addAttribute("msg","用户名或密码不正确!");return"login";}return"redirect:/index.html";}@RequestMapping("/index.html")publicStringredirectIndexPage(@SessionAttribute(name ="user",required =false)User user,Model model){if(user==null){
model.addAttribute("msg","未登录!请先登录!");return"login";}return"index";}//这里为了 防止表单 重复提交.
- 设计bean User类型
@Data@ToStringpublicclassUser{privateString username;privateString password;}
- login.html中添加一个 回显 msg信息的标签
<divclass="login-wrap"><labelclass="text-danger"th:text="${msg}"/><inputtype="text"name="username"class="form-control"placeholder="用户名"autofocus><inputtype="password"name="password"class="form-control"placeholder="密码">
... ...
2.抽取公共部分,让一个页面可以复用
- 创建table文件夹,存放所有表格页面
- 观察页面将 页面中公共的部分 抽取到 common.html中 ,使用thymeleaf语法可以让其他页面引用common.html中的 部分
- 在被抽取页面引用公共部分
<!-- 引入相同的头部部分 --><th:blockth:include="common::commonHead"/><!-- 引入相同的左侧导航栏 --><th:blockth:replace="common::commonLeftNav"></th:block>
三种引入公共片段的方式的区别:
公共部分:
<footerth:fragment="copy">© 2011 The Good Thymes Virtual Grocery
</footer>
使用三种引入方式:
<body><divth:insert="footer :: copy">2</div><divth:replace="footer :: copy">2</div><divth:include="footer :: copy">2</div></body>
结果:
<body>
整个片段插入 到 当前标签里
<div><footer>© 2011 The Good Thymes Virtual Grocery
</footer></div>
整个片段替换 当前标签
<footer>© 2011 The Good Thymes Virtual Grocery
</footer>
只有片段里的内容 替换到 当前标签内
<div>© 2011 The Good Thymes Virtual Grocery
</div></body>
3.拦截器(登录拦截)
1.创建拦截器实现类
/**
* 在访问诸如 /tables/** 这种特殊路径下的内容时 需要有登录权限
*/@Slf4jpublicclassLoginInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{HttpSession session = request.getSession();User user =(User) session.getAttribute("user");if(user ==null){
log.warn("正在访问的资源为: {}",request.getRequestURI());//重定向到登录页面的handler方法 不放行
response.sendRedirect(request.getContextPath()+"/login");returnfalse;}returntrue;}}
2.配置拦截器,将拦截器注入容器,并添加拦截规则
@ConfigurationpublicclassMyConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){LoginInterceptor loginInterceptor =newLoginInterceptor();
registry.addInterceptor(loginInterceptor).addPathPatterns("/**")// 添加拦截路径.excludePathPatterns("/","/login","/js/**","/images/**","/fonts/**","/css/**","/error/**");// 排除拦截路径}@BeanpublicLocaleResolverlocaleResolver(){returnnewMyLocaleResolver();}}
4. 文件上传
- 添加上传表单页面 form_layouts.html 添加 thymeleaf的 命名空间
<formrole="form"method="post"enctype="multipart/form-data"th:action="@{/upload}"><divclass="form-group"><labelfor="username">Username</label><inputtype="text"class="form-control"name="username"id="username"placeholder="username"></div><divclass="form-group"><labelfor="password">Password</label><inputtype="password"class="form-control"name="password"id="password"placeholder="Password"></div><divclass="form-group"><labelfor="headimg">头像</label><inputtype="file"id="headimg"name="headimg"><pclass="help-block">Example block-level help text here.</p></div><divclass="form-group"><labelfor="liveimg">生活照</label><inputtype="file"id="liveimg"name="liveimg"multiple><pclass="help-block">Example block-level help text here.</p></div><divclass="checkbox"><label><inputtype="checkbox"> Check me out
</label></div><buttontype="submit"class="btn btn-primary">Submit</button></form><script>
$("#headimg").change(function(){
let file = this.files[0];
let url = URL.createObjectURL(file);
$("#headimgShow").attr("src",url);
$("#headimgShow").css("display","inline-block");
})
$("#liveimg").change(function(){
$("#liveimgShowDiv").empty();
let files = this.files;
for (let i = 0; i < files.length ; i++) {
let url = URL.createObjectURL(files[i]);
let img = $("<img/>");
img.attr({"src":url,"width":50,"height":50});
$("#liveimgShowDiv").append(img);
}
})
- common页面的 左侧栏中 修改访问 表单页面的超链接
<ath:href="@{/form_layouts}">表单布局</a>
- 添加controller 首先处理 跳转到 表单页面
@ControllerpublicclassFileController{@GetMapping("/form_layouts")publicStringform_layouts(){return"form/form_layouts";}......
- yaml中 配置 最大文件上传大小
spring:servlet:multipart:max-file-size: 10MB
max-request-size: 100MB
- 处理上传请求
@PostMapping("/upload")publicStringuploadm(User user,@RequestPart(name="headimg",required =false)MultipartFile headimg,MultipartFile[] liveimg){
log.info("上传信息:{}",user.toString());
log.info("头像大小:{}",headimg.getSize());
log.info("生活照数量:{}",liveimg.length);//保存文件和springMVC用法一致.return"redirect:/index.html";}
5.错误处理
1.自定义错误页面
可以在静态文件夹下创建 error文件夹 也可以在 模板文件夹下 创建 error文件夹,给页面 添加 thymeleaf的命名空间
2.在5xx页面上 可以使用 ${message}来获取 异常信息.
${status} 取响应状态码
3.异常处理自动配置原理
4.定义全局异常处理器 @ControllerAdvice + @ExceptionHandler 默认优先级高
@ControllerAdvice// 有@Component@Slf4jpublicclassMyGlobalExceptionHandler{@ExceptionHandler({ArithmeticException.class,NullPointerException.class})//这是处理 异常的方法,用起来其实就是handlere方法publicModelAndViewexceptionHandler(Exception e){ModelAndView mv =newModelAndView();
mv.setViewName("error/myxx");
mv.addObject("status","9527");
mv.addObject("message","出现了算术或空指针异常");
log.warn("全局异常处理器工作了,异常: {}",e.getMessage());return mv;}}
5.自定义异常 @ResponseStatus 定义状态码 和 错误原因信息 (因为springboot 异常和错误要带着http响应状态码)
@ResponseStatus(code =HttpStatus.BAD_REQUEST,reason ="请求语法有问题")publicclassCustomExceptionextendsException{}
6.自定义异常解析器 默认优先级低 , 使用@order注解 设置优先级
@Component@Order(value =Ordered.HIGHEST_PRECEDENCE)publicclassMyHandlerExceptionResolverimplementsHandlerExceptionResolver{@OverridepublicModelAndViewresolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex){ModelAndView mv =newModelAndView();
mv.setViewName("error/myxx");
mv.addObject("status",9999);
mv.addObject("message","异常解析器处理了!");return mv;}}
6.国际化
1.提供国际化资源配置文件
title=默认标题
user=默认用户
pass=默认密码
title=登录
user=用户
pass=密码
title=Login
user=Username
pass=Password
- yaml配置指定资源配置文件位置
spring:messages:basename: ls
3.自定义国际化解析器
publicclassMyLocaleResolverimplementsLocaleResolver{@OverridepublicLocaleresolveLocale(HttpServletRequest request){String lan = request.getParameter("lan");if(lan !=null&& lan.contains("_")){String[] data = lan.split("_");// data[0] zh data[1] CNLocale locale =newLocale(data[0],data[1]);return locale;}// 返回默认国际化信息对象 或者 自定义一个returnLocale.getDefault();}@OverridepublicvoidsetLocale(HttpServletRequest request,HttpServletResponse response,Locale locale){}}
4.配置为组件, 组件名必须为 localeResolver
@ConfigurationpublicclassMyConfigimplementsWebMvcConfigurer{@BeanpublicLocaleResolverlocaleResolver(){returnnewMyLocaleResolver();}}
5.thymeleaf里结合消息表达式一起使用
<ath:href="@{/index(lan='zh_CN')}">中文</a><ath:href="@{/index(lan='en_US')}">英文</a><h2th:text="#{index.login}"></h2><h2th:text="#{index.register}"></h2>
版权归原作者 kiddkid 所有, 如有侵权,请联系我们删除。