SpringBoot

一、SpringBoot介绍

原有Spring优缺点分析

Spring的优点

​ Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring为企业级Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单 的Java对象(Plain Old Java Object,POJO)实现了EJB的功能。

Spring的缺点分析

**虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。**一开始,Spring用XML配置,而且是很多XML配 置。Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式XML配置。Spring 3.0引入 了基于Java的配置,这是一种类型安全的可重构配置方式,可以代替XML。 所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所以编 写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但与此同时它要求的回报也不少。 除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要 分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。

SpringBoot概念简介

  • Spring Boot是Spring公司的一个*项目,和Spring Framework是一个级别的。
  • Spring Boot实际上是利用Spring Framework 4 自动配置特性完成。编写项目时不需要编写xml文件。发展到现在,Spring Boot已经具有很很大的生态圈,各种主流技术已经都提供了Spring Boot的启动器。

什么是启动器

Spring框架在项目中作用是Spring整合各种其他技术,让其他技术使用更加方便。Spring Boot的启动器实际上就是一个依赖。这个依赖中包含了整个这个技术的相关jar包,还包含了这个技术的自动配置,以前绝大多数XML配置都不需要配置了。当然了,启动器中自动配置无法实现所有内容的自动配置,在使用Spring Boot时还需要进行少量的配置(这个配置不是在xml中了,而是在properties或yml中即可)。如果是Spring自己封装的启动器的artifact id名字满足:spring-boot-starter-xxxx,如果是第三方公司提供的启动满足:xxxx-spring-boot-starter。以后每次使用Spring Boot整合其他技术时首先需要考虑导入启动器。

Spring Boot优点

  1. 使用Spring Boot可以创建独立的Spring应用程序
  2. 在Spring Boot中直接嵌入了Tomcat、Jetty、Undertow等Web 容器,在使用SpringBoot做Web开发时不需要部署WAR文件
  3. 通过提供自己的启动器(Starter)依赖,简化项目构建配置
  4. 尽量的自动配置Spring和第三方库
  5. 绝对没有代码生成,也不需要XML配置文件

Spring Boot的核心

起步依赖- 起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。 简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
自动配置 -Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定 Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。

二、SpringBoot项目搭建

导入依赖

<dependencies>
    <!--也可以用继承父项目的方式-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.1</version>
        <type>pom</type>
    </dependency>
	
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.4.5</version>
    </dependency>
</dependencies>

controller

@Controller
public class MyController {
    @RequestMapping("/test")
    @ResponseBody
    public String testController(){
        return "Ok!";
    }
}

启动类

@SpringBootApplication
public class SpringBoot01Application {
    public static void main(String[] args) {
        //会扫描该类下的所有注解
        SpringApplication.run(SpringBoot01Application.class,args);
    }

}

使用IDEA插件创建【推荐】

SpringBoot

SpringBoot

创建的过程中可能会提示创建失败,连接不上spring官网。多试几次就好。这样就创建了一个SpingBoot的项目。

SpringBoot

编写controller,运行启动类SpringbootStudyApplication测试。

@Controller
public class FirstController {
    @RequestMapping("/first")
    @ResponseBody
    public String firstController(){
        return "hello springBoot";
    }
}

项目配置

SpringBoot默认读取项目下名字为application开头的 yml yaml properties配置文件。

配置端口、项目上下文、数据源

server:
  port: 8080
  servlet:
    context-path: /springboot
spring:
  datasource:
    driver-class-name:
    url:
    username:
    password:

基本格式要求
① 大小写敏感
② 使用缩进代表层级关系
③ 相同的部分只出现一次
④ 注意空格

三、整合其他技术

整合Mybatis

导入启动器

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
</dependency>

application.yml配置

# 整合mybatis
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis:
  type-aliases-package: com.lzf.pojo
  mapper-locations: classpath:com/lzf/mapper/*.xml

整合druid

导入启动器

<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.jdbc.Driver
    # 填写你数据库的url、登录名、密码和数据库名
    url: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  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

整合Lockback

不需要额外的添加Logback的依赖,因为在spring-boot-starter或者spring-boot-starter-web中已经包含了

classpath下创建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.lzf.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.jdbc.Driver</driverClass>
                  <url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
                  <user>root</user>
                  <password>root</password>
                </dataSource>
            </connectionSource>
      </appender> -->
</configuration>

整合PageHelper

导入启动器

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.12</version>
</dependency>

在service中查询全部的方法基础上添加两句代码就OK

@Override
public PageInfo<Emp> findByPage(Integer pageNum, Integer pageSize) {
    PageHelper.startPage(pageNum, pageSize);
    List<Emp> list = empMapper.findAll();
    PageInfo<Emp> pageInfo = new PageInfo(list);
    return pageInfo;
}

整合Freemarker

导入启动器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

controller往域中放入数据

@RequestMapping("/show")
public String freemarker(Map<String,Object> map){
    map.put("name","猪八戒");
    return "/show";
}

模板引擎中取出数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    ${name}
</body>
</html>

遍历集合

<#--遍历List集合-->
<#list emps as emp>
   <tr>
       <td>${emp_index}</td>
       <td>${emp.empno}</td>
       <td>${emp.ename}</td>
       <td>${emp.job}</td>
       <td>${emp.sal}</td>
       <td>${emp.deptno}</td>
   </tr>
</#list>
<#--遍历amp集合-->
<#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>

if指令

<!--判空 ?? 和 ! -->
<#if empList??>
   <#list empList as emp>
      <tr>
         <td>${emp.mgr!'无'}</td>
      </tr>
   </#list>
</#if>
<!--隔行变色-->
<tr <#if emp_index%2 ==0 > style="background-color: gray" </#if>>
</tr>

整合Thymeleaf

导入启动器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.4.5</version>
</dependency>

添加约束

<html xmlns:th="http://www.thymeleaf.org">

controller往域中放入数据

@RequestMapping("/showIndex")
public String showIndex(Map<String,Object> map){
    map.put("msg","猪八戒");
    return "index";
}

模板引擎中取出数据

<body>
    <!--th:text属性-->
    <span th:text="${msg}"></span>
    <!--th:value-->
    <input th:value="${msg}">
</body>

遍历

<tr th:each="emp,i:${emps}">
    <td th:text="${i.index}"></td>
    <td th:text="${i.count}"></td>
    <td th:text="${i.size}"></td>
    <td th:text="${i.odd}"></td>
    <td th:text="${i.even}"></td>
    <td th:text="${i.first}"></td>
    <td th:text="${i.last}"></td>
    <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>
</tr>

th:if

<span th:if="${name}!='张三'">会显示</span>

th:href

<a th:href="@{/getParam(id=1,name='msb')}" >跳转</a>
<!-- 获取作用域值-->
<a th:href="@{/getParam(name=${stu.name},age=${stu.age})}"

th:onclick

<!--写法1:仅仅支持数字和布尔类型参数的传递,字符串不支持-->
<a href="javascript:viod(0)"  th:onclick="'del('+${emp.empno}+')'">删除</a>
<!--写法2:支持数字和文本类型的参数传递-->
<a href="javascript:void(0)" th:onclick="delEmp([[${emp.empno}]],[[${emp.ename}]])">删除</a>
<script>
    function removeEmp(empno,ename){
        var resulet =confirm("确定要删除编号为"+empno+"的"+ename);
        if(resulet){
            window.location.href="removeEmp?empno="+empno+"&ename="+ename;
        }
    }
</script>

四、项目部署打包

添加打包插件,IDEA插件创建的springboot项目就已经自带了

<!--打包插件-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>

    </plugins>
</build>

导出jar包并运行

指定打包为jar

 <packaging>jar</packaging>

使用maven package指令打包即可

SpringBoot

打成包后,可以通过dos java -jar指令直接启动运行

SpringBoot

导出war包并运

指定打包为war

<packaging>war</packaging>

排除项目中自带的所有的Tomcat插件和jsp servlet 依赖,因为这里要将项目放到一个Tomcat上运行

<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>
    <scope>provided</scope>
</dependency>

SpringBoot的启动类继承SpringBootServletInitializer,并重写configure

@SpringBootApplication
public class Springboot04Application extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Springboot04Application.class);
    }
}    

使用maven package指令打包,并将war包放到tomcat下的webapps下,启动tomcat即可。

SpringBoot

五、异常处理

  1. 设置具体的状态码页面
    在templates/下新建error文件夹,在error中新建:状态码.html的页面。例如当出现500时显示的页面为500.html

  2. 使用x进行模糊匹配
    当出现5开头状态码的错误时,显示页面可以命名为5xx.html
    当出现50开头状态码的错误时,显示页面可以命名为50x.html

  3. 统一错误显示页面
    在templates下新建error.html。如果项目中不存在具体状态码的页面或没有使用x成功匹配的页面时,显示error.html作为错误显示页面。

SpringBoot

六、拦截器

新建拦截器类。
注意:不要忘记类上注解@Component

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行拦截器");
        return true;
    }
}

配置拦截器

@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    //配置拦截器的映射
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

ass MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(“执行拦截器”);
return true;
}
}


配置拦截器

```java
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor;
    //配置拦截器的映射
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}
上一篇:spring-boot-starter-test


下一篇:自定义一个starter