一、Spring Boot自动配置原理

spring boot中的@EnableAutoConfiguration注解的作用就是开启自动配置,正是因为开启了自动配置,开发者在使用spring boot的时候就不用再填写繁琐的的配置项了

1.自动配置原理
  1. spring boot 会根据开发者添加的依赖判断是否使用了某个技术,比如依赖中有DispatcherServlet,那就说明使用了spring mvc 技术
  2. spring boot 判断出开发者使用的技术之后,会从自动配置包( spring-boot-AutoConfigure )下的META-INF
    下的spring.factories文件中找到该技术的相关配置类
  3. spring boot 会加载这些配置类,如果配置文件写有相关的配置信息的话会将该信息读取到配置类的对象中,然后加载到spring 容器中,这样就完成了自动配置
2.源码分析

在spring boot的主类的上面添加了**@SpringBootApplication注解,该注解中包含了@EnableAutoConfiguration**注解,该注解的作用就是开启自动配置,

在**@EnableAutoConfiguration注解中@Import(AutoConfigurationImportSelector.class)引入了AutoConfigurationImportSelector**类。在该类中有一个selectImports方法,代码如下:

public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
       //通过该方法获取的数据,最终被转成数组返回
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    	//转成数组返回
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
  1. 上面中将autoConfigurationEntry.getConfigurations()转成数组返回了,该数据是通过getAutoConfigurationEntry方法返回的,我们进入到该方法内看下:
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    //这里获取了一个list类型的配置数据
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    configurations = removeDuplicates(configurations);
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}
  1. 在该方法中通过调用getCandidateConfigurations方法获取了一个list类型的配置数据,我们进入到该方法中:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
     //这里返回的是list类型的配置数据
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

3.上面是通过调用了loadFactoryNames方法来获取的list类型的配置数据,我们再进入到该方法内部:

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
     //这里返回的是list类型的配置数据
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
  1. 根据上面注释的地方,我们再进入到loadSpringFactories方法里面,在该方法中,可以看到会读取该文件中的内容:
META-INF/spring.factories
  1. 也就是说spring boot会读取该文件中的内容,在spring-boot-autoconfigure.jar包中的spring.factories文件里面,可以看到EnableAutoConfiguration配置了很多类。从配置文件中可以找到MultipartAutoConfiguration这个类,该类是文件上传的自动配置类,进入到这个类中,可以看到在类名上面加了下面注解:
//加入到spring容器中
@Configuration(proxyBeanMethods = false)	

//当前项目中要存在Servlet,StandardServletMultipartResolver,MultipartConfigElement这三个类
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })

//当前application配置文件中spring.servlet.multipart.enabled的如果没有配置,那么他的值是true
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)

//当前项目需要是一个web项目
@ConditionalOnWebApplication(type = Type.SERVLET)

//将配置文件类MultipartProperties加入到spring容器中
@EnableConfigurationProperties(MultipartProperties.class)
  1. 上面会将MultipartProperties这个类加入到spring容器中,我们打开这个类之后,可以看到里面的一些成员变量,这些成员变量就是可以在配置文件中配置的,如果我们没有配置,那么就会使用默认值:
/**
*在项目的配置文件中如要配置一些信息就输入前缀 spring.servlet.multipart
*会发现能点出来的配置信息都是这个类的成员变量
*/
@ConfigurationProperties(prefix = "spring.servlet.multipart", ignoreUnknownFields = false)
public class MultipartProperties {
    
	private boolean enabled = true;
	private String location;
	private DataSize maxFileSize = DataSize.ofMegabytes(1);
	private DataSize maxRequestSize = DataSize.ofMegabytes(10);
	private DataSize fileSizeThreshold = DataSize.ofBytes(0);
	private boolean resolveLazily = false;

二、Spring Boot 自定义起步依赖 start

1.创建autoconfigure模块
  • 创建一个autoconfigure模块,命名为monkey1024-spring-boot-autoconfigure
    添加下面依赖
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--为properties类生成相应的json文件
		加了这个在配置文件中就能有提示,可以.出来
	-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
  • 创建UserProperties类
@ConfigurationProperties(prefix = "monkey1024.user")
public class UserProperties {
    private String name;

    private String password;

    //get和set略
}
  • 创建UserService类
public class UserService {

    private UserProperties userProperties;

    public UserService(UserProperties userProperties) {
        this.userProperties = userProperties;
    }

    public UserService() {}
    public boolean validate() {
        if ("admin".equals(userProperties.getName()) && "123".equals(userProperties.getPassword())) {
            return true;
        }

        return false;
    }

}
  • 创建UserAutoConfiguration类
@Configuration
@ConditionalOnWebApplication//在web应用下启用
@EnableConfigurationProperties(UserProperties.class)//开启配置类
public class UserAutoConfiguration {

    @Autowired
    private UserProperties userProperties;

    @Bean
    @ConditionalOnMissingBean(UserService.class)//当容器中不存在该对象的时候创建
    public UserService addUserService() {
        return new UserService(userProperties);
    }
}
  • 创建spring.factories文件

根据之前源码分析,我们需要在resources下创建META-INF文件夹,在该文件夹下创建spring.factories文件,里面内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.monkey1024.UserAutoConfiguration //包名对应的自动配置类
2.创建starter模块

创建的starter模块是一个空的jar包,里面只是做依赖管理,使用者只需将starter引入即可使用。

创建一个starter模块,命名为monkey1024-spring-boot-starter

在starter模块中加入autoconfigure模块的依赖

<!--autoconfigure自动配置模块-->
    <dependency>
        <groupId>com.monkey1024</groupId>
        <artifactId>monkey1024-spring-boot-starter-autoconfigurer</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
3.创建测试模块
  • 创建测试web模块将上面的starter依赖导入。在配置文件中添加下面内容:
<!-- 启动器 -->
<dependencies>
  <!-- 引入自动配置模块 -->
  <dependency>
    <groupId>monkey1024</groupId>
    <artifactId>monkey1024-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </dependency>
</dependencies>

配置文件中

monkey1024.user.name=admin
monkey1024.user.password=123
  • 创建controller
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/validate")
    public String validate() {
        boolean validate = userService.validate();

        return validate + "";
    }
}

在浏览器中发出请求http://localhost:8080/validate 即可看到返回true

三、Spring Boot 操作数据库

一、集成 Druid
  • Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。
  • Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入
    了日志监控。
  • Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。
  • Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的
    数据源,我们来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控

1.添加上 Druid 数据源依赖。

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.24</version>
</dependency>

2、切换数据源;之前已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数
据源,但可以 通过 spring.datasource.type 指定数据源。

spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/learn?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    type: com.alibaba.druid.pool.DruidDataSource
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
      #druid 数据源专有配置
     initialSize: 5
     minIdle: 5
     maxActive: 20
     maxWait: 60000
     timeBetweenEvictionRunsMillis: 60000
     minEvictableIdleTimeMillis: 300000
     validationQuery: SELECT 1 FROM DUAL
     testWhileIdle: true
     testOnBorrow: false
     testOnReturn: false
     poolPreparedStatements: true
      #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
      #如果允许时报错 java.lang.ClassNotFoundException:
    org.apache.log4j.Priority
      #则导入 log4j 依赖即可,Maven 地址:
    https://mvnrepository.com/artifact/log4j/log4j
     filters: stat,wall,log4j
     maxPoolPreparedStatementPerConnectionSize: 20
     useGlobalDataSourceStat: true
     connectionProperties:
druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
二、 配置 Druid 数据源监控(续上)

Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提
供了一个默认的 web 页面。

所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理:

@Configuration
public class DruidConfig {

    /**
     * 绑定全局配置文件中的 druid 数据源属性到
     * com.alibaba.druid.pool.DruidDataSource从而让它们生效
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }

    //配置 Druid 监控管理后台的Servlet;
	//内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
    //配置后台监控管理
    @Bean
    public ServletRegistrationBean statViewServlet(){

        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
        Map<String, String> initParams = new HashMap<>();
        initParams.put("loginUsername", "admin");//后台管理界面的登录账号
        initParams.put("loginPassword", "123456");//后台管理界面的登录密码
        initParams.put("allow", "");//后台允许谁可以访问,为空或者为null时,表示允许所有访问

        bean.setInitParameters(initParams);//设置初始化参数
        return bean;
    }
}

配置完毕后,我们可以选择访问 : http://localhost:8080/druid/login.html

配置 Druid web 监控 filter 过滤器

//配置 Druid 监控 之 web 监控的 filter 
//WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
@Bean
public FilterRegistrationBean webStatFilter() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new WebStatFilter());
    //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
    Map<String, String> initParams = new HashMap<>();
    initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
    bean.setInitParameters(initParams);
    //"/*" 表示过滤所有请求
    bean.setUrlPatterns(Arrays.asList("/*"));
    return bean;
}

druid监控在开发中可以这样配置

server:
  port: 8080
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/xinguan?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=CTT
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 下面为连接池的补充设置,应用到上面所有数据源中
      # 初始化大小,最小,最大
      initial-size: 5
      min-idle: 5
      max-active: 20
      # 配置获取连接等待超时的时间
      max-wait: 60000
      stat-view-servlet:
        enabled: true
        login-username: root
        login-password: 123456
        allow:
        deny:
        url-pattern: /druid/*

访问登陆:http://localhost:8080/druid/login.html

三、集成MyBatis

1.添加依赖

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

2.修改配置文件

spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/learn?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    type: com.alibaba.druid.pool.DruidDataSource

mybatis:
  # 注意:对应实体类的路径
  type-aliases-package: com.tong.pojo
  #指定myBatis的核心配置文件与Mapper映射文件
  mapper-locations: classpath:mapper/*.xml
  
#打印日志
logging:
  level:
    com.tong.dao: debug

四、Spring Boot 配置拦截器

自定义一个普通的拦截器

这里就跟以前一样创建一个普通的拦截器

  1. 在config包下创建一个InterceptorConfig类,并实现HandlerInterceptor接口
/**
 * 自定义拦截器
 */

public class InterceptorConfig implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		//获取Session中的值,在登录成功时把用户名username放进去
        Object loginUser = request.getSession().getAttribute("username");
		//如果Session的值为空,跳回登录页面
        if (loginUser==null){
            request.setAttribute("msg","没有权限请先登录!");
            request.getRequestDispatcher("/login.html").forward(request,response);
            return false;
        }else {
            return true;
        }
    }
}
  1. 在config包下创建一个MyMvcConfig类,实现WebMvcConfigurer接口,并在类上添加@Configuration注解 这样会被spring容器创建管理 。这个接口用于扩展你springmv的一些配置,以前都是在web.xml中配置,现在spring boot内置了,一些配置只能这样配置。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    //视图控制,用于视图跳转
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //addViewController是跳转的url
        //setViewName是跳转的视图后缀
        registry.addViewController("/").setViewName("login");
        registry.addViewController("/login.html").setViewName("login");
    }

    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new InterceptorConfig())
                .addPathPatterns("/**")//拦截所有的请求
            	//不拦截的请求,有时还要配置不拦截一些静态资源的文件
                .excludePathPatterns("/login.html","/","/login");
    }
}
  1. controller
@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;
    
	//登录
    @RequestMapping("/login")
    public String login( String username, String password, HttpSession session,Model model){

        User login = studentService.login(username);//通过用户名查询数据库
      	//如果不为空,就添加到session中
        if (!login.getPassword().isEmpty()&&login.getPassword().equals(password)){
            session.setAttribute("username",username);
            //重定向到首页controller
            return "redirect:/index";
        }else {
            return "login";
        }
 }
  1. 打来浏览器访问首页 http://localhost:8080/index ,提示请先登录

spring boot用shiro还是spring se_spring

五、Spring Boot 配置过滤器

  1. 创建MyFilter类,实现 Filter 接口
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("进入filter过滤器");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
  1. 在MyMvcConfig中添加 或者 新建一个 FilterConfig 类
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean myFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean(new MyFilter());//注册一个Filter
        registration.addUrlPatterns("/*");//过滤所有的请求
        return registration;
    }
}

六、Spring Boot集成 Thymeleaf

Spring Boot 官方推荐使用

使用thymeleaf创建的html模板可以在浏览器里面直接打开(展示静态数据),这有利于前后端分离。 功能类似以前的Jstl

第一个thymeleaf程序
  1. 添加thymeleaf依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

使用thymeleaf 的注意事项:

  1. 在开发阶段,建议关闭thymeleaf的缓存
spring.thymeleaf.cache=false
  • thymeleaf会对html中的标签进行严格校验,如果html标签缺少结束标签的话,thymeleaf会报错,我们可以通过下面方式去除thymeleaf的校验,添加依赖:
<dependency>
      <groupId>net.sourceforge.nekohtml</groupId>
      <artifactId>nekohtml</artifactId>
      <version>1.9.22</version>
</dependency>
  • 之后在spring boot配置文件中添加下面内容:
spring.thymeleaf.mode=LEGANCYHTML5
  1. 创建controller准备数据
@Controller
public class ThymeleafController {

    @RequestMapping("/hello")
    public String helloThymeleaf(Model model) {
        model.addAttribute("name", "jack");
        return "index";
    }
}
  1. 创建html页面

在resources/templates里面创建一个index.html,填写下面内容,注意添加这个

xmlns:th=“http://www.thymeleaf.org”

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Spring boot集成 Thymeleaf</title>
</head>
<body>
<p th:text="${name}">Spring boot集成 Thymeleaf</p>
</body>
</html>

Springboot使用thymeleaf作为视图展示的时候,我们将模板文件放置在resource/templates目录下,静态资源放置在resource/static目录下。

thymeleaf常用属性

th:each

该属性较为常用,比如从后台传来一个对象集合那么就可以使用此属性遍历输出,它与JSTL中的<c: forEach>类似,此属性既可以循环遍历集合,也可以循环遍历数组及Map

  • 循环list

controller构建list数据

@RequestMapping(value="/users")
public String selectAllUser (Model model) {
    ArrayList<User> userList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(i);
        user.setName("jack" + i);
        user.setPhone("13"+i+"11111111");
        userList.add(user);
    }

    model.addAttribute("userList", userList);
    return "user";
}

html,这里的userStat类似于jstl里面foreach的varStatus,可以获取到当前的迭代信息。

<table>
    <!--
可以省略userStat,默认会在user后面加上Stat,即userStat
-->
    <tr th:each="user,userStat : ${userList}">
    <tr th:each="user : ${userList}">
        <td th:text="${userStat.index}"></td>
        <td th:text="${userStat.count}"></td>
        <td th:text="${userStat.size}"></td>
        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
        <td th:text="${user.phone}"></td>
    </tr>
</table>

userStat 里面一些属性的含义:

index: 当前迭代对象的index(从0开始计算)
count: 当前迭代对象的个数(从1开始计算)
size: 被迭代对象的大小
current: 当前迭代变量
even/odd: 布尔值,当前循环是否是偶数/奇数(从0开始计算)
first: 布尔值,当前循环是否是第一个
last: 布尔值,当前循环是否是最后一个
  • 循环map

controller构建map数据

@RequestMapping(value="/usersMap")
    public String selectAllUserMap (Model model) {

        Map<String, User> userMap = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId(i);
            user.setName("jack" + i);
            user.setPhone("13"+i+"11111111");
            userMap.put(String.valueOf(i), user);
        }

        model.addAttribute("userMap", userMap);
        return "index";
    }

html,myMapVal.key相当于map的键,myMapVal.value相当于map中的值。

<div th:each="myMapVal : ${userMap}">
    <span th:text="${myMapValStat.count}"></span>
    <span th:text="${myMapVal.key}"></span>
    <span th:text="${myMapVal.value.name}"></span>
    <span th:text="${myMapVal.value.phone}"></span>
    <br/>
</div>

th:if

条件判断,比如后台传来一个变量,判断该变量的值,1为男,0为女:

<span th:if="${sex} == 1" >
    男:<input type="radio" name="sex"  th:value="男" />
</span>
<span th:if="${sex} == 0">
    女:<input type="radio" name="sex" th:value="女"  />
</span>

th:value

类似html标签中的value属性,能对某元素的value属性进行赋值,比如:

<input type="hidden" id="userId" name="userId" th:value="${userId}">
url表达式

语法格式如下:

<a th:href="@{/channel/page/add}">添加渠道 </a>

<!--对比普通的 a 标签-->
<a href="/channel/page/add">添加渠道 </a>

七、解决Spring Boot 静态资源被拦截问题

原因

在网上找了半天发现是springboot2.0才会出现的问题。

因为spring boot 2.x依赖的spring 5.x版本,相对于spring boot 1.5.x依赖的spring 4.3.x版本而言,针对资源的拦截器初始化时有区别,有兴趣请查看源码。

解决办法:
  1. 我们在拦截器的配置文件里添加静态资源路径以及设置不拦截的静态资源
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    //视图控制,用于视图跳转
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //addViewController是跳转的url
        //setViewName是跳转的视图后缀
        registry.addViewController("/").setViewName("login");
        registry.addViewController("/login.html").setViewName("login");
    }

     /**
     * 注册添加静态资源
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
    
    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new InterceptorConfig())
                .addPathPatterns("/**")//拦截所有的请求
            	//不拦截的请求,有时还要配置不拦截一些静态资源的文件
                .excludePathPatterns("/login.html","/","/login","/static/**");
    }
}
  1. 注意前端页面引用静态资源路径,不然出现404(本例前端模板是thymeleaf)
<head>
    <meta charset="UTF-8"/>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/>
    <script th:src="@{/js/jquery.min.js}"></script>
    <script src="/js/bootstrap.min.js"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
    <title>用户表</title>
</head>

八、 spring boot 开发中常用配置(通用)

server.port=8081     #配置端口号
server.servlet.context-path=/my   #访问前缀 此时在浏览器中访问要加多一个my前缀
spring.resources.static-locations=classpath:/static/ #配置静态资源的路径 默认的也可以不用配

#配置mybatis  
mybatis.type-aliases-package=com.tong.pojo #指定bean的包	   
mybatis.mapper-locations=classpath:mapper/*.xml  #指定mapper文件的位置

#配置spring
spring.application.name=demo  #项目名
#数据源 
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #阿里巴巴的druid数据库连接池
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #数据驱动	
spring.datasource.url=jdbc:mysql://localhost:3306/demo? useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

#查看sql语句日志
logging.level.com.tong.dao=debug
logging.level.root=info

其他配置说明:

# 1.mysql 驱动说明
`mysql8之后要添加时区配置serverTimezone=Asia/Shanghai,url要用有cj那个`

# 2.热部署
`用sprngboot的热部署要添加依赖,并且要把依赖中的optional设置为true,需要手动build一下才可以生效,快捷键 ctrl + F9`
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
</dependency>

# 3. 添加@MapperScan 注解
`在Application启动类中用@MapperScan("com.tong.dao")扫描dao包,这样就不用每次添加一个mapper类都要在类上添加@Mapper注解了,适用于批量

# 4.使用 lombok
`lombok 的用处,可以帮我们生成相应的get,set方法,除此之外equals,hashcode,toString方法也无需手动在源码中添加了只需要在pojo中的实体类添加 @Data 注解即可

# 5.开启事务
` 1.在启动类上添加注解 @EnableTransactionManagement 开启事务支持
` 2.在访问数据库的Service方法上添加注解 @Transactional 即可

# 6.使用thymeleaf 时要关闭缓存和去掉严格校验
`开发阶段,要关闭thymelear的缓存
spring.thymeleaf.cache=false
`去掉严格校验(还要加依赖)
<dependency>
      <groupId>net.sourceforge.nekohtml</groupId>
      <artifactId>nekohtml</artifactId>
      <version>1.9.22</version>
  </dependency> 
spring.thymeleaf.mode=LEGANCYHTML5

# 7.视图解析器默认后缀是.html

# 8.th:value=${stu?.name} 表示当后台传入的stu不为null时才会赋值

# 9.@ResponseBody 
`作用是将java对象转换为json格式数据

# 10.@CrossOrigin  
`解决跨域,因为vue的端口号和springboot的端口号不一致