一. SpringBoot入门

一. SpringBoot入门

SpringBoot介绍

Spring Boot使开发独立的,产品级别的基于Spring的应用变得非常简单,你只需"just run"。 我们为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数Spring Boot应用需要很少的Spring配置

解决的问题

依赖太多了, 且存在版本问题

配置太多了且每次都一样, 大部分工程, 配置每次都是一样的, 从一个地方拷贝到另外一个地方. 且Spring发展10多年, 各种配置版本太多, 对于很多程序员来说, 分不清哪个是有效, 哪个无效.

部署太麻烦. 需要tomcat部署, 项目结构也需要照着Java EE的目录结构来写.

SpringBoot特点

创建独立的Spring应用程序

嵌入的Tomcat,无需部署WAR文件

简化Maven配置

自动配置Spring

提供生产就绪型功能,如指标,健康检查和外部配置

绝对没有代码生成和对XML没有要求配置

SpringBoot功能

自动配置(auto-configuration)

一项简化配置的功能,比如在classpath中发现有spring security的jar包,则自动创建相关的bean等

starters(简化依赖)

这个比较关键,方便spring去集成各类组件,比如redis、mongodb等等。

Spring(Boot)注解

@RestController。这被称为一个构造型(stereotype)注解。它为阅读代码的人们提供建议。对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web @Controller,所以当处理进来的web请求时,Spring会询问它。

@RequestMapping注解提供路由信息。它告诉Spring任何来自"/"路径的HTTP请求都应该被映射到home方法。@RestController注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者。

@EnableAutoConfiguration。这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。

main方法。这只是一个标准的方法,它遵循Java对于一个应用程序入口点的约定我们的main方法通过调用run,将业务委托给了Spring Boot的SpringApplication类。SpringApplication将引导我们的应用,启动Spring,相应地启动被自动配置的Tomcat web服务器。我们需要将Main.class作为参数传递给run方法来告诉SpringApplication谁是主要的Spring组件。

注意事项

当类没有包含package声明时,它被认为处于default package下。通常不推荐使用default package,并应该避免使用它。因为对于使用@ComponentScan,@EntityScan或@SpringBootApplication注解的Spring Boot应用来说,来自每个jar的类都会被读取,这会造成一定的问题。

定位main应用类

通常建议你将main应用类放在位于其他类上面的根包(root package)中。通常使用@EnableAutoConfiguration注解你的main类,并且暗地里为某些项定义了一个基础“search package”。例如,如果你正在编写一个JPA应用,被@EnableAutoConfiguration注解的类所在包将被用来搜索@Entity项。

使用根包允许你使用@ComponentScan注解而不需要定义一个basePackage属性。如果main类位于根包中,你也可以使用@SpringBootApplication注解。

SpringBoot快速入门

使用没有父POM的Spring Boot

不是每个人都喜欢继承spring-boot-starter-parent POM。你可能需要使用公司标准parent,或你可能倾向于显式声明所有Maven配置。

如果你不使用spring-boot-starter-parent,通过使用一个scope=import的依赖,你仍能获取到依赖管理的好处:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

生成mapper

mybatis集成

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.2.0</version>
</dependency>

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

建表

CREATE TABLE `hgy_user` (
	`id`  int NOT NULAUTO_INCREMENT ,
	`passwd`  varchar(255) NUL,
	`username`  varchar(255) NUL,
	PRIMARY KEY (`id`)
);

mybatis数据源配置

GMT%2B8 = GMT+8

在resources目录,新建application.properties文件,增加内容如下

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

mybatis.mapperLocations=classpath:mapping/*.xml

生成mapper的配置

准备mybatis的生成文件generatorConfig.xml,并在相应目录创建好model,dao,mapping文件夹

<?xmversion="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
  <classPathEntry
    location="E:\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar"/>
  <context id="DB2Tables" targetRuntime="MyBatis3">
    <commentGenerator>
      <property name="suppressDate" value="true"/>
      <!-- 是否去除自动生成的注释 true:是 : false:否 -->
      <property name="suppressAllComments" value="true"/>
    </commentGenerator>
    <!--数据库链接URL,用户名、密码 -->
    <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
      connectionURL="jdbc:mysql://127.0.0.1:3306/my_db?serverTimezone=GMT%2B8" userId="root" password="root">
    </jdbcConnection>
    <javaTypeResolver>
      <property name="forceBigDecimals" value="false"/>
    </javaTypeResolver>
    <!-- 生成模型的包名和位置-->
    <javaModelGenerator targetPackage="len.hgy.model" targetProject="src/main/java">
      <property name="enableSubPackages" value="true"/>
      <property name="trimStrings" value="true"/>
    </javaModelGenerator>
    <!-- 生成映射文件的包名和位置-->
    <sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">
      <property name="enableSubPackages" value="true"/>
    </sqlMapGenerator>
    <!-- 生成DAO的包名和位置-->
    <javaClientGenerator type="XMLMAPPER" targetPackage="len.hgy.dao" targetProject="src/main/java">
      <property name="enableSubPackages" value="true"/>
    </javaClientGenerator>
    <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
    <table tableName="hgy_user" domainObjectName="Users" enableCountByExample="false"
      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
      selectByExampleQueryId="false"/>
  </context>
</generatorConfiguration>

生成方式

cmd命令执行配置文件

Java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xm-overwrite

通过Main方法执行配置文件

依赖

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.4.0</version>
</dependency>

Main

package len.hgy;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorConfig {

    public static void main(String[] args) {
        try {
            List<String> warnings = new ArrayList<>();
            boolean overwrite = true;
            String genCfg = "/generatorConfig.xml";
            File configFile = new File(Objects.requireNonNull(GeneratorConfig.class.getResource(genCfg)).getFile());
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config;
            config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);

            myBatisGenerator.generate(null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过Maven插件运行

<build>  
    <plugins>  
        <plugin>  
            <groupId>org.mybatis.generator</groupId>  
            <artifactId>mybatis-generator-maven-plugin</artifactId>  
            <version>1.3.2</version>  
            <configuration>  
                <verbose>true</verbose>  
                <overwrite>true</overwrite>  
            </configuration>  
        </plugin>  
    </plugins>  
</build> 

运行命令

mvn mybatis-generator:generate

报错

Description:
A component required a bean of type 'len.hgy.dao.UsersMapper' that could not be found.

Action:
Consider defining a bean of type 'len.hgy.dao.UsersMapper' in your configuration.

注意:得在App启动类上增加@MapperScan扫描注解, 否则找不到Mapper的bean

package len.hgy;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@MapperScan("len.hgy.dao")
@EnableTransactionManagement
public class App {

    public static void main(String[] args) {
        //启动类
        //定制化
        SpringApplication.run(App.class, args);
    }
}

也要注意配置自己的过滤配置的规则

<build>
    <resources>
        <resource>
            <directory>src/java/main</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

全局异常处理

一般在企业里面对这些异常一般都会统一捕获,由一个专门的异常处理类来统一处理

异常捕获

package len.hgy.utils;

import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public Object defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        e.printStackTrace();
        return "我是个异常处理类";
    }

    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return factory -> {
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.do");
            factory.addErrorPages(error404Page);
        };
    }
}

静态资源访问

静态资源:js, css, html, 图片,音视频等

静态资源路径:是指系统可以直接访问的路径,且路径下的所有文件均可被用户直接读取。Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

/static

/public

/resources

/META-INF/resources

在任意目录放一张图片1.jpg

在地址栏上输入localhost:8080/1.jpg,可以看到图片

JSP集成

一般来说springboot不建议直接使用jsp页面,但不排除有些公司的项目依然使用jsp做前端界面。

springboot内置的tomcat并没有集成对jsp的支持,也没有对EL表达式的支持,因此要使用jsp应该先把相关的依赖集成进来

在pom文件里面新增

<!--JavaServer Pages Standard Tag Library,JSP标准标签库-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>

<!--内置tocat对Jsp支持的依赖,用于编译Jsp-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

由于要springmvc解析jsp,要配置试图解析器,在applicaiton.properties 里面新增

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

在resources里面新建WEB-INF文件夹,在里面放一个index.jsp页面

image-20220127010608629

类容如下

<%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%>
<!DOCTYPE htmPUBLIC "-//W3C//DTD HTM4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>jsp page</title>
</head>
<body>
	<h1>这是个jsp页面!!</h1>
</body>
</html>

最后新建一个controller,注意这里的注解是@Controller,千万不能用@RestController

package cn.enjoy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/jsp")
public class JspController {
    @RequestMapping("/hi")
    public String sayHello() {
        return "index";
    }
}

在浏览器上输入:localhost:8080/jsp/hi,可以看到JSP页面

模板引擎

SpringBoot 推荐使用模板引擎来渲染html,如果你不是历史遗留项目,一定不要使用JSP,常用的模板引擎很多,有freemark,thymeleaf等,其实都大同小异其中springboot 强烈推荐的是用thymeleaf

pom文件种添加thymeleaf的支持,并且删除JSP的支持

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

删除application.properties文件里面视图解析器内容

#spring.mvc.view.prefix=/WEB-INF/jsp/
#spring.mvc.view.suffix=.jsp

新建Controller内容如下

package len.hgy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/tpl")
public class ThymeleafController {
    @RequestMapping("/testThymeleaf")
    public String testThymeleaf(ModelMap map) {
        // 设置属性
        map.addAttribute("name", "enjoy");
        // testThymeleaf:为模板文件的名称
        // 对应src/main/resources/templates/testThymeleaf.html
        return "testThymeleaf";
    }
}

Springboot默认的模板配置路径为:src/main/resources/templates

在resources目录里面新建一个templates目录,在目录里面新建testThymeleaf.html文件

<!DOCTYPE html>
<htmxmlns:th="http://www.w3.org/1999/xhtml">
    <head lang="en">
        <meta charset="UTF-8" />
        <title>thymeleaf</title>
    </head>
    <body>
        <h1 th:text="${name}"/>
    </body>
</html>

在浏览器上输入:localhost:8080/tpl/testThymeleaf,可以看到页面。

localhost:8080/tpl/testThymeleaf/hgy?nameQ=Hgy

SpringBoot热部署

热部署不会用在生产环境,但对于程序员开发的效率,还是有一定帮助的,所谓的热部署,就是在应用程序在不停止的情况下,实现新的部署

spring-boot-devtools 是一个为开发者服务的一个模块,其中最重要的功能就是自动应用代码更改到最新的App上面去。原理是在发现代码有更改之后,重新启动应用,但是速度比手动停止后再启动还要更快,更快指的不是节省出来的手工操作的时间。

其深层原理是使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为 restart ClassLoader ,这样在有代码更改的时候,原来的restart ClassLoader 被丢弃,重新创建一个restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间

spring-boot-devtools 介绍

  • spring-boot-devtools 是一个为开发者服务的模块,可以实现 Spring Boot 热部署,其中最重要的功能就是自动将应用代码更改到最新的 App 上面去。
  • spring-boot-devtools 可以实现页面热部署,实现类文件热部署(类文件修改后不会立即生效),实现对属性配置文件的热部署。其原理是 spring-boot-devtools 会监听 Classpath 下的文件变动,并且会立即重启应用(发生在保存时机)。
  • 由于采用的虚拟机机制,重启的时候只是加载了在开发的 Class,没有重新加载第三方的 JAR 包,所以重启是很快的。

pom.xml

如果你是使用eclipse,请忽略,但如果你是使用IDEA,由于idea 没有保存修改的也就是说在idea中并不会因为你ctrl+s 就重新编译代码。那么就需要额外的配置

在pom文件中,增加编译插件,让代码有变动的时候也编译

<!--热部署依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
 </dependency>

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <!--没有该项配置,热部署不会起作用-->
    <configuration>
        <fork>true</fork>
    </configuration>
 </plugin>

application.properties

# 页面修改后立即生效,关闭缓存,立即刷新
spring.thymeleaf.cache=false
# 热部署生效
spring.devtools.restart.enabled=true
# 设置需要重启的目录
spring.devtools.restart.additional-paths=src/java/main
# 设置不需要重启的目录
spring.devtools.restart.exclude=static/**,public/**,WEB-INF/**
# 为 mybatis 设置,生产环境可删除
# restart.include.mapper=/mapper-[\\w-\\.]+jar
# restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar

设置 IDEA 环境自动编译

在编译器选项中勾选 Build project automatically 选项

image-20220127015835107

使用快捷键:Ctr+ Alt + Shift + / 调出 Registry 窗口,勾选 compiler.automake.allow.when.app.running 选项

image-20220127015946644

测试class和模板引擎的配置文件修改都会生效, 需要重新编译

手动:修改完代码,按快捷键Ctrl+F9,手动构建项目,或者只修改单个类文件的话,按Ctrl+Shift+F9,重新编译该类文件,即可触发重启服务。

集成Swagger2构建API文档

Swagger2 的作用

随项目自动生成强大RESTfuAPI文档,减少工作量

API文档与代码整合在一起,便于同步更新API说明

页面测试功能来调试每个RESTfuAPI

修改pom文件,添加swagger2的相关依赖

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.7.0</version>
</dependency>

新建一个swagger的配置类SwaggerConfig.java

package len.hgy.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("len.hgy"))// 指定扫描包下面的注解
            .paths(PathSelectors.any())
            .build();
    }

    // 创建api的基本信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("集成Swagger2构建RESTful APIs")
            .description("集成Swagger2构建RESTful APIs")
            .termsOfServiceUrl("https://www.hgy.len/")
            .contact(new Contact("hgy", "len.hgy", "hgy@hgy.len"))
            .version("1.0.0")
            .build();
    }
}

新建Controller用于显示相关接口

package len.hgy.controller;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/swagger")
public class SwaggerController {

    @ApiOperation(value = "获取用户信息", notes = "根据id来获取用户详细信息")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "String")
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Map<String, String> getInfo(@PathVariable String id) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("name", "hgy");
        map.put("age", "38");
        return map;
    }
}

访问:http://localhost:8080/swagger-ui.html

日志集成

java有许多的日志组件,比如 log4j,log4j2,logback还有java自生提供的Java Util Logging,其实在springboot中对这些组件都提供了支持,log4j,log4j2和logback都提供相应的组件支持。默认使用logback

Logback

在springboot中默认使用的日志工具是logback,不过在提及具体的日志工具之前要提一个名词,这个名词就是slf4j(Simple Logging Facade For Java)

slf4j不是具体的日志解决方案,它有点类似于jdbc,使用了门面模式,是一个针对各类日志的抽象实现,既然是抽象的日志实现,在springboot中肯定不需要额外导入。

依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

注意:spring-boot-starter中就提供了对spring-boot-starter-logging的依赖在spring-boot-starter-logging中可以看到以及集成了slf4j与具体实现logback的默认支持

image-20220127021613021

日志使用

private final Logger logger = LoggerFactory.getLogger(UserController.class);

日志配置

一般情况下,springboot日志只会输出到控制台,并不会写入到日志文件,但是,在一些正式环境的应用中,我们需要通过在 application.properites 文件中配置 logging.file 文件名称和 logging.path 文件路径,将日志输出到日志文件中。

# 默认当前项目下
logging.path = /var/tmp
# 默认名称是spring.log
logging.file = xxx.log
# 默认级别是info
logging.level.root = info

如果只配置 logging.path,在 /var/tmp文件夹生成一个日志文件为 spring.log。如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。

这里有一个坑,logging.path 和logging.file都配置了路径和文件,只会有logging.file生效,所以,如果要指定日志生成的具体位置使用logging.file 配置就好

log4j2

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</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-log4j2</artifactId>
</dependency>

log4j的1.xxx版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.8.RELEASE</version>
</dependency>

注意: 由于默认使用logback在扩展log4j2之前先要把logback移除

配置

如果不只为了学习集成log4j,在工作是最好不要使用log4j,毕竟有了log4j2,也有了logback使用log4j就是吃饱了撑着

在springboot中并没有提供对log4j这个依赖的支持,因此要使用它配置起来还是挺麻烦的。

在classpath下增加log4j.properties文件

log4j.rootCategory=INFO, stdout, file, errorfile
log4j.category.cn.enjoy=INFO, myFile
log4j.logger.error=errorfile

# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

# root日志输出
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.file=logs/all.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

# error日志输出
log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorfile.file=logs/error.log
log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd
log4j.appender.errorfile.Threshold = ERROR
log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

# cn.enjoy下的日志输出
log4j.appender.myFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.myFile.file=logs/my.log
log4j.appender.myFile.DatePattern='.'yyyy-MM-dd
log4j.appender.myFile.layout=org.apache.log4j.PatternLayout
log4j.appender.myFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n
在代码中使用

import org.apache.log4j.Logger;

private final Logger logger = Logger.getLogger(xxx.class);

使用AOP统一日志处理

为了防止在工作中经常在代码中加入大量的日志处理代码,在实际项目开发中,一般使用AOP统一完成日志处理工作

修改pom文件,引入springboot对aop的支持

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

新增AOP日志处理类

package len.hgy.utils;

import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class WebLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution(public * len.hgy.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String name = (String) enu.nextElement();
            logger.info("name:{},value:{}", name, request.getParameter(name));
        }
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
}

编译,打包

在pom文件中新增

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!-- 如果不设置fork,那么不会restart,devtools热部署不会起作用-->
                <fork>true</fork>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

使用mvn clean package 打包

java –jar 运行

war部署

如果并不希望使用内置的tomcat,希望部署到其他tomcat服务器,那么就需要使用war包部署了。

修改pom文件,打包方式改成war

<package>war</package>

修改在pom文件,剔除内置tomcat的支持,否则会和外面的tomcat冲突

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是打包阶段做了exclude操作-->
    <scope>provided</scope>
</dependency>

修改启动类,使其继承org.springframework.boot.web.servlet.support.SpringBootServletInitializer,并重写configure方法

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
@MapperScan("len.hgy.dao")
public class App  extends SpringBootServletInitializer  {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(App.class);
    }
}

使用mvn clean package 打包

把war包拷贝到tomcat webapps中

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

岁月玲珑

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值