SpringBoot

时间:2022-10-29 07:53:38

项目搭建方式1

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>

项目搭建方式2

 <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>

SpringBoot文件配置

application.properties

server.servlet.context-path=/springboot03
server.port=8090

application.yml

server:
  port: 8080
  servlet:
    context-path: /springboot03

上下两行隔开两个空格是一个层级。

两者都配置的话.properties的优先级更高。

SpringBoot整合Mybatis

导入依赖:

 <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的一样了。

SpringBoot整合logback

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>


<!--    &lt;!&ndash;日志异步到数据库 又开启一个线程来打印日志&ndash;&gt;-->
<!--    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
<!--&lt;!&ndash;        日志异步到数据库&ndash;&gt;-->
<!--        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
<!--&lt;!&ndash;            连接池&ndash;&gt;-->
<!--            <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
<!--                <driverClass>com.mysql.cj.jdbc.Driver</driverClass>-->
<!--                <url>jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;rewriteBatchedStatements=true</url>-->
<!--                <user>root</user>-->
<!--                <password>cl091900</password>-->
<!--            </dataSource>-->
<!--        </connectionSource>-->
<!--    </appender>-->

</configuration>

SpringBoot整合pageHelper

导入依赖:

<!--        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;
    }

SpringBoot整合Druid

很方便的帮助我们实现对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

SpringBoot整合FreeMarker

导入依赖:

<!--        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>

FreeMarker常用指令(遍历List集合)

这里使用.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>

FreeMarker遍历Map集合

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月")} 

SpringBoot整合Thymeleaf

导入依赖:

 <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内置对象

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/>

SpringBoot热部署

热部署之后则不需要重启项目,当监听到内容改变后tomcat则自动的进行重启。
步骤:

添加依赖:

<!--        开发者工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.4.5</version>
            <optional>true</optional>
        </dependency>

修改idea自动编译配置:
SpringBoot

idea2022版本:
SpringBoot
这里要打勾。

注意在2022以前的版本需要修改Reigstry
Ctrl+Shift+Alt+/ 点击弹出框中Registry…
SpringBoot
SpringBoot

SpringBoot打包部署

将项目打成jar包

导入依赖:

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

使用maven package代码打包就可以

SpringBoot

项目打成war包

排除项目中自带的所有的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即可。

SpringBoot拦截器配置

自定义拦截器类:

@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");

    }
}

SpringBoot其他注解

@Configuration

用来编写配置类,里面有一些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

@Import(User.class)
@Configuration
public class MyConfig {
    @Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
    public User user1(){
        return new User("张三","123");
    }
}

根据类型来获取bean实例,默认使用无参构造方法来创建实例对象。

@ImportResource

原生配置文件引入,允许我们自己定义xml配置文件,在文件中配置bean

@ImportResource("classpath:beans.xml")
@Configuration
public class MyConfig {
    @Bean // 向容器中添加一个Bean,以方法名作为Bean的id,返回值类型作为组件的类型
    public User user1(){
        return new User("张三","123");
    }


}

@ConfigurationProperties

读取application.properties配置文件中的内容,读取进入bean

JUnit5

JUnit5常见注解

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次");
    }
}