spring及其整合


title: spring及其整合
date: 2020-08-01 16:31:16
tags: ‘srping’
categories: ‘spring’
copyright: true

spring入门

  1. 为什么要学习springBoot,spring是java企业版(java Enterprise Edition)的轻量级替代品,无需开发重量级EJB(Enterprise JavaBean),spring通过依赖注入和切面式编程,用简单的Java对象(POJO)实现了EJB的功能。但是随之而来的是重量级的配置文件,spring上古时代,全部Java对象都是使用xml注入,2.5时代产生了注解扫描,xml和注解并存,3.0时代,可以全部使用Java配置。但是复杂的配置需要在业务逻辑和配置文件中不断切换,编写配置逐渐占据了大部分的时间,同时依赖管理,版本冲突也是一项十分繁杂的工作。而springBoot的出现解决了上面的问题,springBoot基于约定大于配置的思想,开发人员只要按照Boot的约定书写就可以快速搭建spring项目,大大缩减了项目的周期
  2. spring的特点:开箱即用,无需xml配置,同时可以修改默认值来满足个性化配置,提供了大型项目中常见的非功能性配置,比如嵌入式服务器,安全,指标,健康检测,外部配置等等。springBoot并不是对spring的功能增强,只是提供了一种快速使用spring的方式
  3. spring的使用步骤
  • 创建maven工程,一个普通的maven工程就可以,(就是maven父工程,其他模块是子工程)
  • 添加起步依赖
<!--spring要求项目要继承SpringBoot的起步依赖spring-boot-starter-parent-->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artufactId>sprig-boot-starter-parent</artufactId>
	<version>2.3.2.RELEASE</version>
</parent>

<!--第二部分就是集成SpringMvc进行controller的开发,所以项目要引入web的启动依赖-->
<dependecies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
</dependecies>
<!--没有version是因为springBoot中是以功能为单位进行划分而不是以SpringMVC和mybatis等一个个具体的依赖进行划分的,功能单位的底层已经将springboot对应版本的这个功能所需的所有依赖全部集成了-->
  • 编写入口(spring引导类)
@SpringBootApplication//加上这个注解告诉spring这是引导类
public class MyspringBootApplication{
	public static void main(){
		SptingBootApplication.Run(MyspringBootApplication.class);//运行当前引导类的字节码文件,就是将程序入口转入springBoot
	}
}
  • 编写controller
@Controller//controller表明这是表现层
public class QuickController {

    @RequestMapping("/quick")//路径映射
    @ResponseBody//使用输出流写到浏览器上 
    public String quick(){
        return "hello springBoot!";
    }
}

小知识

  1. spring热部署,这样就不用每次重新启动spring,直接刷新就可以

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

添加依赖之后会发现还是不能热部署,这是因为IDEA不会自动编译,需要进行设置,
请添加图片描述

在设置中搜索编译器,英文版搜索complier,选择自动编译选项,compile java project automatically
选择之后更改之后会自动进行刷新,但是需要等一段时间,时间并不会比冷启动快多少
请添加图片描述

选择shift+ctrl+alt+/,选择第一个选项(注册或者register),选择第一个选项。就可以自动编译了
2. IDEA快速创建spring工程,在maven上面一个选项选择spring Initializer,进入之后设置编译的jar包版本,我用的是8,选择spring版本,我用的是2.3.2.RELEASE,之后再勾选自己想要的功能模块就可以了

springboot原理分析

起步依赖-parent

  1. parent内部点进去之后发现里面规定了application配置文件的存放位置,和编译包,以及各种内置的插件,而parent继承了dependencies,dependencies中规定了需要用到的各种jar包的版本。

web功能依赖

各种功能模块中都是定义的各种依赖的版本和插件,

自动配置分析

  1. 点进springBootApplication,中发现其中有以下几个注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration//这个与Configuration等价,定义当前类为spring配置类
@EnableAutoConfiguration//这个是允许自动配置
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}//表示当前配置类的上一级包的所有包及其子类都会被扫描
)}
)

点进@SpringBootConfiguration,里面有以下几个注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class//将springBootConfiguration等价于Configuration注解
    )
    boolean proxyBeanMethods() default true;
}
  1. 点击EnableAutoConfiguration,这个就是允许自动配置的开关。点进去之后又几个注解
@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 {};
}

点进去AutoConfigurationImportSelectior


public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

//找到getAutoConfigurationEntry

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//这个就是找到默认配置文件的方法
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

//点击getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

//默认配置文件默认是在当前类的(org.springframework.boot.autoconfigure)
//就是在META-INF下的spring.factories文件,在外部库中

//点进去spring.factories
//spring.factories中定义了许多的自动配置类,
//配置类中有下面的注解,就是引入自动配置文件,就在spring.factories的下面。
@EnableConfigurationProperties({ServerProperties.class})

//
{
      "name": "server.port",
      "type": "java.lang.Integer",
      "description": "Server HTTP port.",
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
      "defaultValue": 8080
    },
    就是定义端口
  1. 可以对默认配置进行覆盖,变成我们自己的配置,之前在starter-parent里面可以看到配置文件的名称和位置
<resource>
        <directory>${basedir}/src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
          <include>**/application*.yml</include>
          <include>**/application*.yaml</include>
          <include>**/application*.properties</include>
        </includes>
      </resource>

上面规定了spring配置文件要放在resource目录下,一般就是引导类所在的模块下的resource,可以看到有yml,yaml,prooperties三种配置文件格式,后面的文件格式会覆盖前面的文件格式,那么现在来尝试个性化我们的配置,

server.port=8081//将端口号修改为8081

这样端口号就配置好了

  1. 点击run方法,发现里面是
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }
  1. 点击查看SpringApplication对象
Assert.notNull(primarySources, "PrimarySources must not be null");//断言primarySouece不为空
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));//将主配置存入集合中
        this.webApplicationType = WebApplicationType.deduceFromClasspath();//判断web工程的类型
  1. 点进WebApplicationType.deduceFromClasspath()
static WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
            return REACTIVE;//如果上面这三个类都不存在说明这个web工程是reactive风格的,这是spring5的新特性,响应式编程,是一套完全不同于之前的web编程方式
        } else {
            String[] var0 = SERVLET_INDICATOR_CLASSES;
            int var1 = var0.length;

            for(int var2 = 0; var2 < var1; ++var2) {
                String className = var0[var2];
                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                    return NONE;
                }
            }

            return SERVLET;//否则就是普通的web工程
        }
    }

    static WebApplicationType deduceFromApplicationContext(Class<?> applicationContextClass) {
        if (isAssignable("org.springframework.web.context.WebApplicationContext", applicationContextClass)) {
            return SERVLET;
        } else {
            return isAssignable("org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext", applicationContextClass) ? REACTIVE : NONE;//如果两个都不符合就是普通的jar工程
        }
    }
  1. 接着将判断好的工程类型存储并返回,进入下一行
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));//获取spring工厂实例

//点进工厂中
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();//获取当亲加载器
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));//获取工厂名字
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//利用反射方式创建实例
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
  1. 点进去loadFactoryName看它是怎么获取名字的
try {
      Enumeration<URL> urls = (classLoader != null ?//如果类加载器不为空,就用第一个方法否则第二个,但都是同样的
          classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
          ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
  1. 点进去FACTORIES_RESOURCE_LOCATION
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";//命运石之门,世界线收束,和上面对上了,
  1. 这个配置文件在springboot-autoConfigurationjar包下的spring.properties中,它下面还有许多自动配置好的类
//我们以webmvcConfiguration举例子
@Bean//内部资源解析器的配置,前缀后缀都帮我们配置好了,就是说配置了这个类就会生效里面的所有自动配置
        @ConditionalOnMissingBean
        public InternalResourceViewResolver defaultViewResolver() {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
        }
//当我们没有在spring中配置视图解析器时,就会由自动配置类(即上面那个)为我们自动创建并加入到spring容器中,但是如果我们自己配置了视图解析器,当前注解就会失效,会采用我们自己的配置。
/*
但是当我们只需要修改其中的一些配置而不想整个全部自己重新配置的时候,就显得有些复杂,但是万能的springboot早就准备好了,
this.mvcProperties.getView().getPrefix(),点进这个mvcProperties中,
@ConfigurationProperties(
    prefix = "spring.mvc"
)
这个就是配置的统一前缀,从那个获取前后缀的方法中可以看出,是从View这个属性中在获取Prefix这个属性,那么在application中就可以覆盖写为
spring: 
 mvc: 
  View:
    Prefix: /META-INF/Views
    suffix: .jsp
这样我们的修改部分配置就完成了,以后我们想修改其他配置就可以查找所在自动配置文件的位置,进行修改即可。
*/


@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(//这个注解表示只有在web工程是servlet类型时才会执行
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})//只有有这些类才会执行
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
  1. 总结:spring为我们提供了默认配置,而要让自动配置生效的有两个条件,1. 引入相关依赖,2.自己没有配置Bean
    部件:
  • 启动器:如果我们不想自己配置,只需要引入依赖就可以,而依赖版本也无需我们操心,只要引入springboot的starter(启动器),就会为我们自动进行依赖管理和版本控制,因此玩springboot的第一件事就是找启动器,spring提供了大量的默认启动器。而spring提供的所有启动器命名都是spring-boot-starter-功能,除了第三方制作的依赖会以第三方作为开头。
  • 全局配置: 玩springboot的第二件事就是在全局配置文件中写我们自己的配置来覆盖springboot的默认配置,不需要记住,只需要打出和你想要的相关的关键词,springboot就能智能提示。

spring配置文件

spring配置文件类型和作用

  1. yml是比较通用的配置文件,可以被c,c#,java,python等多中语言所识别,比xml更加通用,其次,yml中没有自定义标签,以一种类似于json的格式进行书写,免去了xml繁重的标签书写,并且更加有利于阅读,并且yml可以注入集合和对象,properties根本不行。
  2. 配置方法
  • 配置普通数据
name: zhangsan//冒号后面要有空格
  • 配置对象,使用缩进关系配置,缩进空格没有要求随便缩进多少,但是只有缩进同样的空格才表示是同一级,
person:
 name: zhangsan
 age: 10
 addr: fdsa

#比如之前的server.port可以变成
server:
 prot: 8081

#此外还可以在一行内进行配置
person: {name: zhangsan,age; 18,addr: beijign}
  • 配置集合,数组
# 集合
city:
 - bejing
 - tianjing  
 - sahnghai

# 0120
 
 行内方式
city: [beijing,tianjing,chongqing,shagnhai]

# 对象集合
student:
 - name: tom
   age: 15
   addr: shanghai
 - name: hai
   age: 656
   addr: fda

student: [{name: tom,addr: fdaa},{name: afds,addr: fdsa}]
  1. 有些属性是spring固有的,在程序中可以直接引入,但是也有一些是没有的,是我们自定义的,这就需要使用@Value注解获取
@Value("${name}")
private String name;
//其实已经注入了sprig容器中,只要用el表达式取出来就可以,如果使用value="xxx"是取不出来的
  1. 但是像那样一个个注入是非常繁琐的,我们就可以使用@ConfigurationProperties注解将配置文件中的对象或集合全部注入,但是要在类中定义相应的属性,并且还要提供getset方法。我们在写注解@ConfigurationProperties时会发现报错Spring Boot Configuration Annotation Processor not configured,但是并不会影响我们的额运行,这个错误是由于我们没有配置configuration-processer这个依赖产生的,在pom中添加这个依赖就可以
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<!--这个的作用就是当我们在类中定义好属性和前缀名之后就可以在写配置文件时自动提示-->
  1. 还有另一种方法,可以帮我们自动生成getset方法,
//首先要引入依赖
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok<artifactId>
</dependency>
//这个依赖是编译时的依赖,自动生成getset方法,在使用时直接加@Data注解
//并且这个依赖也是编译依赖,

@Data
@ConfigurationProperties(prefix = "jdbc")//写前缀
public class jdbcProperties{
  private String name;
  private String url;
  private String password;
}

@Configuration
@EnableConfigurationProperties(jdbcProperties.class)//将配置类的字节码传入,告诉哪个是配置类
public class jdbcConfig{

  @Bean
  public Datasource dataSource(jdbcProperties prop){
    DruidDataSource datasource = new DruidDataSource();
    datasource.setDriverClassName(prop.getDriverClassName());
    //以下就是通过配置类的get方法将属性全部取出
  }
}
  1. 下面来一种更优雅的方式
@Data
//把这个注释注掉之后注入就会失败
//@ConfigurationProperties(prefix = "jdbc")//写前缀
public class jdbcProperties{
  private String name;
  private String url;
  private String password;
}

//在具体方法上进行注入,加上@ConfigurationProperties(prefix = "jdbc")
@ConfigurationProperties(prefix = "jdbc")
public Datasource datasource(){
  //会自动寻找配置文件中的set方法和配置文件中的属性相同的
  return new DruidDataSource();
}
  1. 配置文件也是有优先级别的,分别是properties>yaml>yml

springboot整合其他技术

整合mybatis

  1. 添加mybatis的起步依赖
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>xxx</version>
</dependency>
<!--从他的前缀可以看出来是mybatis提供的jar包而不是spring的jar包-->

<!--数据库连接依赖-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--版本不用写,已经在springboot中规定好了-->
  1. 在application配置文件中写连接信息
spring.datasource.driverClassName=com.mysql.jabc.Driver
spring.datasource.url=jdbc://127.0.0.1:3306/test?useUnicode=true&charcterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=admin
//这些在springboot中都已经有了约束,可以在autoConfiguration中找到
  1. 建立实体类
  2. 配置映射Mapper,在resource下建立mapper文件夹,建立位每个到接口配置的独立配置文件
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cuit.cs.mapper.User">
  <select id="queryList" resulyType="user"><!--这个resultType肯定使用了别名-->
    select * from user
  </select>
</mapper>
  1. 建立接口
public interface UserMapper{
  public List<User> queryList();
}
  1. 要将mybatis和springboot产生依赖,在mybatis的autoConfiguration的json文件中找,并且写在applicaiton配置文件中
mybatis.type-aliases-package="cuit.cs.domain"<!--解释了前面resultType-->
加载Mybatis映射文件
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
  1. 下面介绍另一种方式,通用Mapper。这个适用于只要用单表查询,不涉及多表联合查询的项目。
    在application.yml中配置mybatis,
mybatis:
  configuration:
    map-underscore-to-camel-case: true#这个是开启驼峰命名
  mapper-locations: mapper/*.xml#这个是指定mapper文件的位置,但是我们这次适用通用Mapper,只涉及单表操作,就不要写mapper.xml了,但是多表的复杂操作还是要写的。
  type-aliases-package: cuit.cs.pojo#配置别名包
  1. 下面配置扫描的接口位置,在引导类上加@MapperScan(“cuit.cs.mapper”),就能扫描mapper接口
  2. 下面来介绍通用Mapper怎么(一查才发现,就是tkmybatis啊,这个就是类似于jpa,用方法来进行单表的增删改),首先引入依赖
<dependency>
  <groupId>tk.mybatis</groupId>
  <artifactId>mapper-spring-boot-starter</artifactId>
  <version>xxx</version>
</dependency>
  1. 是mapper继承Mapper<pojo类>,注意哦,引入tk.mybtias依赖之后,tkmybatis中已经引入了mybtias和hikariCp,因此这两个依赖我们就可以删除了,此外,tkmybaits还会帮我们将驼峰开启,因此在配置文件中不再需要开启驼峰了,MapperScan也要由mYbaits的换成tkMybatis的MapperScan。
  2. 还没有结束,tkMybatis还不知道我们的表名叫什么,并且也不知到主键,还需要我们到pojo中取设置,

@Table("tb_user")
@Data//这个是自动帮我们生成getset方法的
public class User{

  @Id
  @KeySql(userGenertedKeys = true)//设置主键策略自增,这就是jpa啊喂
  private Integer id;
  private String name;
  private float money;
  @Transient//表示这是一个临时字段,不需要持久化到sql字段
  private String hanahn;
}

整合junit

  1. 和之前spring集成的方法类似都是用spring提供的运行接口,boot整合就用boot提供的接口
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootMybatisApplication.class)//引导类
//这样就可以使用junit测试了

整合sptingDataJpa

整合redis

springboot的扫描注解

  1. 之前我们的ssm工程都是使用springMVC负责扫描web层,spring扫描dao和service层,这实际上是spring的父子容器,容易出现一些意料之外的问题,而我们的springboot的@SpringBootApplicaiton中有一个@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
    ), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}//表示当前配置类的上一级包的所有包及其子类都会被扫描
    )},这个注解会扫描引导类所在的包及其子包的所有注解,放在同一容器中管理

springboot实战

  1. 使用IDEA自带的springbootInitializer进行快速搭建springboot工程,勾选web功能,并且引入插件lombok
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>
  1. 有了lombok就可以使用以下几个注解
  • @Data: 自动提供getter和setter,hashCode,equals,toString等方法
  • @Getter: 自动提供getter方法
  • @Setter: 自动提供setter方法
  • @Slf4j: 自动在bean中提供log变量,其实用的是slf4j的日志功能
  1. 在pojo类的上面加@Data注解,自动生成getset方法,省去很多麻烦
  2. 开始集成springMVC,其实不用整合,毕竟是自家的全家桶,只是需要我们进行一些个性化的配置覆盖,springMVC的大部分配置可以使用boot提供的默认配置,需要我们自己配置的只有几个,端口,视图解析器,资源拦截器
server:
  port: 8081
#修改端口

#但是我们不配视图解析器,因为springboot不支持jsp,并且也没有META-INF文件夹,
#下面配置资源拦截器
spring:
  mvc:
    servlet:
      path: "*.html"  #yml不支持*,要用双引号表示这是字符串

#进行日志级别控制,
logging:
  level: 
    cuit.cs: debug
    org.srpingframework: debug
#level需要map类型的数据,键是包名,值是控制级别
  1. springboot访问静态资源(图片,css,js),以前这些资源是放在webApp下的,但是springboot下面没有webApp目录,这就没有办法获得静态文件,但是我们可以找springMVC的自动配置jar包,里面有读取的配置文件的位置
//打开resource.properties,这里面就是存放配置文件的地方
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
//可以看到有四个地方,但是classpath:/resources/"这个位置一般是不用的,因为classpath就是resources目录,而classpath:/resources/就是在resources目录下在新建一个resources文件夹。但是这样容易混淆,所有不适用,一般我们用static
//但其实现在都流行前后端分离,后端实际上根本不需要接触静态资源,只需要提供接口。
  1. springMVC拦截器,首先新建一个自定义拦截器继承HandlerInterceptor接口,
package cuit.cs.intecotor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器
 */
@Sl4j//有了这个注解,就不用在去写private static final Logger log = LoggerFactory.getLogger(MyInterceptor.class);,注解会自动生成,
//也是lombok插件的功能
public class MyInterceptor implements HandlerInterceptor {

    //因为springboot的日志要输出日期,线程,调用的类,类所在位置,因此就需要传入类的字节码文件才能知道是那个类调用的。
    private static final Logger log = LoggerFactory.getLogger(MyInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("preHandle is running");//有了日志输出就不用再sout,在控制台中输出了。
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.debug("postHandle is running");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.debug("afterCompletion is running");
    }
}

  1. 但是这仅仅只是定义了一个我们自己的拦截器,还需要配置,以前在springMVC中是在xml中配置,但现在是springboot,已经使用java全注解配置了。
    注意,如果你仅仅是想保留一些springMVC的默认配置,修改少部分配置,应该让一个类实现WebConfigurer,并且加上@Configuration注解,如果你是想完全自定义一个MVC,那么加上@Configuration和@EnableWebMvc
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {//实现addInterceptors方法,由于这里我们配置的是拦截器,所以使用addInterceptor,
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}

配置连接池

  1. Druid(德鲁伊连接池,阿里巴巴提供),相较于DBCP(apache提供)和c3p0(Hibernate)而言,Druid能够监控没条sql语句的执行时间,访问次数,来确定哪条sql语句需要进行优化,并且提供数据库密码加密功能,毕竟密码写在配置文件中非常不安全。
  2. 但是最快的连接池是追光者(HikariCP),这是最快的连接池,c3p0和他比就是渣渣。是由日本开发的,由于性能十分优秀,spring已经默认支持HikariCp,只需要找spring提供的启动器就行,不需要像Mybatis一样使用myBaits提供的第三方启动器。

暂时要点

  1. 创建springBootinitializer时artifiId必须全部小写不然,会报错

  2. 折腾了我三个小时的springboot终于解决了,一开始时maven-plugin红色,下载不了,然后就把maven仓库中的springframework文件夹及其下的子文件夹全部删除了,准备重新引入依赖的,但是使用idea的springInitiazer快速创建springboot项目时,却出现了问题,使用的版本时2.3.1.RELEASE,使用之后发现外部库中只有jdk,其他没有任何包,在打开右边的maven,发现全是红线,后面后小字(omitted for duplicated),查了之后发现是版本冲突(黑人问号),springboot不就是用来解决依赖冲突的么,然后再删再下,根本不行,网上的资料几乎没有,但是看到好多把springboot版本降下来就能使用的,于是我也试了一下,2.1.5不行,还是失败,一直试到2.2.8.RELEASE,才终于成功了。太不容易了,没有办法,有时就会出一些莫名奇妙的错误。

  3. springboot整合mtbatis的核心就是将sqlSessionFactoryBean交由spring进行管理,但是一个个放进Ioc容器十分麻烦,就需要适用MapperScanConfiguer,或者@MapperScan注解,但是注解并不强大,复杂的操作还是要写在mapper文件中

  4. 无法访问静态资源,详情看这里,重写资源处理器。但是看其他人的项目不用重写也能访问,还是我太菜了,还是得好好看看springboot

  5. springboot2.3.0之后的版本中starter-web不再传递引入javax.validation依赖,需要手动引入依赖,这里,但是我之前没有成功,可能是因为我没有安装lombok插件,导致没有setget方法而不能使用验证,之前的thymeleaf没有办法拿到后台传的数据也就是这个原因,哎,学习新技术总会走一些这种低级的坑。

  6. springboot的表单验证不再使用jQuery进行验证,那样太烦,像上面一样使用validation依赖。

  7. 表单提交数据时是通过name属性封装到controller参数中的,因此就要求name属性的名字必须和controller中的参数名字相同,但是可以通过@requestParam注解将参数名称和name属性绑定起来。

  8. thymeleaf的动态url拼接,看资料

  9. thymeleaf拿到不同类型对象的中数据的方法,看这里

  10. 表单提交时出现了数据在地址栏出现的问题,这种问题是因为没有指定method属性为post,添加上这个属性就可以。但有时侯不写也可以。玄学,但是以后还是要养成习惯,写表单就要写方法,因为表单一般就是用来做post提交的,不会用来做request提交的。

  11. sprigboot中的重定向更多的是controller之间的相互跳转,这时参数的拼接是无法完成的,参数接受不到,但是使用RedirectAttributes就可以将参数存储,另一个controller就可以用requestParam拿到
    详情见

  12. thymeleaf中在th:href中传入多个参数是在参数括号中加逗号分割。看资料

  13. org.apache.ibatis.binding.BindingException: Parameter ‘userId’ not found. Available parameters are [id, title, param1, param2],报这个错是因为在dao中的方法中的参数名称和mapper。xml中的#{}的参数名称不同,这样mybatis就无法封装参数。处理方法和controller中参数名称和表单那么属性不同时的处理方法相同,都是使用注解将参数进行绑定。不过是注解不同而已,mybatis是@Param,spring是@RequestParam。

  14. resultType封装list类型只需指定list中么个元素的类型即可, 详见

  15. thymeleaf进行迭代器循环,和双重循环一样,嵌套即可, 详见,但是表格嵌套暂时不会,只会目录的嵌套,详见这里

  16. 有时会出现新添加的静态资源无法加载的情况,这时只需将idea关闭重启,让springboot重新扫描即可,可能就是没有扫描到才会这样。

  17. 以后要找前端资源可以去模板里面去找,那里面比网上找的全多了还有处理好了。

  18. 技术薄弱点:ajax,权限控制,thymeleaf动态标签和其他语法。分页,可以使用pagehelper

  19. RedirectAttributes只能在重定向的url后面拼接字符串,不能在返回视图时拼接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值