SpringBoot

一、SpringBoot简介

1.1 SpringBoot介绍

  • SpringBoot基于Spring开发,SpringBoot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。换言之,它并不是用来替代Spring的解决方案,而是与Spring框架紧密结合,用于提升Spring开发者体验的工具。Spring Boot以约定大于配置的核心思想,底层默认进行了很多配置,多数Spring Boot应用只需很少的Spring 配置,同时集成了大量常用的第三方库配置(例如:Redis、MongoDB、JPA、RabbitMQ、Quartz等)。
  • Spring Boot应用中这些第三方库几乎可以零配置的开箱即用。

1.2 主要优点

  • 为所有Spring开发者更快的入门;
  • 开箱即用,提供各种默认配置来简化项目的配置;
  • 内嵌式容器简化Web项目;
  • 没有冗余代码生成和XML配置的要求;

二、第一个SpringBoot程序

到底多么简单?!

2.1 开发工具 

  • jdk1.8
  • maven 3.8.3
  • springboot 最新版
  • IDEA

官方:提供了一个快速生成的网站!IDEA集成了这个网站!

  • 可以在官网直接下载,导入到IDEA中开发;
  • 直接使用IDEA创建一个springboot项目(一般情况下);

2.2 流程步骤 

 

三、原理初探

3.1 自动配置

  • pom.xml
  • spring-boot-dependencies:核心依赖在父工程!
  • 在写入或引入一些springboot依赖时,不需指定版本,正是因为这些版本仓库!

3.2 启动器

  • SpringBoot的启动环境,例如spring-boot-starter-web会自动导入web环境所有的依赖;
  • SpringBoot会将所有功能场景,变成一个个启动器;
  • 需使用什么功能,即只需找到对应的启动器即可starter;
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

3.3 主程序

@SpringBootApplication
public class Springboot01HelloworldApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }

}

 SpringBootApplication这个类做了以下事情:

  1. 推断应用的类型是普通项目还是Web项目;
  2. 查找并加载所有可用初始化器,设置到initializers属性中;
  3. 找出所有的应用程序监听器,设置到listeners属性中;
  4. 推断并设置main方法的定义类,找到运行的主类;
  •  注解

@SpringBootApplication:标注这个类是springboot的应用,启动类下的所有资源导入

  • @Configuration:spring配置类
  • @Componet:说明这也是一个spring的组件

@SpringBootConfiguration:springboot的配置

@EnableAutoConfiguration:自动配置

  • @AutoConfigurationPackage:自动配置包
  • @Import({AutoConfigurationImportSelector.class}):自动导入选择
  • 获取候选配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
    AnnotationAttributes attributes) {
    List<String> configurations =SpringFactoriesLoader.
    loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), 
    this.getBeanClassLoader());
    Assert.notEmpty(configurations, 
   "No auto configuration classes found in META-INF/spring.factories. 
    If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}
  •  META-INF/spring.factories:自动配置的核心文件

springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里,但不一定会生效,要判断条件是否成立,只要导入了对应的start,就会有对应的启动器,有了启动器,自动装配就会生效,然后配置成功!

  • springboot在启动时,从类路径下/META-INF/spring.factories获取指定的值;
  • 将这些自动配置的类导入容器,自动配置就会生效,帮助开发者进行自动配置;
  • 以前需自动配置的文件,springboot会帮开发者完成;
  • 整合JavaEE,解决方案和自动配置的文件都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下;
  • springboot会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
  • 容器会存在很多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件,并自动配置,比如@Configuration等;

总而言之,有了这些自动配置类,免去了开发者手动编写配置文件的工作量!

四、SpringBoot Web开发

4.1 静态资源

1)在springboot中,可以使用以下方式-新建目录-处理静态资源

默认已经新建了static目录,另外两个目录需新建。

  • webjars:localhost:8080/webjars/
  • public,static,/**,resources:localhost:8080/

2)优先级

resources>static(默认)>public

4.2 首页和图标定制

1)首页设置

在resources、static(默认)或public,添加index.html即可,然后通过localhost:8080/进行访问。

注意:在templates目录下的所有页面,只能通过controller来跳转!这个需要模板引擎的支持!

 2)定制图标

在resources、static(默认)或public目录下,添加favicon.ico图标,并在yml配置文件上,设置

spring:
  mvc:
    favicon:
      enabled: false

4.3 模板引擎

 只需使用thymeleaf,导入相应的依赖即可!

并将HTML页面放在templates目录下

public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

所有的html元素都可以被thymeleaf替换接管:th:元素名,并引入

 xmlns:th="http://www.thymeleaf.org"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2 th:text="${msg}"></h2>
</body>
</html>

4.4 扩展SpringMVC

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    //视图跳转
    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        registry.addViewController("/xiao").setViewName("test");
    }
}

4.5 整合JDBC

1)pom.xml配置

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

 2)yml文件

# 数据库驱动:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源名称
    name: defaultDataSource
# 数据库连接地址 记得增加时区的配置,不然会报错
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UT
# 数据库用户名&密码:
    username: root
    password: 1234

3)测试代码

@RestController
public class JDBCController {
    @Resource
    JdbcTemplate jdbcTemplate;

    //查询数据库的所有信息
    //没有实体类,数据库中的东西,如何获取?
    @GetMapping("/userList")
    public List<Map<String,Object>> userList(){
        String sql="select * from users";
        List<Map<String,Object>> list_maps=jdbcTemplate.queryForList(sql);
        return list_maps;
    }

    //插入新记录
    @GetMapping("/addUser")
    public String addUser(){
        String sql="insert into mybatis.users(user_name,user_pwd,"+
                    "user_realname,user_img) values('YeJieJie',"+
                    "'124345','叶杰杰','5.jpg')";
        jdbcTemplate.update(sql);
        return "add-ok";
    }

    //更新记录
    @GetMapping("/updateUser/{id}")
    public String updateUser(@PathVariable("id") int id){
        String sql="update mybatis.users set user_pwd=?,user_img=?"+ 
                    "where user_id="+id;
        //封装
        Object[] objects=new Object[2];
        objects[0]="123456";
        objects[1]="8.png";
        jdbcTemplate.update(sql,objects);
        return "update-ok";
    }
    //删除记录
    @GetMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") int id){
        String sql="delete from mybatis.users where user_id=?";
        jdbcTemplate.update(sql,id);
        return "delete-ok";
    }
}

4.6 整合MyBatis框架

 1)pom.xml配置

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

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

 2)properties或yml文件

# 应用名称
spring.application.name=springboot-05-mybatis
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=1234

# 整合mybatis
mybatis.type-aliases-package=com.xsbc.pojo
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

3)测试代码

@RestController
public class UserController {

    @Resource
    private UserMapper userMapper;

    @GetMapping("/queryUserList")
    public List<User> queryUserList(){
        List<User> users=userMapper.queryUserList();
        return users;
    }
    //根据id查询用户
    @GetMapping("/queryUserById")
    public User queryUserById(){
        User user=userMapper.queryUserById(6);
        return user;
    }
    //增加一个用户
    @GetMapping("/addUser")
    public String addUser(){
        int i=userMapper.addUser(new 
            User(7, "XiaoWang", "456245", "小王", "23.png"));
        System.out.println(i);
        return "add-ok";
    }
    //修改一个用户
    @GetMapping("/updateUser")
    public String updateUser(){
        int i=userMapper.updateUser(new 
            User(12, "XiaoWang", "9876543", "小王", "21.png"));
        System.out.println(i);
        return "update-ok";
    }
    //根据id删除一个用户
    @GetMapping("/deleteUser")
    public String deleteUser(){
        int i=userMapper.deleteUser(11);
        System.out.println(i);
        return "delete-ok";
    }

}
  • 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xsbc.mapper.UserMapper">
    <select id="queryUserList" resultType="User">
        select * from users
    </select>

    <select id="queryUserById" resultType="User">
        select * from users where user_id=#{userId}
    </select>

    <insert id="addUser" parameterType="User">
        insert into users(user_name,user_pwd,user_realName,user_img)
        values(#{user_name},#{user_pwd},#{user_realName},#{user_img})
    </insert>

    <update id="updateUser" parameterType="User">
        update users set user_pwd=#{user_pwd},user_img=#{user_img}
        where user_id=#{user_id}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from users where user_id=#{user_id}
    </delete>
</mapper>

五、日志配置

5.1 日志框架

市面上的日志框架:

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j等

spring-boot-starter-logging默认采用了slf4j+logback的形式,Spring Boot也能自动配置(JUL、log4j2、logback),并简化配置。

日志门面(抽象类)日志实现(实现类)

JUL(Jakarta Commons Logging)

SLF4j(Simple Logging Facade for Java)

jboss-logging

Log4j

JUL(java.util.logging)

Log4j2

Logback

5.2 SLF4j使用

1)在IDEA中使用SLF4j

在开发过程中,日志记录方法的调用,不应该直接调用日志实现类,而是调用日志抽象层里面的方法。在项目中导入slf4j的jar和logger。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
}

2)自定义日志常用配置

  • 日志输出级别
trace追踪日志
debug调试日志
info自定义日志或信息日志
warn警告日志
error错误日志
  • 日志输出到文件
  • 日志输出格式

 日志输出到文件

  • file的name:日志的名称,可添加路径+日志名
  • file的path:路径
  • 控制台和文件输出 
file:
  name: test.log
  path: /
pattern:
  console: "%d{yyyy-MM-dd HH:mm:ss}---[%thread]%-5level %logger{50} - %msg%n"
  file: "%d{yyyy-MM-dd HH:mm:ss}---[%thread]%-5level %logger{50} - %msg%n"

 3)XML日志配置方式

xml文件定义位于resource/static目录下名,通常命名为:logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,
       将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,
         如果没有给出时间单位,默认单位是毫秒当scan为true时,
        此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,
        实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
   <!-- 定义日志的根目录 -->
   <property name="LOG_HOME" value="/app/log" />
   <!-- 定义日志文件名称 -->
   <property name="appName" value="atguigu-springboot"></property>
   <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
   <appender name="stdout" 
        class="ch.qos.logback.core.ConsoleAppender">
       <!--
       日志输出格式:
           %d表示日期时间,
           %thread表示线程名,
           %-5level:级别从左显示5个字符宽度
           %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
           %msg:日志消息,
           %n是换行符
       -->
       <layout class="ch.qos.logback.classic.PatternLayout">
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} 
            [%thread] %-5level %logger{50} - %msg%n</pattern>
       </layout>
   </appender>

   <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
   <appender name="appLogAppender" 
        class="ch.qos.logback.core.rolling.RollingFileAppender">
       <!-- 指定日志文件的名称 -->
       <file>${LOG_HOME}/${appName}.log</file>
       <!--
       当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
       TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,
       既负责滚动也负责出发滚动。
       -->
       <rollingPolicy 
        class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!--
           滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
           %i:当文件大小超过maxFileSize时,按照i进行文件滚动
           -->
           <fileNamePattern>
                ${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log
            </fileNamePattern>
           <!-- 
           可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。
           假设设置每天滚动,且maxHistory是365,则只保存最近365天的文件,
           删除之前的旧文件。注意,删除旧文件是,
           那些为了归档而创建的目录也会被删除。
           -->
           <MaxHistory>365</MaxHistory>
           <!-- 
           当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 
           注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,
           必须配置timeBasedFileNamingAndTriggeringPolicy
           -->
           <timeBasedFileNamingAndTriggeringPolicy     
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
               <maxFileSize>100MB</maxFileSize>
           </timeBasedFileNamingAndTriggeringPolicy>
       </rollingPolicy>
       <!-- 日志输出格式: -->     
       <layout class="ch.qos.logback.classic.PatternLayout">
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] 
            [ %logger{50} : %line ] - %msg%n</pattern>
       </layout>
   </appender>

   <!-- 
       logger主要用于存放日志对象,也可以定义日志类型、级别
       name:表示匹配的logger类型前缀,也就是包的前半部分
       level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
       additivity:作用在于children-logger是否使用 
            rootLogger配置的appender进行输出,
       false:表示只用当前logger的appender-ref,true:
       表示当前logger的appender-ref和rootLogger的appender-ref都有效
   -->
   <!-- hibernate logger -->
   <logger name="com.atguigu" level="debug" />
   <!-- Spring framework logger -->
   <logger name="org.springframework" level="debug" 
        additivity="false"></logger>



   <!-- 
   root与logger是父子关系,没有特别定义则默认为root,
    任何一个类只会和一个logger对应,
   要么是定义的logger,要么是root,判断的关键在于找到这个logger,
    然后判断这个logger的appender和level。 
   -->
   <root level="info">
       <appender-ref ref="stdout" />
       <appender-ref ref="appLogAppender" />
   </root>
</configuration> 

5.3 AOP结合自定义注解实现日志统一处理

  • 引入aop依赖
  • 自定义注解
  • 自定义切面类

常用的注解:

@Aspect标明这是一个切面类
@Componet标明这是一个bean
@Pointcut("annotation(com.xsbc.annotation.SamleLog")定义切入点为自定义的注解
@before前置通知,在一个方法执行之前被调用
@after在方法执行之后调用的通知,无论方法执行是否成功
@after-returning仅当方法执行成功之后通知
@after-throwing在方法抛出异常退出时执行的通知
@around在方法执行之前和之后执行的通知

1)引入AOP依赖

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

2)自定义注解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleLog {
    String value() default "";
}

3)自定义切面类

@Aspect
@Component
public class LogAspect {
    private final Logger logger=LoggerFactory.getLogger(LogAspect.class);
    
    @Pointcut("@annotation(com.xsbc.annotation.SampleLog)")
    public void samplePointCut(){
        //签名,可以理解成这个切入点的一个名称
    }
    
    @Before("samplePointCut()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes=(ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request=attributes.getRequest();
        // 获取url,请求方法,ip地址,类名以及方法名,参数
        logger.info("url={},method={},ip={},args={}",request.getRequestURI(),
                request.getMethod(),request.getRemoteAddr(),
                joinPoint.getArgs());
    }
    
    @AfterReturning("samplePointCut()")
    public void printLog(JoinPoint joinPoint){
        MethodSignature signature=(MethodSignature) joinPoint.getSignature();
        Method method=signature.getMethod();
        SampleLog sampleLog=method.getAnnotation(SampleLog.class);
        String value=null;
        if(sampleLog!=null){
            value=sampleLog.value();
        }
        logger.info(new Date()+"------"+value);
    }
}

4)Controller类

@RestController
@RequestMapping("/Log")
public class LogController {
    Logger logger=LoggerFactory.getLogger(LogController.class);

    @GetMapping("/testLog")
    @SampleLog("测试AOP日志")
    public void testLog(){
        logger.trace("这是trace级别的日志");
        logger.debug("这是debug级别的日志");
        logger.info("这是正常自定义的日志");
        logger.warn("这是trace级别的日志");
        logger.error("这是error级别的日志");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值