第一章 SpringBoot基础入门笔记

本文详细介绍了SpringBoot的基础入门,包括SpringBoot的特点、功能、系统要求和第一个SpringBoot项目的创建过程。此外,还涉及SpringBoot快速入门,如集成mybatis、单元测试、日志配置、热加载/部署等方面,旨在帮助读者快速掌握SpringBoot的使用。
摘要由CSDN通过智能技术生成

一、SpringBoot简介

1、SpringBoot基础介绍

Spring Boot使开发独立的,产品级别的基于Spring的应用变得非常简单,你只需"just run"。我们为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数Spring Boot应用需要很少的Spring配置。你可以使用Spring Boot创建Java应用,并使用java -jar启动它或采用传统的war部署方式。

1.1、解决的问题

  • 依赖太多了,且存在版本问题。
  • 配置太多了且每次都一样,大部分工程配置每次都是一样的,从一个地方拷贝到另外一个地方;且Spring发展10多年,各种配置版本太多,对于很多程序员来说分不清哪个是有效、哪个无效。
  • 部署太麻烦,需要tomcat部署,项目结构也需要照着Java EE的目录结构来写。

1.2、SpringBoot特点

  • 创建独立的Spring应用程序
  • 嵌入的Tomcat,无需部署WAR文件
  • 简化Maven配置
  • 自动配置Spring
  • 提供生产就绪型功能,如指标,健康检查和外部配置
  • 绝对没有代码生成和对XML没有要求配置

1.3、SpringBoot功能

自动配置(auto-configuration):

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

starters(简化依赖):

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

2、系统要求

默认情况下,目前使用SpringBoot 2.2.1最新版本,最好安装JDK8以及以上的版本,maven使用3.3或者以上的版本。

3、第一个SpringBoot项目

新建一个普通maven项目,创建pom文件:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.1.RELEASE</version>
</parent>

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

3.1、编写代码:

为了完成应用程序,我们需要创建一个单独的Java文件,Maven默认会编译src/main/java下的源码。

新建:com.chj.Example.java

@RestController
@EnableAutoConfiguration
public class Example {
    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);
    }
}

3.2、@RestController和@RequestMapping说明

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

RestController源码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

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

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";
    @AliasFor("path")
    String[] value() default {};
    @AliasFor("value")
    String[] path() default {};
    RequestMethod[] method() default {};
    String[] params() default {};
    String[] headers() default {};
    String[] consumes() default {};
    String[] produces() default {};
}

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

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

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

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}

执行main方法,使用一个浏览器打开 localhost:8080,以下输出:Hello World!

4、注意事项

Spring Boot不需要使用任何特殊的代码结构,然而这里有一些地方需要注意。

4.1、使用"default"包

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

4.2、定位main应用类

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

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

二、SpringBoot快速入门

1、spring-boot-starter-parent使用

可以继承spring-boot-starter-parent项目来获取合适的默认设置,想配置你的项目继承spring-boot-starter-parent只需要简单地设置parent为:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
</parent>

备注

你应该只需要在该依赖上指定Spring Boot版本,如果导入其他的starters,你可以放心的省略版本号。

使用没有父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.2.1.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

2、搭建springboot环境

2.1、新建App.java

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

2.2、新建Controller:

@RestController
public class UserController {
    @RequestMapping("/hello")
    public Object sayHello() {
        return "hello";
    }
}

运行App,在浏览器输入:localhost:8080/hello,发现“hello”说明第一步部署成功。

3、集成mybatis

https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/1.3.5

 

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

3.1、生成mapper

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

@ConfigurationProperties( prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

特别注意:driverClassName与driver-class-name在不同的springboot版本中是不一样的

#数据库相关配置
spring.datasource.name=mysql
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

配置mybatis映射文件:mybatis.mapperLocations=classpath:mapping/*.xml

@ConfigurationProperties(prefix = "mybatis")
public class MybatisProperties {
    public static final String MYBATIS_PREFIX = "mybatis";
    private String configLocation;
    private String[] mapperLocations;
    private String typeAliasesPackage;

准备mybatis的生成文件generatorConfig.xml,并在相应目录创建好entity、dao、mapping文件夹,右键生成对应的文件。

注意:得再App启动类上增加@MapperScan扫描注解

@SpringBootApplication
@MapperScan("com.chj.dao")
public class App {
    public static void main( String[] args ) {
        SpringApplication.run(App.class, args);
    }
}

3.2、新增mapper登陆方法

dao接口类增加接口:

TUser findUserByNamePasswd(@Param("userName") String userName, @Param("password ") String password );

对应的XML配置:

<select id="findUserByNamePasswd" resultType="com.chj.entity.TUser" parameterType="map">
  select
  <include refid="Base_Column_List" />
  from t_user where 1=1
  <if test="password != null" >
    and password = #{password,jdbcType=VARCHAR}
  </if>
  <if test="userName != null" >
    and user_name = #{userName,jdbcType=VARCHAR}
  </if>
  limit 1
</select>

4、SpringBoot单元测试

  要测试刚才新增的Mapper方法是否成功,这里需要单元测试,在springboot中是有专门的组件来做单元测试的,在pom文件中新增依赖。

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

新建UserTest放置在test目录下:

@SpringBootTest(classes = {App.class})
@RunWith(SpringRunner.class)
public class UserTest {
    @Resource
    private TUserMapper tUserMapper;
    @Test
    public void testAdd() {
        TUser user = new TUser() ;
        user.setUserName("hankin");
        user.setPassword("123456");
        tUserMapper.insert(user);
    }
}

这样SpringBoot集成单元测试成功!

特别注意:springboot配置问题整理

1、问题1:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

//无法配置数据库,没有指定url属性,并且无法配置embedded datasource

Reason: Failed to determine a suitable driver class

//原因:无法明确指定正确的驱动类(driver.class):

Action:

Consider the following:  //建议:

//如果如果需要加载嵌入式的数据库,请将他放入路径中

If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.

//如果有数据库设置需要从指定配置文件中加载,需要调用该配置文件(目前没有活动的配置文件)

If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

问题分析:

通过比较两个项目结构,和修改的文件,会发现只因为有pom文件的修改导致项目中增加的mysql、redis、es、mongodb的依赖包的导入,需要添加新的database配置文件,可能因为springboot的启动会自动加载这些依赖启动时候需要的以来文件。

结果:报错的原因是因为导入的两个依赖

<!--<dependency>-->

     <!--<groupId>org.springframework.boot</groupId>-->

     <!--<artifactId>spring-boot-starter-web</artifactId>-->

<!--</dependency>-->

 <!--<dependency>-->

      <!--<groupId>org.mybatis.spring.boot</groupId>-->

      <!--<artifactId>mybatis-spring-boot-starter</artifactId>-->

      <!--<version>1.3.0</version>-->

<!--</dependency>-->

经过排查根据网上各种尝试发现还是没能解决问题,最终新建一个springboot项目,然后依次加入各种配置发现可以正常启动!!!

2、问题2

数据库连接配置时区问题,因为springboot2以后需要加时区,否则报错如下所示:

java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

注意添加:serverTimezone=GMT%2B8

spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8

4.1、新建service

新增接口UserService: 

public interface UserService {
    boolean login(String username,String password);
    boolean register(String username,String password);
}

创建实现类:

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private TUserMapper usersMapper;
    @Override
    public boolean login(String username, String passwd) {
        TUser users = usersMapper.findUserByNamePasswd(username, passwd);
        return users != null;
    }
    @Override
    public boolean register(String username, String passwd) {
        TUser users = new TUser();
        users.setUserName(username);
        users.setPassword(passwd);
        int cnt = usersMapper.insert(users);
        return cnt > 0;
    }
}

4.2、修改controller

修改UserController,增加login和register方法

@RestController
public class UserController {
    @Resource
    private UserService userService;
    @RequestMapping("/hello")
    public Object sayHello() {
        return "hello";
    }
    @RequestMapping("/login")
    public String login(String username,String passwd) {
        boolean login = userService.login(username, passwd);
        if(login) {
            return "登陆成功";
        }else {
            return  "登陆失败";
        }
    }
    @RequestMapping("/register")
    public String register(String username,String passwd) {
        boolean login = userService.register(username, passwd);
        if(login) {
            return "注册成功";
        }else {
            return  "注册失败";
        }
    }
}

在浏览器上输入:localhost:8080/register?username=hankin&passwd=123456,显示“注册成功”

在浏览器上输入:localhost:8080/login?username=hankin&passwd=123456,显示“登陆成功”。

5、事务支持

修改UserService接口,增加一个新增batchAdd方法,在UserServiceImpl增加相应实现类,在实现类中故意产生一个被0整除得异常。

@Override
public void batchAdd(String username, String passwd) {
    User user = new User();
    user.setUserName(username);
    user.setPassword(passwd);
    usersMapper.insertSelective(user);
    int i = 10 /0;
    user = new User();
    user.setUserName(username+"2");
    user.setPassword(passwd);
    usersMapper.insertSelective(user);
}

修改UserContoller增加batchAdd方法:

@RequestMapping("/batchAdd")
public String batchAdd(String username,String passwd) {
    userService.batchAdd(username, passwd);
    return "成功";
}

重新运行,在浏览器上输入:

localhost:8080/batchAdd?username=chj&passwd=123456,可以发现在浏览器上出现500错误。

检查数据库,发现表里面已经产生了一个错误的数据,产生了事务问题。

事务支持:

在batchAdd方法上增加@Transactional注解,重启服务后,在浏览器上输入:

localhost:8080/batchAdd?username=chj&passwd=123456

浏览器还继续报错,但检查数据库,事务问题已经得到了解决

6、全局异常处理

通过上面步骤,虽然已经解决了事务问题,但界面上出现这500错误,这对用户来说还是不友好;一般在企业里面对这些异常一般都会统一捕获,由一个专门的异常处理类来统一处理。

6.1、异常捕获

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

重启服务后,在浏览器重新访问会出现异常的服务,界面返回:

 

6.2、404页面处理

在浏览器上故意输错地址:localhost:8080/batchAddx?username=enjoy&passwd=123,后端并没有这服务,虽然已经做了相关的异常捕获,但浏览器还是显示了404错误,这个时候就要做404处理了(其他异常代码一样)。

1)在配置这样错误页面的时候,以前是在WEB.XML中进行配置,而在这里,需要有个WebServerFactoryCustomizer的实例进行配置,在前面建立的GlobalExceptionHandler,新建一个方法:

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

2)新建BaseController:

@RestController
public class BaseController {
    @RequestMapping("/404.do")
    public Object error_404() {
        return "你要找的页面,就是我!";
    }
}

3)重启服务,在浏览器上输入:

localhost:8080/batchAddx?username=enjoy&passwd=123,此时页面返回“你要找的页面,就是我!”。

注意:

WebServerFactoryCustomizer这种配置方式是在SpringBoot2之后才这样配置的,在1.X的版本需要用到的是EmbeddedServletContainerCustomizer。

代码如下:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
    return (container -> {
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.do");
        container.addErrorPages( error404Page);
    });
}

7、静态资源访问

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

静态资源路径:是指系统可以直接访问的路径,且路径下的所有文件均可被用户直接读取。

Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

/static

/public

/resources

/META-INF/resources

在resources目录下面建立static文件夹,在文件夹里面任意放张图片,命名为:image.png,在地址栏上输入localhost:8080/image.png,可以看到图片。

三、前端界面访问

1、JSP集成

一般来说springboot不建议直接使用jsp页面,但不排除有些公司的项目依然使用jsp做前端界面。springboot内置的tomcat并没有集成对jsp的支持,也没有对EL表达式的支持,因此要使用jsp应该先把相关的依赖集成进来

1.1、在pom文件里面新增

<!--JavaServer Pages Standard Tag Library,JSP标准标签库-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>
<!--内置tomcat对Jsp支持的依赖,用于编译Jsp-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

1.2、配置视图解析器

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

# jsp视图解析器
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

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

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

@Controller
@RequestMapping("/jsp")
public class JspController {
    @RequestMapping("/hello")
    public String sayHello() {
        return "index";
    }
}

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

2、模板引擎

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

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

<!--  模板引擎 thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

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

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

#spring.mvc.view.suffix=.jsp

3)新建Controller代码如下:

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

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

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

<body>

<h1 th:text="${name}"/>

</body>

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

四、集成Swagger2构建API文档

1、Swagger2 的作用

  • 随项目自动生成强大RESTful API文档,减少工作量
  • API文档与代码整合在一起,便于同步更新API说明
  • 页面测试功能来调试每个RESTful API

2、添加swagger2的相关依赖

<!--  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>

3、新建一个swagger的配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.chj")) //TODO 指定扫描包下面的注解
                .paths(PathSelectors.any())
                .build();
    }
    // 创建api的基本信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("集成Swagger2构建RESTful APIs")
                .description("集成Swagger2构建RESTful APIs")
                .termsOfServiceUrl("https://blog.csdn.net/m0_37661458")
                .contact(new Contact("hankin","blog.csdn.net","1032291008@qq.com"))
                .version("1.0.0")
                .build();
    }
}

4、新建Controller用于显示相关接口

@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", "zacker");
        map.put("age", "32");
        return map;
    }
}

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

 

五、日志集成

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

1、Logback日志实现

在springboot中默认使用的日志工具是logback,不过在提及具体的日志工具之前要提一个名词,这个名词就是slf4j(Simple Logging Facade For Java)。slf4j不是具体的日志解决方案它有点类似于jdbc,使用了门面模式,是一个针对各类日志的抽象实现,既然是抽象的日志实现,在springboot中不需要额外引入。

注意:spring-boot-starter中就提供了对spring-boot-starter-logging的依赖

在spring-boot-starter-logging中可以看到以及集成了slf4j与具体实现logback的默认支持:

 

修改UserController

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

@RequestMapping("/hello")
public Object sayHello() {
    logger.info("这是个hello的info日志!");
    logger.debug("这是个hello的debug日志!!");
    return "hello";
}

在浏览器上输入:localhost:8080/hello,可以看控制台日志的输出:这是个hello的info日志!

1.1、日志级别

修改controller 把日志的输出改成:logger.debug("这是个hello的debug日志!!"),这个时候重启再调用,发现后台并不会有任何输出,这原因是日志级别在作祟。默认情况下Spring Boot配置的是INFO日志级别,也就是会输出INFO级别以上的日志(ERROR、WARN、NFO)。

如果需要Debug 级别的日志,在 src/main/resources/application.properties中配置debug=true,此外配置logging.level.* 来具体输出哪些包的日志级别。

例如:

#  日志级别配置
logging.level.root=INFO
logging.level.org.springframework.web=DEBUG
logging.level.com.chj.controller=DEBUG

这个时候,包括springframework.web以及com.chj.controller的info\debug日志都可以输出来了。

1.2、日志文件

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

# 日志输出
logging.path = D:\\tmp\\testlog
logging.file = test.log

注意:

如果只配置logging.path,在/var/tmp文件夹生成一个日志文件为spring.log;如果只配置logging.file,会在项目的当前路径下生成一个xxx.log日志文件。这里有一个坑,logging.path和logging.file都配置了,只会有logging.file生效,所以如果要指定日志生成的具体位置使用logging.file配置就好。

在application.properties中配置:logging.file =F:\\log\\testlog,这样在F盘的相应位置出现日志文件。

2、log4j2方式实现

在spring-boot-dependencies POM中搜索spring-boot-starter-log4j2,发现Spring boot父Pom中自己提供了这个依赖,于是我们加入如下jar依赖:

修改pom.xml文件:

<!-- 由于默认使用logback在扩展log4j2之前先要把logback移除,日志使用跟上面logback一样 -->
<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>

注意:

由于默认使用logback在扩展log4j2之前先要把logback移除,日志使用跟上面logback一样。

3、log4j方式实现

如果不只为了学习集成log4j,在工作是最好不要使用log4j,毕竟有了log4j2,也有了logback使用log4j就是吃饱了撑着。在springboot中并没有提供对log4j这个依赖的支持,因此要使用它配置起来还是挺麻烦的。在mvnrepository.com 中发现log4j最新版本spring-boot-starter-log4j是1.3.8.RELEASE。

修改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-log4j</artifactId>
        <version>1.3.8.RELEASE</version>
    </dependency>

在classpath下增加log4j.properties文件:

log4j.rootCategory=INFO, stdout, file, errorfile
log4j.category.com.chj=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
# com.chj下的日志输出
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);

4、使用AOP统一日志处理

为了防止在工作中经常在代码中加入大量的日志处理代码,在实际项目开发中,一般使用AOP统一完成日志处理工作,修改pom文件引入springboot对aop的支持:

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

新增AOP日志处理类:

@Aspect
@Component
public class WebLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    @Pointcut("execution(public * com.chj.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);
    }
}

启动访问接口hello,日志打印结果如下:

URL : http://localhost:8080/hello

IP : 0:0:0:0:0:0:0:1

这是个hello的info日志!

这是个hello的debug日志!!

RESPONSE : hello

六、Spring Boot热加载/部署

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

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

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

修改pom文件增加引用:

<!--  热加载/部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

修改properties文件:

如果使用的Thymeleaf模板,那么请直接在application.properties中添加:spring.thymeleaf.cache=false

如果使用的FreeMarker模板,那么请直接在application.properties中添加:spring.freemarker.cache=false

1、IDEA中使用

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

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <!-- 如果不设置fork,那么不会restart,devtools热部署不会起作用-->
        <fork>true</fork>
    </configuration>
</plugin>

1.1、手动:

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

1.2、自动

1)File -> Settings -> Compiler,勾选 Build Project automatically

2)按快捷键Ctrl+Shift+Alt+/,选择1.Registry...

3)勾选 compiler.automake.allow.when.app.running 即可

 

这个时候修改JAVA文件或者模板文件都自动会生效。

2、编译,打包

快速入门进行到这里,其实已经差不多了,能应对绝大多数开发常见,接下来就是导包部署。

在pom文件中新增:

<!-- 编译,打包 -->
<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>

使用:mvn clean package 打包,java -jar springboot-basic-0.0.1-SNAPSHOT.jar运行。

 

3、war部署

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

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

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

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

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

@SpringBootApplication
@MapperScan("com.chj.dao")
@EnableTransactionManagement
public class WarApp extends SpringBootServletInitializer {
    public static void main(String[] args) {
        //启动类 定制化
        SpringApplication.run(WarApp.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(WarApp.class);
    }
}

使用:mvn clean package打包,把war包拷贝到tomcat webapps中,访问:

http://localhost:8080/springbootvip/hello

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值