springboot+mybatis+thymeleaf学习一个简单的管理系统

在淘宝上买的课程的一个例子,看了视频,抄了一遍代码,那时候刚开始学springboot,所以感觉没什么用,然后就又学习了一段时间。最近回想起来有这样的一个系统符合我现阶段的学习程度,然后就又写了一遍。其中css和js实在没法自己搞,所以就直接把课程里的拿来用。所有做完后的样式确实不好看,但我自己觉得看的过去。
今天下午可以算是完工了(也就是增删改查),又想起大佬的话,也怕自己忘了,所以写博客记录一下。

1.技术方法

springboot+thymeleaf+mybatis+shiro

1.1 pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>bill</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>

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

</project>

pom依赖差不多用的最新的版本,自己学习用的,应该没什么大的影响。

1.2 springboot使用thymeleaf

springboot使用thymeleaf我觉的比较方便,在HTML中引入<html xmlns:th="http://www.thymeleaf.org">,就能使用thymeleaf的功能(不知道这样说对不对)。thymeleaf特性的使用还是要多学习的,能够灵活应用的感觉应该非常不错。

1.3 springboot-mybatis

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录(百度)。
刚接触springboot的时候就是学的mybatis,所以可能情有独钟吧。

1.4 springboot-shiro

本来的教程上没有这个技术点,但我在学习的过程中接触到了shiro,有一篇springboot+Vue的教学博客让我记忆犹新,所以我决定试一下。在这里给大家推荐一下 Evan-Nightly大佬的这篇博客 Vue + Spring Boot 项目实战,也给自己插个眼。
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序(百度)。

2.代码梳理

2.1 结构

在这里插入图片描述
java类大概就是这些。
WebMvcConfig.java是拦截器、过滤器和视图控制器的配置文件。

package com.example.config;

import com.example.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MySpringMvcConfig implements WebMvcConfigurer {
    //添加视图控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    //main.html是显示在浏览器网址上的,main/main是项目main下面的main/html
        registry.addViewController("main.html").setViewName("main/main");
        registry.addViewController("index.html").setViewName("main/index");
    }
    //配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
        //拦截所有请求
                .addPathPatterns("/**")
                //不拦截
                .excludePathPatterns("/", "/login", "/index.html")
                //测试用的请,不拦截,可在项目上线时删掉
                .excludePathPatterns("/test", "/thymeleaf");
    }
}

我在刚开始学springboot的时候,拦截器、过滤器和视图控制器还挺难理解的,虽然看了几遍概念介绍但感觉还是无法理解这到底是个什么东西。在做这个项目的时候我自己多试了几遍。改一个编一次看一下什么情况,慢慢的就知道是什么作用了。自学,笨鸟先飞,是这样的,没办法。
ShiroConfig.java是shiro配置类

package com.example.config;

import com.example.realm.MyRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Create by Administrator on 2020/2/24.
 */
@Configuration
public class ShiroConfig {

    @Bean
    public static  LifecycleBeanPostProcessor getLifecycleBeanProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(getMyRealm());
        return securityManager;
    }
    @Bean
    public MyRealm getMyRealm() {
        MyRealm wjRealm = new MyRealm();
        wjRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return wjRealm;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

shiro的配置具体是什么意思我还真说不出来,感觉自己也就知道的大概,知其然而不知所以然。
我只用到了shiro的用户信息加密和认证登录功能,就是给用户注册时的密码加密,然后在登录时再比对加密的密码。
MyRealm.java

package com.example.realm;

/**
 * Create by Administrator on 2020/2/24.
 */
public class MyRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;
    //简单重写获取授权信息方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
        return s;
    }

    //获取认证信息,即根据token中的用户名从数据库中获取密码和盐等信息并返回
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = authenticationToken.getPrincipal().toString();
        User user = userService.getUserByName(userName);
        String passwordInDB = user.getPassword();
        String salt = user.getSalt();
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, passwordInDB, ByteSource.Util.bytes(salt), getName());
        return authenticationInfo;
    }
}

MyRealm和ShiroConfig.java配合使用,其中的奥秘我还没懂,希望有懂的大佬帮忙教一下。

2.2 登录模块

package com.example.controller;

@Controller
public class LoginController {

    @Autowired
    UserService userService;
//跳转到用户登录界面
    @RequestMapping("/index")
    public String index(){
        return "main/index";
    }
    //在页面点击登录按钮后执行登录
    @RequestMapping("/login")
    //username和password是前端传递过来的,这就是前后传递的一种方式
    public String login(HttpSession httpSession, String username, String password){
        System.out.println("username="+username+",password="+password);
        //判断是否为空,这个可以改到前端独立判断
        if(username.equals("") || password.equals("")){
        //如果为空就跳转到登录页
            return "redirect:/index";
        }
        //根据用户名获取用户
        User loginuser = userService.getUserByName(username);
        if(loginuser == null){
            System.out.println("user==null");
            return "redirect:/index";
        }
        //简单的判断密码是否正确
//        if(!loginuser.getPassword().equals(password)){
//            System.out.println("error password");
//            return "redirect:/index";
//        }
        //shiro获取subject
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
        try {
            subject.login(usernamePasswordToken);
            //存储到session中,拦截器中判断是否登录
            httpSession.setAttribute("loginUser", loginuser);
            return "redirect:/main.html";
        }catch (AuthenticationException e){
            return "redirect:/index";
        }
//        httpSession.setAttribute("loginUser", loginuser);
//        return "redirect:/main.html";
    }
//跳转到主页面
    @GetMapping("/main/main")
    public String mainMain(HttpServletRequest httpServletRequest){
        System.out.println("mainMain method="+httpServletRequest.getMethod());
        return "redirect:/main.html";
    }
    //退出登录
    @GetMapping("/logout")
    //public String logout(HttpSession httpSession){
    public String logout(HttpServletRequest httpServletRequest){
        System.out.println("logout method="+httpServletRequest.getMethod());
        Subject subject = SecurityUtils.getSubject();
        subject.logout();

        //httpSession.removeAttribute("loginUser");
        //httpSession.invalidate();
        return "redirect:/index";
    }
}

我不知道怎么讲,所以把该说的都用注释写出来
index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" th:href="@{/css/public.css}"/>
    <link rel="stylesheet" th:href="@{/css/style.css}"/>
</head>
<body style="background: #ffffff">
<section class="loginBox" style="margin-top: 100px">
    <section class="loginCont">
        <form class="loginForm" th:action="@{/login}"  method="post">
            <div class="inputbox">
                <label>用户名</label>
                <!-- username绑定到后端 -->
                <input type="text" name="username"/>
            </div>
            <div class="inputbox">
                <label>用户密码</label>
                <!-- 后端接收到password -->
                <input type="text" name="password"/>
            </div>
            <div class="subBtn" style="margin-top: 5px">
            <!-- 提交表单 -->
                <input type="submit" value="登录" onclick="this.form.submit()"/>
            </div>
        </form>
    </secion>
</section>
</body>
</html>

提交后,后台判断用户是否存在,用户的密码是否正确,然后跳转到主界面main.html,然后点击菜单就会跳转到相应的界面。
在这里插入图片描述

2.3 用户模块

登录之后自然会有一些操作,但大多都基于对数据库的增删改查。

User.java

package com.example.bean;

import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;
/**
 * Create by Administrator on 2020/2/19.
 */
public class User {
    private Integer id;
    private String username;
    private String realName;
    private String password;
    private String salt;
    //性别 1:女   2:男
    private int gender;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    //1管理员 2经理 3普通用户
    private int userType;

    public User(Integer id, String username, String realName, String password, String salt, int gender, Date birthday, int userType) {
        this.id = id;
        this.username = username;
        this.realName = realName;
        this.password = password;
        this.salt = salt;
        this.gender = gender;
        this.birthday = birthday;
        this.userType = userType;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", realName='" + realName + '\'' +
                ", password='" + password + '\'' +
                ", salt='" + salt + '\'' +
                ", gender=" + gender +
                ", birthday=" + birthday +
                ", userType=" + userType +
                '}';
    }
    
getter() and setter()...

在创建user类时要注意id的类型最好用Integer,否则在增加用户时会有问题,应为id在数据库中是自增的,而在增加用户时页面上没有,会有问题。
还有在建user表时password和salt的大小要大一点,我当时用25个字节结果加了shiro加密后有报错提示(具体的报错就不回放了)。
还有用户的生日也会有问题,要注意加上@DateTimeFormat(pattern = “yyyy-MM-dd”)注解。如果不加从页面保存时(增加或者更新)会有类型转换的错误。
然后重点说一下和shiro有关的内容,就是在注册时密码加密的过程。

@PostMapping("/user/add")
    public String add(HttpServletRequest httpServletRequest, User user){
        System.out.println("add method="+httpServletRequest.getMethod());
        String password = user.getPassword();
        String username = user.getUsername();
        username = HtmlUtils.htmlEscape(username);
        user.setUsername(username);
        User user1 = userService.getUserByName(username);
        if(null != user1){
            return "redirect:/list/users";
        }
        //生成盐,默认长度16位
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        //设置hash迭代次数
        int times = 2;
        //获取hash后的密码
        String encodingPassword = new SimpleHash("md5", password, salt, times).toString();
        user.setSalt(salt);
        user.setPassword(encodingPassword);
        userService.addUser(user);
        return "redirect:/list/users";
    }

大概都写到注释里了。
再说一下在页面上展示所有用户,list.html

<table class="providerTable" cellpadding="0" cellspacing="0">
    <tr>
        <a type="button" th:href="@{/user/add}">
            <button>增加用户</button>
        </a>
    </tr>
    <tr class="firstTr">
        <th width="10%">用户名</th>
        <th width="20%">真实姓名</th>
        <th width="10%">性别</th>
        <th width="10%">出生日期</th>
        <th width="10%">用户类型</th>
        <th width="30%">操作</th>
    </tr>
    <!-- 循环取出所用用户 -->
    <tr th:each="u : ${users}">
        <td th:text="${u.username}">xxx</td>
        <td th:text="${u.realName}">xx</td>
        <!--性别:1 女  2 男-->
        <td th:text="${u.gender == 1 ? '女' : '男'}">x</td>
        <td th:text="${#dates.format(u.birthday, 'yyyy-MM-dd')}">xxx</td>
        <!--1管理员  2经理  3普通用户-->
        <td th:text="${u.userType==1 ? '管理员' : (u.userType==2 ? '经理' : '普通用户') }">xx</td>
        <td>
            <a th:href="@{/user/} + ${u.id}" ><img th:src="@{/img/read.png}" alt="查看" title="查看"/></a>
            <a th:href="@{/user/} + ${u.id} +'?type=update'" ><img th:src="@{/img/xiugai.png}" alt="修改" title="修改"/></a>
            <a th:href="@{/delete/user/}+${u.id}" ><img th:src="@{/img/schu.png}"  alt="删除" title="删除"/></a>
        </td>
    </tr>
</table>

后台从数据库中查找出所有用户传递给前端

//列出所有用户
    @RequestMapping("/list/users")
    public String listUser(Map<String, Object> map){

        List<User> users = userService.uListAll();
        map.put("users", users);
        return "user/list";
    }

修改用户页update.html

<form id="updateForm" action="#" th:action="@{/user}" method="post">
        <input th:type="hidden" name="_method" value="put">
        <input th:type="hidden" name="id" th:value="${user.id}">
        <input th:type="hidden" name="username" th:value="${user.username}">
        <input th:type="hidden" name="password" th:value="${user.password}">

        <div>
         <!-- 这里需要显示用户原本信息 -->
            <label >真实姓名:</label>
            <input type="text" th:value="${user.realName}" name="realName" id="realName" placeholder="realName"/>
            <span >*</span>
        </div>
        <div>
            <label >用户性别:</label>
            <select name="gender">
                <option value="1" th:selected="${user.gender == 1}">女</option>
                <option value="2" th:selected="${user.gender == 2}" selected>男</option>
            </select>
        </div>
        <div>
            <label for="birthday">出生日期:</label>
            <input type="text" th:value="${#dates.format(user.birthday, 'yyyy-MM-dd')}" name="birthday" id="birthday" placeholder="2016年2月1日"/>
            <span >*</span>
        </div>
        <div>
            <label >用户类别:</label>
            <!--1管理员  2经理  3普通用户-->
            <input type="radio" name="userType" value="1" th:checked="${user.userType == 1}"/>管理员
            <input type="radio" name="userType" value="2" th:checked="${user.userType == 2}" checked/>经理
            <input type="radio" name="userType" value="3" th:checked="${user.userType == 3}"/>普通用户
        </div>
        <div>
            <input type="button" value="保存" onclick="this.form.submit()"/>
            <input type="button" value="返回" onclick="history.back(-1)"/>
        </div>
    </form>

在修改页需要显示用户原本的信息,所以前后端需要用id来绑定一个user。

//查看用户详细信息
    @GetMapping("/user/{id}")
    //参数type来区分前端是要查看用户详细信息还是要修改用户信息
    public String view(HttpServletRequest httpServletRequest, @PathVariable("id") int id,
                       @RequestParam(value = "type", defaultValue = "view") String type,
                       Map<String, Object> map){
        System.out.println("view method="+httpServletRequest.getMethod());
        //通过前端传来的id获取到用户
        User user = userService.getUserById(id);
        //返回给前端用于页面显示用户原本的信息
        map.put("user", user);
        return "user/"+type;
    }

点击保存按钮好提交修改的用户信息

//更新用户信息
    @PostMapping("/user")
    public String update(HttpServletRequest httpServletRequest, User user){
        System.out.println("update method="+httpServletRequest.getMethod());
        userService.updateUser(user);
        return "redirect:/list/users";
    }

删除我就简单做了一下点击删除按钮直接从数据库删除

<a th:href="@{/delete/user/}+${u.id}" ><img th:src="@{/img/schu.png}"  alt="删除" title="删除"/></a>
//删除用户
    @GetMapping("/delete/user/{id}")
    public String delete(HttpServletRequest httpServletRequest, @PathVariable(value = "id") int id){
        System.out.println("delete method="+httpServletRequest.getMethod());
        userService.deleteUserById(id);
        return "redirect:/list/users";
    }

3. 总结

现在就总结好像有点早,但我写着写着发现好像没什么东西能写,或许可能功能比较少吧,Bill和Provider都和user类似,也是对数据库的增删改查操作。所以就不再赘述。
之后应该还会去完善一下,加上log系统和druid后台监控。
最后分享一下GitHub链接
https://github.com/azermu-milk/SpringbootTest.git
供大家clone。近期应该还会更新吧。

4.增加druid后台监控

4.1 介绍

在config文件夹下创建DruidConfig.java类,配置druid后台管理类和druid的filter类,当然还需要在application.yml中补全druid配置。
DruidConfig.java

package com.example.config;

/**
 * Create by Administrator on 2020/2/25.
 */
@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
        return new DruidDataSource();
    }

    //1.配置一个后台管理servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");

        //设置初始化参数
        Map<String, String> initParam = new HashMap<>();
        initParam.put(StatViewServlet.PARAM_NAME_USERNAME, "root");
        initParam.put(StatViewServlet.PARAM_NAME_PASSWORD, "root");
        //如果不写 则默认所有ip都能访问
        initParam.put(StatViewServlet.PARAM_NAME_ALLOW, "");
        //写入本地电脑的IP地址
        initParam.put(StatViewServlet.PARAM_NAME_DENY, "192.xxx.11.1");

        bean.setInitParameters(initParam);
        return bean;
    }

    //2.配置druid的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new WebStatFilter());

        Map<String, String> initParam = new HashMap<>();
        initParam.put(WebStatFilter.PARAM_NAME_EXCLUSIONS, "*.js,*.css,/druid/*");
        bean.setInitParameters(initParam);

        //设置拦截请求
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }
}

大概就是这样,如注释所示。
application.yml配置

    #数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    #间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    #配置有一个连接在连接池中的最小生存时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,slf4j
    maxPoolPreparedStatementPerConnectionSize: 25
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

4.2 后台监控展示

后台登录页
sql监控
刚开始我在statViewServlet()上少写了个@Bean,结果怎么改都没有后台的登录界面,全被我的拦截器拦截了,不过经过我再三检查终于被我发现了这个问题,哈哈。

5.日志框架

看了半天日志框架什么也没看明白,就把自己想用到的加进来了。

logging:
  level:
    com.example.mapper: debug
  #path和name二选一,name的优先级会高于path
  file:
    path: C:\Users\Administrator\IdeaProjects\mybill\
    #name: BillLog.log
  #如果使用yml做配置文件,格式要用'',如果是properties则不用
  pattern:
    #console: '%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n'
    #把控制台的日志输出到文件的格式
    file: '%d{yyyy/MM/dd-HH:mm:ss} ===== [%thread] ===== %-5level ===== %logger ===== %msg%n'

这个改动也在GitHub上提交了。整个项目是完整的,拉下来加到IDEA中就能启动成功。

5.1分析日志底层实现

在web项目当中引用了 spring-boot-starter-web 依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-web 中引入了 spring-boot-starter 启动器
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.0.6.RELEASE</version>
  <scope>compile</scope>
</dependency>
spring-boot-starter 中引入了 spring-boot-starter-logging 日志启动器
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
spring-boot-starter-logging 日志启动器 采用的是 logback 日志框架
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.3</version>
  <scope>compile</scope>
</dependency>

SpringBoot中默认日志启动器为 spring-boot-starter-logging ,默认采用的是 logback日志框架

logback的默认配置
<included>
 <!--日志格式默认规定-->
 <include resource="org/springframework/boot/logging/logback/defaults.xml" />
 <!--日志文件默认生成路径-->
 <property name="LOG_FILE"
value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
 <!--控制台日志信息默认配置-->
  <include resource="org/springframework/boot/logging/logback/console-
appender.xml" />
 <!--文件中日志信息默认配置-->
 <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
  <!--日志级别默认为: info -->
  <root level="INFO">
   <appender-ref ref="CONSOLE" />
   <appender-ref ref="FILE" />
 </root>
</included>

6.写在最后

这个项目到这里应该结束了,我不会再动它了。
又该去找新的项目学习去了。。。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值