springboot内置了tomcat
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.5</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.5</version>
</dependency>
</dependencies>
server.servlet.context-path=/springboot03
server.port=8090
server:
port: 8080
servlet:
context-path: /springboot03
上下两行隔开两个空格是一个层级。
两者都配置的话.properties的优先级更高。
导入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatis的启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
server:
servlet:
context-path: /springboot03
mybatis:
type-aliases-package: com.msb.pojo
mapper-locations: classpath:mybatis/*.xml
其他的地方就和springmvc的一样了。
logback作用: 打印日志
在resourse目录下增加logback.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${catalina.base}/logs/"/>
<!-- 控制台输出 -->
<appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志输出格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</layout>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 日志输出级别 -->
<root level="info">
<appender-ref ref="Stdout"/>
<appender-ref ref="RollingFile"/>
</root>
<logger name="com.msb.mapper" level="DEBUG"></logger>
<!-- <!–日志异步到数据库 又开启一个线程来打印日志–>-->
<!-- <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
<!--<!– 日志异步到数据库–>-->
<!-- <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
<!--<!– 连接池–>-->
<!-- <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
<!-- <driverClass>com.mysql.cj.jdbc.Driver</driverClass>-->
<!-- <url>jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true-->
<!-- <user>root</user>-->
<!-- <password>cl091900</password>-->
<!-- </dataSource>-->
<!-- </connectionSource>-->
<!-- </appender>-->
</configuration>
导入依赖:
<!-- pageHelper的启动器-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
Controller层:
@RequestMapping("findByPage/{pageNum}/{pageSize}")
@ResponseBody
public List<Emp> findByPage(@PathVariable("pageNum") Integer pageNum,@PathVariable("pageSize") Integer pageSize ){
return empService.findByPage(pageNum,pageSize);
}
Service层:
@Override
public List<Emp> findByPage(Integer pageNum, Integer pageSize) {
Page<Object> objects = PageHelper.startPage(pageNum, pageSize);
List<Emp> list=empMapper.findAll();
System.out.println(objects.toString());
// 页码 页大小 当前页数据 总页数 总记录数
//这些对象都在startPage的返回值里
//数据封装方式2pageInfo ->pageBean
PageInfo<Emp> pi=new PageInfo<>(list);
return list;
}
很方便的帮助我们实现对sql执行的监控
导入依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
application.yml配置文件:
spring:
datasource:
#使用阿里的Druid连接池
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
# 填写你数据库的url、登录名、密码和数据库名
url: jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password:
druid:
#连接池配置信息
#初始化大小,最小,最大
initial-size: 5
min-idle: 5
maxActive: 20
#配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 配置DruidStatFilter
web-stat-filter:
enabled: true
url-pattern: "/*"
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
# 配置DruidStatViewServlet
stat-view-servlet:
url-pattern: "/druid/*"
# IP白名单(没有配置或者为空,则允许所有访问)
allow: 127.0.0.1,192.168.8.109
# IP黑名单 (存在共同时,deny优先于allow)
deny: 192.168.1.188
# 禁用HTML页面上的“Reset All”功能
reset-enable: false
# 登录名
login-username: admin
# 登录密码
login-password: 123456
main:
allow-circular-references: true
导入依赖:
<!-- freeMaker启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
Controller:
@Controller
public class FreemarkerController {
@RequestMapping("/show")
public String freemarger(Map<String,Object> map){
map.put("name","漩涡刘能");
return "show";
}
}
show.ftlh:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<br/>
${name}
</body>
</html>
这里使用.ftlh渲染出来的界面,属性如果为空值,则显示不出来。
需要在ftlh中引入这个指令。
<#setting classic_compatible=true>
Controller:
//查询全部员工信息,展示
@RequestMapping("/showEmp")
public ModelAndView testList(){
ModelAndView mv=new ModelAndView();
List<Emp> list=empService.findAll();
System.out.println(list.toString());
mv.addObject("empList",list);
mv.setViewName("showEmp");
return mv;
}
showEmp.ftlh:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#empTable {
width: 80%;
border: 1px solid blue;
margin: 0px auto;
}
#empTable th, td {
border: 1px solid green;
text-align: center;
}
</style>
</head>
<body>
<table id="empTable" cellpadding="0px" cellspacing="0px">
<tr>
<th>索引</th>
<th>工号</th>
<th>姓名</th>
<th>岗位</th>
<th>薪资</th>
<th>部门号</th>
</tr>
<#list empList as emp>
<#setting classic_compatible=true>
<tr>
<#-- //通过_index可以得到循环的下标-->
<td>${emp_index}</td>
<td></td>
<td>${emp.ename}</td>
<td>${emp.job}</td>
<td>${emp.sal}</td>
<td>${emp.deptno}</td>
</tr>
</#list>
</table>
</body>
</html>
Controller:
//查询全部员工信息,展示
@RequestMapping("/showEmpMap")
public ModelAndView testMap(){
ModelAndView mv=new ModelAndView();
List<Emp> list=empService.findAll();
Map<String,Emp> empMap=new HashMap<>();
for (Emp emp : list) {
empMap.put(emp.getEmpno().toString(),emp);
}
mv.addObject("empMap",empMap);
mv.setViewName("showEmpMap");
return mv;
}
showEmpMap.ftlh:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#empTable {
width: 80%;
border: 1px solid blue;
margin: 0px auto;
}
#empTable th, td {
border: 1px solid green;
text-align: center;
}
</style>
</head>
<body>
<#setting classic_compatible=true>
<#--查看Map集合中单独一个元素-->
<table id="empTable" cellpadding="0px" cellspacing="0px">
<tr>
<th>索引</th>
<th>工号</th>
<th>姓名</th>
<th>岗位</th>
<th>薪资</th>
<th>部门号</th>
</tr>
<#list empMap?keys as k>
<tr>
<td>${k_index}</td>
<td>${k}</td>
<td>${empMap[k].ename}</td>
<td>${empMap[k].job}</td>
<td>${empMap[k].sal}</td>
<td>${empMap[k].deptno}</td>
</tr>
</#list>
</table>
</body>
</html>
FreeMarker在遍历map集合是,key必须是String
FreeMaker内置函数:
内建函数语法格式: 变量+?+函数名称
显示年月日: ${today?date}
显示时分秒: ${today?time}
显示日期+时间:${today?datetime}
自定义格式化: ${today?string("yyyy年MM月")}
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.4.5</version>
</dependency>
showEmp.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#empTable {
width: 80%;
border: 1px solid blue;
margin: 0px auto;
}
#empTable th, td {
border: 1px solid green;
text-align: center;
}
</style>
</head>
<body>
展示单个员工信息
工号:<span th:text="${emp.empno}"></span><br>
姓名:<span th:text="${emp.ename}"></span><br>
职务:<span th:text="${emp.job}"></span><br>
上级:<span th:text="${emp.mgr}"></span><br>
入职日期:<span th:text="${emp.hiredate}"></span><br>
<hr/>
<table id="empTable" cellpadding="0px" cellspacing="0px" >
<tr>
<th>工号</th>
<th>姓名</th>
<th>职务</th>
<th>上级</th>
<th>入职日期</th>
<th>工资</th>
<th>补助</th>
<th>部门</th>
<th>操作</th>
</tr>
<tr th:each="emp:${empList}">
<td th:text="${emp.empno}"></td>
<td th:text="${emp.ename}"></td>
<td th:text="${emp.job}"></td>
<td th:text="${emp.mgr}"></td>
<td th:text="${emp.hiredate}"></td>
<td th:text="${emp.sal}"></td>
<td th:text="${emp.comm}"></td>
<td th:text="${emp.deptno}"></td>
<td>
<a th:href="@{removeEmp(empno=${emp.empno},ename=${emp.ename})}" >删除</a>
<a href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>
<a href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>
</td>
</tr>
</table>
<script>
function removeEmp(empno,ename){
var resulet= confirm("确定要删除编号为“+empno+”的"+ename);
if(resulet){
window.location.href="removeEmp?empno="+empno+"&ename="+ename;
}
}
</script>
</body>
</html>
Thymeleaf提供了一些内置对象,内置对象可直接在模板中使用。这些对象是以#引用的。
使用内置对象的语法
1引用内置对象需要使用#
2大部分内置对象的名称都以s结尾。如:strings、numbers、dates
3常见内置对象如下
#arrays:数组操作的工具;
#aggregates:操作数组或集合的工具;
#bools:判断boolean类型的工具;
#calendars:类似于#dates,但是是java.util.Calendar类的方法;
#ctx:上下文对象,可以从中获取所有的thymeleaf内置对象;
#dates:日期格式化内置对象,具体方法可以参照java.util.Date;
#numbers: 数字格式化;#strings:字符串格式化,具体方法可以参照String,如startsWith、contains等;
#objects:参照java.lang.Object;
#lists:列表操作的工具,参照java.util.List;
#sets:Set操作工具,参照java.util.Set;#maps:Map操作工具,参照java.util.Map;
#messages:操作消息的工具。
<span th:text="${#httpServletRequest.getAttribute('msg')}"></span><br/>
<span th:text="${#request.getAttribute('msg')}"></span><br/>
<span th:text="${msg}"></span><br/>
session:<br/>
<span th:text="${#httpSession.getAttribute('msg')}"></span><br/>
<span th:text="${#session.getAttribute('msg')}"></span><br/>
<span th:text="${session.msg}"></span><br/>
application:<br/>
<span th:text="${#servletContext.getAttribute('msg')}"></span><br/>
<span th:text="${application.msg}"></span><br/>
热部署之后则不需要重启项目,当监听到内容改变后tomcat则自动的进行重启。
步骤:
添加依赖:
<!-- 开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.4.5</version>
<optional>true</optional>
</dependency>
注意在2022以前的版本需要修改Reigstry
Ctrl+Shift+Alt+/ 点击弹出框中Registry…
导入依赖:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
使用maven package代码打包就可以
排除项目中自带的所有的Tomcat插件和jsp servlet 依赖,因为这里要将项目放到一个Tomcat上运行
<!--配置SpringBoot的web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除web启动中自动依赖的tomcat插件-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--
手动依赖tomcat插件,但是表明项目打包时该依赖不会被打进去,目的主要是保证开发阶段本地SpringBoot
项目可以正常运行
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
相当于compile,但是打包阶段做了exclude操作-->
<scope>provided</scope>
</dependency>
SpringBoot的启动类继承SpringBootServletInitializer,并重写configure
@SpringBootApplication
public class Springboot04Application extends SpringBootServletInitializer {
//重写配置方法
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Springboot04Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Springboot04Application.class, args);
}
}
使用install命令打包项目,并将war包放到tomcat下的webapps下,启动tomcat即可。
自定义拦截器类:
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
拦截器配置:
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
@Autowired
MyInterceptor myInterceptor;
//设置拦截器路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptorRegistration = registry.addInterceptor(myInterceptor);
interceptorRegistration.addPathPatterns("/**").excludePathPatterns("/login");
}
}
用来编写配置类,里面有一些bean实例,spring容器从配置类中来获取这些实例。
配置类:
@Configuration
public class MyConfig {
@Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
public User user1(){
return new User("张三","123");
}
}
启动类:
@SpringBootApplication
public class Springboot04Application {
public static void main(String[] args) {
ConfigurableApplicationContext Context = SpringApplication.run(Springboot04Application.class, args);
User user1=Context.getBean("user1",User.class);
System.out.println(user1);
}
}
@Import(User.class)
@Configuration
public class MyConfig {
@Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
public User user1(){
return new User("张三","123");
}
}
根据类型来获取bean实例,默认使用无参构造方法来创建实例对象。
原生配置文件引入,允许我们自己定义xml配置文件,在文件中配置bean
@ImportResource("classpath:beans.xml")
@Configuration
public class MyConfig {
@Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
public User user1(){
return new User("张三","123");
}
}
读取application.properties配置文件中的内容,读取进入bean
class Springboot04ApplicationTests {
@DisplayName("测试方法1:")//是对类的描述
@Test //方法可以独立的运行,不需要再测试了
public void test1(){
}
@BeforeAll
public void beforeAll(){
System.out.println("在所有的测试方法执行之前先执行一次");
}
@BeforeEach
public void beforeEach(){
System.out.println("在每一个测试方法之前执行该方法");
}
@AfterEach
public void afterEach(){
System.out.println("在每一个测试方法之后执行该方法");
}
@AfterAll
public void afterAll(){
System.out.println("在所有方法执行之后执行该方法");
}
@RepeatedTest(3)
public void repeatTest(){
System.out.println("重复测试3次");
}
}