SpringBoot

项目:Ubuntu--eclipse--springbootInstance1

学习路线图:
0.jpg

SpringBoot简介

- 第一个SpringBoot程序
- 原理初探
- yaml语法
- 多环境配置、配置文件位置
- 配置文件和spring.factories
- 配置文件字段与Properties类属性映射
- @Conditional注解
- 查看所有生效、没生效、排除配置类

[SpringBoot web开发](#SpringBoot web开发)

- 静态资源相关
- 自定义首页、标签页图标
- Thymeleaf模板引擎
- 语法
- 拓展springmvc

网站实现

- 业务逻辑处理
数据库、安全相关
- [整合JDBC](#整合JDBC)
- [SpringSecutiry](#SpringSecutiry)

其他

[eclipse使用Resource Bundle Editor实现属性集编写](#eclipse使用Resource Bundle Editor实现属性集编写)


SpringBoot简介

为了简化SSM整合的配置文件相关的复杂性,spring进行了整合,提出了springBoot,其理念就是约定大于配置。

主要优点

  • 对开发者来说可以更快入门
  • 开箱即用:提供各种默认配置来简化项目配置。
  • 内嵌式容器(如tomcat)简化Web项目
  • 没有冗余代码生成和xml配置的要求

微服务介绍

​ 微服务时一种架构风格,它规定我们在开发一个应用时,应用必须构建成一系列组件的组合(每个组件提供一个小服务);可以通过http方式进行互通。

如何构建微服务:

​ 一个大型系统的微服务架构,就像一个复杂交织的网络,每个节点就是一个功能元素,他们各自完成特定的职责,然后通过http相互请求、调用。

​ 如电商系统:查缓存、连数据库、浏览页面、结账、支付等服务,被微化成一个个独立的微服务,这些微服务共同构建了一个完整而庞大的系统。

​ 当想要修改其中一个服务时,并不需要如All in one类型的项目,停止、重启。而只需要更新一个服务功能,空挡期可以选择一个备用的接口或者返回某个页面来进行提示。

​ 但这样庞大的系统架构给部署和运维带来了很大的难度,于是,spring为我们简化,并提供了全套的微服务架构、产品:

  • SpringBoot:帮助快速构建一个应用:包含一个个功能独立的微服务应用单元。
  • Spring Cloud:完成大型分布式网络服务的调用。-
  • Spring Cloud Data Flow:在分布式中间,进行流式数据计算、批处理。
  • spring为我们罗列了构建大型分布式应用,整个流程的方案。
2.jpg

第一个SpringBoot程序

第一种--直接在springboot官网配置好,下载下来,解压缩即可。
第二种--直接在IDEA创建一个springBoot项目(其帮我们去官网下载)

​ 只要创建了项目,就可以直接运行了。http://localhost:8008/也可以启动,显示springBoot提供的提示信息。(使用tomcat作为默认嵌入式容器)

​ 然后可以直接创建Controller类了,并不需要配置web.xml(DispatcherServlet)、Springmvc.xml等文件了,springboot已经帮我们配置了。

application.properties

​ 里面已经包含springboot默认配置的很多依赖了。最主要的是该项目的父项目,即spring-boot-starter-parent,在其内部进行了约定的默认配置。(约定大于配置)

部分配置说明:

​ 首先:springboot已经帮我们配置好了所有东西,此处说一些自定义配置之类的。

  • 自定义banner图像:即console启动时显示的图像,可以自定义。

    ①去网上搜:springboot banner,然后下载

    ②在resources文件夹下,即application.properties同目录,创建一个banner1.txt文件,将上述复制或下载的banner传入。

  • tomcat port号配置:

    • 直接在application.properties里面写:port=8081即可。

原理初探

自动配置的原理:

pom.xml

  • 核心依赖在parent父工程中:parent项目里中还有一个dependencies父项目,其包含了所有依赖。
  • 依赖不需要指定版本号:因为有这些版本在父依赖仓库里全部配置了properties。(几乎包含所有需要的)

启动器(starter)

  • springboot将功能相近的API,整合成一个启动包。如spring-boot-starter-web,他就会帮我们自动导入web环境所有的依赖。
  • 我们需要相应功能,只需要指定相应启动器。(在官网可以查询:连接

主程序(主启动类)

说明:springboot所有的自动配置,都在启动类中被扫描并加载:spring.factories所有的自动配置类都在这里面。但是不一定生效,只有条件成立才会生效(导入了对应的start,有了对应的启动器,自动装配才会生效,才会配置成功)

大概流程

1.springboot启动时,从类路径下 /META-INF/spring.factories获取指定的配置信息list,及其中所有包名

2.将这些自动配置的类添加依赖(pom.xml中添加starter依赖),配置就会生效,进行自动配置。

3.以前我们需要配置的东西,现在springboot帮我们做了。

4.整合了javaEE、解决方案和自动配置的东西都在spring-boot-autoconfiguration-2.2.6.RELEASE.jar下

5.他会把所有需要导入的组件,以全限定类名的方式返回,这些组件就会被添加到容器中。

6.容器中也会存在非常多的xxxAutoConfiguration的类名,这些类给容器中导入了这个场景所需要的所有组件(@Bean返回值),并自动配置,免去我们手动配置文件的时间。

  • 标注了@SpringbootApplication的类,作为应用的主入口。

    @SpringbootApplication注解包含了多个注解,下面说其中两个:

    • @SpringBootConfiguration
      • @Configuration:spring配置注解
        • @Component:说明其本质是组件类
    • @EnableAutoConfiguration:自动配置
      • @AotuComfiguration:自动配置包
        • @Import(AutoConfigurationPackages.Registrar.class):导入注册
      • @Import(AutoConfigurationImportSelector.class):导入选择器
  • main方法:

    ​ 在main中,SpringApplication.run(XXApplication.class,args),反射创建该类。

主启动类的运行分析(springApplication.run(..))

SpringApplication.run(MySpringBootApplication.class, args);的四个职责

  • 判断应用的类型是普通的项目还是web项目

  • 查找并加载所有可用初始化器,设置到initializers属性中

  • 找出所有应用程序监听器,设置到listeners属性中

  • 推断并设置main方法的定义类,找到运行的主类。

3.jpg

yaml语法

说明:springboot使用全局的配置文件,配置文件的名称固定:

  • application.properties
    • 语法:key=value
  • application.yml (*官方推荐)
    • 语法:key: 空格 value 如:port: 8081
    • 注意空格必须存在,格式是规定的。

职责:修改springboot自动配置的默认值,其已经在底层给我们自动配置了,我们可以通过设定值,来进行自定义。

基本语法

#代表注释,yaml对空格要求严格。
#强大功能:可以注入到我们的配置类中

#普通的key-value
name: 老孙

#支持存放对象
student:
 name: 老孙
 age: 24
    
#行内写法
student: {name: MrSun,age: 24}

#数组
pets:
 - cat
 - dog
 - pig
    
#数组行内写法
pets: [cat,dog,pig]
使用yaml对对象参数注入

.yml文件中:

person:
 name: mySun
 age: 24
 sex: G
# birthday: 1996/4/6  其类注入失败,猜测是不能对该字符串类型,进行Date自动转换。 
 birthday: 1996-4-6
 map: {k1: v1,k2: v2}
 list:
  - code
  - music
  - girl
 dog:
  name: 仔仔
  age: 3

实体类中:

@Component
@ConfigurationProperties("person")
public class Person {
    String name;
    int age;
    char sex;
    Date birthday;
    Map<String,Object> map;
    List<String> list;
    Dog dog;
    ...
}

说明:一般用于JavaConfig配置类里面。

@PropertySource

  • 用properties也可以进行对象属性注入,但是更繁琐。

@PropertySource("classpath:custom.properties")注解类,在类中,每个属性进行注释@Value("${name}")

  • yaml文件中,可以使用spring的EL表达式,如:

    person:
     name: mySun.${random.int}     //随机整数
     age: 2${random.int}
     ...
     dog: ${person.hello:hello}_狗   //指定默认值形式,若hello存在,则结果:${person.hello}_狗
     name: 仔仔                     //如果不存在,则:hello_狗
     age: 3
    
yaml和properties的区别
6.jpg
  • 松散绑定:即yaml中的值,可以与实体类属性名字格式不同,如:last-name 和 lastName。其可以赋值成功

  • JSR303数据校验:在这个字段增加一层过滤器验证,验证合法性等。

    格式:类前注释@Validated,然后变量前注释以下内容:

4.jpg
  • 复杂类型封装:yaml可以封装对象

多环境配置、配置文件位置

说明:配置文件规定的几种位置,可以从SpringBoot官网Guide里找到,优先级渐低:

5.jpg

多环境配置:

​ 在真实项目开发中,会有多种环境,如test、development等,springboot支持多环境配置,但默认读取application.properties配置文件

激活其他环境配置文件:

  • properties实现

​ 在主配置文件applicaiton.properties中:键入:spring.profiles.active=test,其就会选择application-test.properties来运行。

  • yaml实现:(推荐)

    直接将三个环境的配置,写在一个yaml中:

    server:
     port: 8081
    spring:
     profile:
      active: dev
      
      
    ---
    server:
     port: 8082
    spring:
     profile: test
      
    ---
    server:
     port: 8083
    spring:
     profile: dev
    

配置文件和spring.factories

spring.factories

​ spring.factories中,包含了多个配置环境,如Listeners、Processors等,每个配置环境包含了诸多相关配置类。

XXXproperties类:

​ 我们在配置文件中自定义的字符串,如spring.mvc.dateFormat: yyyy-MM-dd,其是更换(注入)了WebMvcProperties属性类的默认值,该类主要供WebMvcAutoConfiguration配置类使用。

​ 意味我们在application.propertiesapplication.yaml中写的属性,其必须已经由spring整合了默认配置类,否则并不会生效。

​ 导入的每个(springboot已配置)依赖包,都有一个...properties类,我们更改application.yaml也就是更改其类属性。

了解的原因

​ 这样,我们能知道在配置文件中,我们能写什么东西,如下述具体配置类的实例中,其属性我们都可以指定,如其引用成员变量Encoding类:

​ 我们可以在文件中编写:spring.http.encoding.XXX配置encoding中的属性。

配置文件字段与Properties类映射

注解:@ConfigurationProperties

​ 在配置类前注解该类(spring也是这样做的),然后value\prefix传入配置文件中的对应的字符串即可。如:

@ConfigurationProperties(prefix = "spring.mvc")

spring.factories位置

2.2.6.RELEASE/spring-boot-autoconfigure-2.2.6.RELEASE.jar/META-INF/spring.factories

某个具体配置类实例

下述是HttpEncodingAutoAconfiguration的类体,其属于一个配置环境。

7.jpg

第一个注解:声明该类是配置类就不说了。

第二个注解:其自动配置属性,点进HttpProperties.class,其注解了@ConfigurationProperties,如下

8.jpg

​ 其是通过配置文件.yaml中的spring.http对应的值,给其属性(成员变量)进行自动注入。

第三~五个注解:决定该配置类是否生效:根据三个注解的条件成立与否。

@Conditional注解

9.jpg
查看所有生效、没生效、排除配置类

在配置文件application.xxx中输入:debug: true。然后启动即可在console中看到。

自定义starter

步骤:

①创建XXXconfiguration类,

②创建XXXProperties类,

③将两者放入org.springframework.boot.autoconfigure包下。


SpringBoot web开发

说在前面:springboot帮我们配置了什么东西?我们能不能修改?可以修改哪些?能不能拓展?

  • 上述都是可以的。
  • xxxxAutoConfigurationxxx:自动配置类,可以像容器中自动配置Bean。
  • xxxxProperties:自动配置类,装配配置文件中自定义的一些内容。

静态资源

使用以下方式处理静态资源:

  • webjars:百度搜,并去官网,可以找到很多的jar,并有依赖。将其导入pom.xml即可。然后就可以在浏览器中输入指定url,得到导入的webjars包的文件。

  • 将资源放到指定位置:

    ​ 源码中声明的classpath:/**/resources/statis(默认创建)、/public。(优先级递减;classpath是默认创建的resources文件夹,application.yaml也是放在其内;)

    如在浏览器中输入:localhost:8080/myjsp,其会到上述四个目录下查找myjsp,当url存在目录时,也会递归搜寻目录。

templates目录

说明:对于该目录下的所有页面,只能通过我们的@Controller来进行跳转。(利用配置的视图解析器)

注意:需要模板引擎的支持,要导入thymeleaf依赖包。

自定义首页

​ 将index.html自定义文件放到资源目录下即可。

​ 注意,若要放在/templates,即使用Controller来返回index,则需要先配置thymeleaf依赖。

自定义浏览器标签页图标

在最新版本好像不行了,在2.1.7版本是可以的:

​ ①直接在/resources、/static、/public、/templates(需先如上调用thymeleaf)中的一个目录下,放一个favicon.ico图像即可。

​ ②在application.yaml中:spring.mvc.favicon.enabled=false;关闭默认图标


Thymeleaf模板引擎

模板引擎:

​ 如jsp也是一个模板引擎,如下示意图:

10.jpg

补充:Thymeleaf模板引擎是SpringBoot推荐的。

导入配置

​ 所以需要我们手动导入thymeleaf依赖,可以在Spring官网ref文档查询

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>

补充:可以去父项目dependencies里面看版本是不是比较旧,如果是,则需要在<properties>里面配置版本号。查找后我看到版本还是满新的,官方也就多出了一个snapshot版本。

使用thymeleaf

html中:

①导入thymeleaf命名空间。(thymeleaf官方文档):

<!DOCTYPE html>
<!-- 导入命名空间-->
<html xmlns:th="http://www.thymeleaf.org">

  <head>
    <title>Good Thymes Virtual Grocery</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all" 
          href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
  </head>

  <body>
  
    <p th:text="#{home.welcome}">Welcome to our grocery store!</p>
  
  </body>

</html>

Thymeleaf语法

  • Simple expressions:
    • Variable Expressions: ${...}
    • Selection Variable Expressions: *{...}
    • Message Expressions: #{...} (国际化)
    • Link URL Expressions: @{...}
    • Fragment Expressions: ~{...}
  • Literals(字面值)
    • Text literals: 'one text', 'Another one!',…
    • Number literals: 0, 34, 3.0, 12.3,…
    • Boolean literals: true, false
    • Null literal: null
    • Literal tokens: one, sometext, main,…
  • Text operations:
    • String concatenation: +
    • Literal substitutions: |The name is ${name}|
  • Arithmetic(算术) operations:
    • Binary operators: +, -, *, /, %
    • Minus sign (unary operator): -
  • Boolean operations:
    • Binary operators: and, or
    • Boolean negation (unary operator): !, not
  • Comparisons and equality:
    • Comparators: >, <, >=, <= (gt, lt, ge, le)
    • Equality operators: ==, != (eq, ne)
  • Conditional operators:
    • If-then: (if) ? (then)
    • If-then-else: (if) ? (then) : (else) (*)
    • Default: (value) ?: (defaultvalue)
  • Special tokens:
    • No-Operation: _

All these features can be combined and nested:

'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
说明:

​ 所有的html元素都可以被html接管,需要在标签对应属性中,添加th:前缀,如要:

<div th:text="${msg}"></div>
注意:

​ 只有属性标注了th:,并在对应value中,才可以使用thymeleaf的语法,否则不生效。

对应属性的功能

Order Feature Attributes
1 Fragment inclusion th:insert th:replace
2 Fragment iteration th:each
3 Conditional evaluation th:if th:unless th:switch th:case
4 Local variable definition th:object th:with
5 General attribute modification th:attr th:attrprepend th:attrappend
6 Specific attribute modification th:value th:href th:src ...
7 Text (tag body modification) th:text th:utext
8 Fragment specification th:fragment
9 Fragment removal th:remove

数组遍历语法

<!-- 第一种写法(建议),字面值即普通字符串用'',然后用+号连接 -->
    <h4 th:each="fruit:${fruits}" th:text="${fruit}+':推荐写法'"></h4>
<!-- 第二种写法 -->
    <!-- <h4  th:each="fruit:${fruits}">[[${fruit}]]:第二种写法</h4> -->

拓展springmvc

详细看官方文档:这里

步骤:
  • ①创建自定义配置类,其实现WebMvcConfigurer接口。
  • ②-1:可以直接重载该接口的方法,并编写自定义代码。
  • ②-2:在配置类中创建想要自定义的mvc组件类,并实现其接口,如下的ViewResolver
  • ③将组件放入spring容器中。可以如下用@Bean方式,或者用BeanFactory等方式。

拓展视图解析器:

11.jpg

网站实现

前端模板

说明:可以直接下载网上的前端模板。

框架:bootstrap、Layui、semantic-ui、xadmin(专门后端)等,可以适当学一下这些模板知识:

  • 栅格系统:将ui分成多少份
  • 导航栏:
  • 侧边栏:
  • 表单:
13.jpg

首页配置

说明:如果是从网上下载模板,我们需要将静态资源导入我们的模板引擎,如Thymeleaf。

步骤:

①从网上、或者前端得到bootstrap模板,用于View视图

②导入thymeleaf

​ 主要作用是以后计算我们修改了根目录,静态资源连接也不会影响,因为是绝对路径。而默认的html是相对路径。

③修改所有的静态资源(html)中部分元素的属性:(语法参考thymeleaf语法)

  • <link><a>href

  • ​ 使用thymeleaf接管:如本地资源索引:href="/../.." th:href="@{/../..}"

页面国际化(locale:地区化)

说明:最主要是提供页面的多种语言访问机制,根据传入的请求头的语言,一般是浏览器设置。或者也可以在页面添加语言按钮,再自定义LocaleResolver进行处理。

步骤:

①对需要国际化页面,配置属性文件,在resources下建立i18n目录。

12.jpg

②在主配置文件中添加:spring.messages.basename=i18n/login

③在前端切换语言标签中,将属性ref修改,每个语言对应一个语言请求头(可以用url传递),如:zh_CN、en-US。

④自定义配置地区化解析器:

​ springboot会检查是否有自定义的LocaleResolver,如果有则使用该解析器,否则是默认解析器,其是按照浏览器发送的accept-language来进行处理,所以不支持多种语言切换,需要我们自己配置。

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        System.out.println("resolverLocale执行了");
        String lang = (String) request.getParameter("l");

        Locale locale = Locale.getDefault();
        if (!StringUtils.isEmpty(lang)) {
                String[] ofLang =  lang.split("_");         
                locale = new Locale(ofLang[0],ofLang[1]);   
        }
        // TODO Auto-generated method stub
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        // TODO Auto-generated method stub
    }

⑤将其添加到自定义的WebMvcConfiguration实现类中

    //国际化:自定义本地化解析器
    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocaleResolver();
    }

业务逻辑处理

ubuntu--springbootInstance01

说明:View上一个<a>连接,对应着一个Controller。该Controller可能会调用Service(其引用了dao),实现一个视图--数据库--视图的全程访问。

​ 如:统计网页上,一个label对应着【员工信息】,点击这个label时,其会被服务器中对应Controller拦截,并调用对应Service组件,该组件又调用了DAO组件,实现对数据层的访问。

​ 然后Controller处理结果,并返回字符串,让DispatcherServlet去将对应视图返回到浏览器。

springboot练习项目.xmind


数据库、安全相关

整合JDBC(默认数据源Hikari)

[JdbcTemplate + Druid 数据源](#JdbcTemplate + Druid 数据源)

整合mybatis-spring-boot

14.jpg

整合JDBC

数据源选择

说明:现在最好的数据源:

  • Hikari:号称JavaWeb当前速度最快的数据源。相比传统的jdbc、c3p0、DBCP(数据库连接池)、tomcat等连接池更优秀。(springboot默认)

  • Druid:ali开源,集成了日志,易于获取数据库访问统计信息。

整合流程

①依赖:

        <!-- 导入jdbc依赖,spring为我们提供了jdbcTemplate封装类,可以比原生jdbc更便捷 -->
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

②Application配置文件:

spring:
 datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/TestBase
    username: sun
    password: sunlin

③使用:

完成上述之后,可以直接使用了,jdbcTemplate对数据库具有不错的封装:

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Test
    void JdbcTemplateTest() throws SQLException {
        //spring提供的jdbcTemplate,非常简单的就完成了。
        List<Map<String, Object>> resultList = jdbcTemplate.queryForList("select * from subjects;");
        System.out.println(resultList);
    }

原生jdbc:

    @Autowired
    DataSource dataSource;
    
    void rawJdbcTest() throws SQLException {
        //原生jdbc测试
        //建立sql语句
        String sqlString="select * from subjects;";
        //从数据库得到连接
        PreparedStatement ss =  dataSource.getConnection().prepareStatement(sqlString);
        //发送语句并接受结果
        ResultSet rs = ss.executeQuery();
        int i=0;
        while(rs.next()) {          
            System.out.println("结果==>"+i+" "+rs.getInt("id"));
            System.out.println("结果==>"+i+" "+rs.getInt("uid"));
            System.out.println("结果==>"+i+" "+rs.getString("enjoy"));
            System.out.println("结果==>"+i+" "+rs.getString("name"));
            System.out.println("结果==>"+i+" "+rs.getInt("grade"));
            i++;
        }
        ss.close();

JdbcTemplate + Druid 数据源

CSDN文章:比较完美的Druid+log4j2配置:比较好,完全配置,可以去看看。

github开源Druid

①依赖:

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    <dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <!--移除自带日志管理 -->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <!--移除自带web日志管理 -->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

②配置:

application.yaml:替换默认数据源:

spring:
 datasource:
     #尝试用阿里的Druid数据源,若没下面语句,则是使用默认的Hikari
  type: com.alibaba.druid.pool.DruidDataSource
  druid:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/TestBase?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
    username: sun
    password: sunlin
    #下面的配置,是Druid超越其他数据源的优势:说明:filters:监控统计拦截器{stat:监控统计、log4j:日志记录、wall:防御sql注入},只需要配置即可生效。 log4j记得导入
    filters: stat,wall,log4j2
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    #若需要配置其他数据源参数,无论是Hikari、Druid,都直接添加即可,如:
    #initialSize: 5等等

​ 说明:还可以配置一些数据源的参数,可以直接网上找,然后复制黏贴到配置文件:datasource下即可。

log4j2.xml:

点这里到结尾

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="1800">

    <Properties>
        <!-- ==============================================公共配置============================================== -->
        <!-- 设置日志文件的目录名称 -->
        <property name="logFileName">IotEmLog</property>

        <!-- 日志默认存放的位置,可以设置为项目根路径下,也可指定绝对路径 -->
        <!-- 存放路径一:通用路径,window平台 -->
        <property name="basePath">f:/Java/project/logs/${logFileName}</property>
        <!-- 存放路径二:web工程专用,java项目没有这个变量,需要删掉,否则会报异常,这里把日志放在web项目的根目录下 -->
        <!-- <property name="basePath">${web:rootDir}/${logFileName}</property> -->
        <!-- 存放路径三:web工程专用,java项目没有这个变量,需要删掉,否则会报异常,这里把日志放在tocmat的logs目录下 -->
        <!--<property name="basePath">${sys:catalina.home}/logs/${logFileName}</property>-->


        <!-- 控制台默认输出格式,"%-5level":日志级别,"%l":输出完整的错误位置,是小写的L,因为有行号显示,所以影响日志输出的性能 -->
        <property name="console_log_pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level]: %l - %m%n</property>
        <!-- 日志文件默认输出格式,不带行号输出(行号显示会影响日志输出性能);%C:大写,类名;%M:方法名;%m:错误信息;%n:换行 -->
        <!-- <property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %C.%M - %m%n</property> -->
        <!-- 日志文件默认输出格式,另类带行号输出(对日志输出性能未知);%C:大写,类名;%M:方法名;%L:行号;%m:错误信息;%n:换行 -->
        <property name="log_pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level]: %C.%M[%L line] - %m%n</property>

        <!-- 日志默认切割的最小单位 -->
        <property name="every_file_size">20MB</property>
        <!-- 日志默认输出级别 -->
        <property name="output_log_level">DEBUG</property>

        <!-- ===========================================所有级别日志配置=========================================== -->
        <!-- 日志默认存放路径(所有级别日志) -->
        <property name="rolling_fileName">${basePath}/all.log</property>
        <!-- 日志默认压缩路径,将超过指定文件大小的日志,自动存入按"年月"建立的文件夹下面并进行压缩,作为存档 -->
        <property name="rolling_filePattern">${basePath}/%d{yyyy-MM}/all-%d{yyyy-MM-dd-HH}-%i.log.gz</property>
        <!-- 日志默认同类型日志,同一文件夹下可以存放的数量,不设置此属性则默认为7个,filePattern最后要带%i才会生效 -->
        <property name="rolling_max">500</property>
        <!-- 日志默认同类型日志,多久生成一个新的日志文件,这个配置需要和filePattern结合使用;
                如果设置为1,filePattern是%d{yyyy-MM-dd}到天的格式,则间隔一天生成一个文件
                如果设置为12,filePattern是%d{yyyy-MM-dd-HH}到小时的格式,则间隔12小时生成一个文件 -->
        <property name="rolling_timeInterval">12</property>
        <!-- 日志默认同类型日志,是否对封存时间进行调制,若为true,则封存时间将以0点为边界进行调整,
                如:现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am -->
        <property name="rolling_timeModulate">true</property>

        <!-- ============================================Info级别日志============================================ -->
        <!-- Info日志默认存放路径(Info级别日志) -->
        <property name="info_fileName">${basePath}/info.log</property>
        <!-- Info日志默认压缩路径,将超过指定文件大小的日志,自动存入按"年月"建立的文件夹下面并进行压缩,作为存档 -->
        <property name="info_filePattern">${basePath}/%d{yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz</property>
        <!-- Info日志默认同一文件夹下可以存放的数量,不设置此属性则默认为7个 -->
        <property name="info_max">100</property>
        <!-- 日志默认同类型日志,多久生成一个新的日志文件,这个配置需要和filePattern结合使用;
                如果设置为1,filePattern是%d{yyyy-MM-dd}到天的格式,则间隔一天生成一个文件
                如果设置为12,filePattern是%d{yyyy-MM-dd-HH}到小时的格式,则间隔12小时生成一个文件 -->
        <property name="info_timeInterval">1</property>
        <!-- 日志默认同类型日志,是否对封存时间进行调制,若为true,则封存时间将以0点为边界进行调整,
                如:现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am -->
        <property name="info_timeModulate">true</property>

        <!-- ============================================Warn级别日志============================================ -->
        <!-- Warn日志默认存放路径(Warn级别日志) -->
        <property name="warn_fileName">${basePath}/warn.log</property>
        <!-- Warn日志默认压缩路径,将超过指定文件大小的日志,自动存入按"年月"建立的文件夹下面并进行压缩,作为存档 -->
        <property name="warn_filePattern">${basePath}/%d{yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz</property>
        <!-- Warn日志默认同一文件夹下可以存放的数量,不设置此属性则默认为7个 -->
        <property name="warn_max">100</property>
        <!-- 日志默认同类型日志,多久生成一个新的日志文件,这个配置需要和filePattern结合使用;
                如果设置为1,filePattern是%d{yyyy-MM-dd}到天的格式,则间隔一天生成一个文件
                如果设置为12,filePattern是%d{yyyy-MM-dd-HH}到小时的格式,则间隔12小时生成一个文件 -->
        <property name="warn_timeInterval">1</property>
        <!-- 日志默认同类型日志,是否对封存时间进行调制,若为true,则封存时间将以0点为边界进行调整,
                如:现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am -->
        <property name="warn_timeModulate">true</property>

        <!-- ============================================Error级别日志============================================ -->
        <!-- Error日志默认存放路径(Error级别日志) -->
        <property name="error_fileName">${basePath}/error.log</property>
        <!-- Error日志默认压缩路径,将超过指定文件大小的日志,自动存入按"年月"建立的文件夹下面并进行压缩,作为存档 -->
        <property name="error_filePattern">${basePath}/%d{yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz</property>
        <!-- Error日志默认同一文件夹下可以存放的数量,不设置此属性则默认为7个 -->
        <property name="error_max">100</property>
        <!-- 日志默认同类型日志,多久生成一个新的日志文件,这个配置需要和filePattern结合使用;
                如果设置为1,filePattern是%d{yyyy-MM-dd}到天的格式,则间隔一天生成一个文件
                如果设置为12,filePattern是%d{yyyy-MM-dd-HH}到小时的格式,则间隔12小时生成一个文件 -->
        <property name="error_timeInterval">1</property>
        <!-- 日志默认同类型日志,是否对封存时间进行调制,若为true,则封存时间将以0点为边界进行调整,
                如:现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am -->
        <property name="error_timeModulate">true</property>

        <!-- ============================================控制台显示控制============================================ -->
        <!-- 控制台显示的日志最低级别 -->
        <property name="console_print_level">INFO</property>

    </Properties>

    <!--定义appender -->
    <appenders>
        <!-- =======================================用来定义输出到控制台的配置======================================= -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 设置控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="${console_print_level}" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 设置输出格式,不设置默认为:%m%n -->
            <PatternLayout pattern="${console_log_pattern}"/>
        </Console>

        <!-- ================================打印root中指定的level级别以上的日志到文件================================ -->
        <RollingFile name="RollingFile" fileName="${rolling_fileName}" filePattern="${rolling_filePattern}">
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${rolling_timeInterval}" modulate="${warn_timeModulate}"/>
                <SizeBasedTriggeringPolicy size="${every_file_size}"/>
            </Policies>
            <!-- 设置同类型日志,同一文件夹下可以存放的数量,如果不设置此属性则默认存放7个文件 -->
            <DefaultRolloverStrategy max="${rolling_max}" />
        </RollingFile>

        <!-- =======================================打印INFO级别的日志到文件======================================= -->
        <RollingFile name="InfoFile" fileName="${info_fileName}" filePattern="${info_filePattern}">
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${info_timeInterval}" modulate="${info_timeModulate}"/>
                <SizeBasedTriggeringPolicy size="${every_file_size}"/>
            </Policies>
            <DefaultRolloverStrategy max="${info_max}" />
            <Filters>
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
        </RollingFile>

        <!-- =======================================打印WARN级别的日志到文件======================================= -->
        <RollingFile name="WarnFile" fileName="${warn_fileName}" filePattern="${warn_filePattern}">
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${warn_timeInterval}" modulate="${warn_timeModulate}"/>
                <SizeBasedTriggeringPolicy size="${every_file_size}"/>
            </Policies>
            <DefaultRolloverStrategy max="${warn_max}" />
            <Filters>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
        </RollingFile>

        <!-- =======================================打印ERROR级别的日志到文件======================================= -->
        <RollingFile name="ErrorFile" fileName="${error_fileName}" filePattern="${error_filePattern}">
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${error_timeInterval}" modulate="${error_timeModulate}"/>
                <SizeBasedTriggeringPolicy size="${every_file_size}"/>
            </Policies>
            <DefaultRolloverStrategy max="${error_max}" />
            <Filters>
                <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
        </RollingFile>
        <!--druid的日志记录追加器-->
        <RollingFile name="druidSqlRollingFile" fileName="${basePath}/druid-sql.log"
                     filePattern="${basePath}/%d{yyyy-MM}/druid-sql-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="${log_pattern}"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>
    </appenders>

    <!--定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!-- 设置打印sql语句配置开始,以下两者配合使用,可以优化日志的输出信息,减少一些不必要信息的输出 -->
        <!-- 设置java.sql包下的日志只打印DEBUG及以上级别的日志,此设置可以支持sql语句的日志打印 -->
        <logger name="java.sql" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!-- 设置org.mybatis.spring包下的日志只打印WARN及以上级别的日志 -->
        <logger name="org.mybatis.spring" level="WARN" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!-- 设置org.mybatis.spring包下的日志只打印WARN及以上级别的日志 -->
        <logger name="org.springframework" level="WARN" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!-- 设置org.mybatis.spring包下的日志只打印WARN及以上级别的日志 -->
        <logger name="com.qfx.workflow.service" level="WARN" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!-- 设置打印sql语句配置结束 -->
        <!--记录druid-sql的记录-->
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>

        <!--建立一个默认的root的logger-->
        <root level="${output_log_level}">
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="Console"/>
            <appender-ref ref="InfoFile"/>
            <appender-ref ref="WarnFile"/>
            <appender-ref ref="ErrorFile"/>
        </root>
    </loggers>
</configuration>
log4j.xml结尾

③使用:和之前一样,就可以直接使用了。非常轻松。

整合mybatis-spring-boot

步骤:

1:导入包:

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

2:配置文件

  • 首先是application.yaml,在其内部添加数据源。
  • 然后配置mybatis的mapper(dao)接口别名、映射文件.xml位置(如果是纯注解则不需要)

3:编写sql,可以在对应类名的mapper.xml中,也可以直接在接口中。(对应接口类注释为@Repository、@Mapper

4:Controller调用Service层

5:Service业务层调用dao(Mapper)对象。


SpringSecutiry

说明:其是spring提供的一个髙定制性的认证和访问权限框架。

权限:

  • 功能权限:如博客中,游客不能写博客,只有登录用户能写。
  • 访问权限:如游客、普通用户不能访问后台。
  • 菜单权限:
  • ...

之前实现:一般用拦截器和过滤器。

15.jpg

其他说明

eclipse使用Resource Bundle Editor实现属性集编写
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355