出现spring、mybatis、springmvc框架能够帮助我们去解决在Servlet中大量重复代码的问题,但是他们又引入了新的问题,虽然能够帮我们简化重复代码的书写,但是要写很多的配置;springboot的出现就是为了解决这些框架大量配置的问题。
第一步,创建一个
quickstart
工程
第二步,引入依赖pom依赖
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
第三步,编写启动类
@SpringBootApplication
public class FirstSpringBootApplication { // FirstSpringBootApplication也会被纳入到IOC容器中
public static void main( String[] args) {
/**
* 启动springboot的项目,第一个参数是标注了 @SpringBootApplication 这个注解的类型
*/
ConfigurableApplicationContext ctx = SpringApplication.run(FirstSpringBootApplication.class, args);
// Stream.of(ctx.getBeanDefinitionNames()).forEach(System.out::println); // 可以拿到整个IOC容器中所有的Bean的名字
}
}
第四部,编写任意的
Controller
, 启动服务,即可实现访问。
将属性配置注入到Spring 的Bean中,在很多中间件中都需要去定义一些属性的,方式总共有四种:
第一种方式,@ConfigurationProperties 和 @Component 搭配使用,属性需要在
application.yml
中进行配置;
@ConfigurationProperties(prefix = "person")
@Component
public class Person {
private Integer id;
private String name;
private List<String> interests;
// setter and getter
}
# yaml 文件中内容
person:
id: 10
name: 李四
interests:
- movie
- sport
- read
第二种方式,@ConfigurationProperties 和 @EnableConfigurationProperties 搭配使用,但是要注意以下两点:
- @EnableConfigurationProperties 需要放在一个被纳入到 IOC 容器的Bean的头顶;
- @EnableConfigurationProperties 和 @ConfigurationProperties 不是在一起使用的;
- @EnableConfigurationProperties 的值是头顶加了 @ConfigurationProperties 这个类的 Class 类型的对象
@ConfigurationProperties(prefix = "person")
public class Person {
private Integer id;
private String name;
private List<String> interests;
// setter and getter
}
@SpringBootApplication
@EnableConfigurationProperties(Person.class)
public class FirstSpringBootApplication { // FirstSpringBootApplication也会被纳入到IOC容器中
public static void main( String[] args) {
/**
* 启动springboot的项目,第一个参数是标注了 @SpringBootApplication 这个注解的类型
*/
SpringApplication.run(FirstSpringBootApplication.class, args);
}
}
# yaml 文件中内容
person:
id: 10
name: 李四
interests:
- movie
- sport
- read
第三种方式,@PropertySource(“classpath: /config.properties”) 和 @Component 搭配使用,然后属性要使用 @Value 实现注入
@PropertySource(value="classpath:/config.properties", encoding = "utf-8")
@Component
public class User {
@Value("${user.id}")
private Integer id;
@Value("${user.nickname}")
private String name;
@Value("${user.interests}")
private List<String> interests;
//
}
第四种方式,@PropertySource 和 @ConfigurationProperties 、@Component 搭配使用,@PropertySource来指定外部资源; @ConfigurationProperties 指定前缀。不需要使用 @Value 来实现属性的注入
@PropertySource("classpath:/config.properties")
@ConfigurationProperties(prefix = "wx")
@Component
public class Pay {
private String appKey;
private String tradeId;
// setter and getter
}
logback和log4j的作者是同一人,log4j是同步记录日志,但是logback是异步的方式来记录日志的。
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan: 当配置文件被修改后, 将会被重新载入。
scanPeriod: 置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 输出到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 配置日志输出到控制台的格式 --> debug info warn error fatal
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -- %-4relative %-5level %logger{32} %thread -- %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 将日志记录到文件当中 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 基于时间和大小的的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名, 必须包含%i, 从1开始-->
<FileNamePattern>D:/logs/logback.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<!-- 最大20KB 超过最大值,会重新建一个文件-->
<maxFileSize>20MB</maxFileSize>
<!-- 所有的日志加起来最大的大小, 以它为基准 -->
<totalSizeCap>400MB</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %thread -- %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性。 -->
<root level="info">
<!-- 标识这个appender将会添加到这个loger。 -->
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</configuration>
第一步,引入依赖
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.5.RELEASE</version>
</parent>
<dependencies>
<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>2.2.0</version>
</dependency>
<!-- 替代 druid -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java7</artifactId>
<version>2.4.13</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
第二步,
application.yml
文件配置
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/es?serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
# 链接池的最大链接数量
maximum-pool-size: 20
# 链接池的最小链接数量
minimum-idle: 5
# 链接初始化的时候发送的sql, 进而验证sql是否有效
connection-init-sql: select 1
mybatis:
mapper-locations: classpath:org/example/**/*.xml
configuration:
# 控制日志打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
# 分页合理化, 当前页超过总页数,会查询最后一页
reasonable: true
Mybatis-plus 是 mybatis的增强版,但是其只适合单表操作,不影响 mybatis 现有的使用,对于单表操作我们可以不用书写 mapper 文件,但是如果存在多表或者复杂的查询还是需要定义 mapper 文件。
Mybatis-plus 在使用的时候,只需要在Mapper的接口上继承
BaseMapper<T>
.
- 根据id查询
// Integer String 都是 Serializable 的子类
// Goods goods = goodMapper.selectById(Serializable id);
Goods goods = goodMapper.selectById(2001);
- id的in查询
// List<Goods> list = goodMapper.selectBatchIds(Collection<? extends Serializable> ids);
List<Goods> list = goodMapper.selectBatchIds(Arrays.asList(2001, 2002, 2003));
- 查询所有
// List<Goods> list = goodMapper.selectList(Wrappre wrapper);
List<Goods> list = goodMapper.selectList(null);
- 多条件查询
// List<Goods> list = goodMapper.selectList(Wrappre wrapper);
// select * from t_goods where id >= 2001 and id < 2010 and promo_words like '%锅%';
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.le("id", 2010);
queryWrapper.ge("id", 2001);
queryWrapper.like("promo_words", "锅");
List<Goods> list = goodMapper.selectList(queryWrapper);
注解:
- @TableName() 当类名与表名不一致的时候,需要通过该注解来指定
- @TableField 当属性名与字段名不一致的时候,通过该注解来指定
- @TableId(type=IdType.AUTO) 表示注解由数据库来决定
第一步,引入依赖
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
</dependency>
<!-- 替代 druid -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java7</artifactId>
<version>2.4.13</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
第二步,
application.yml
文件配置
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/es?serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
# 链接池的最大链接数量
maximum-pool-size: 20
# 链接池的最小链接数量
minimum-idle: 5
# 链接初始化的时候发送的sql, 进而验证sql是否有效
connection-init-sql: select 1
mybatis-plus:
mapper-locations: classpath:org/example/**/*.xml
configuration:
# 控制日志打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
# 分页合理化, 当前页超过总页数,会查询最后一页
reasonable: true
过滤器与拦截器的区别?都可以实现资源的拦截与过滤,但是过滤是Servlet中的内容,拦截器是 SpringMVC 框架的内容,在使用上过滤器用来过滤所有的资源,但是拦截 器只是针对 Controller.
在 Servlet 阶段,书写过滤器的方式如下:
<filter>
<filter-name>firstFilter</filter-name>
<filter-class>org.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
第一步,写一个过滤器,实现 Filter 接口
第二步,配置过滤器
@Bean
public FilterRegistrationBean<FirstFilter> filterRegistrationBean() {
FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>();
// 设置过滤器
registrationBean.setFilter(new FirstFilter());
registrationBean.setName("firstFilter"); // 设置过滤器的名字
registrationBean.addUrlPatterns("/*"); // 针对哪些资源进行过滤
registrationBean.setOrder(11); // 数字越小,越先执行
return registrationBean;
}
springmvc中设置拦截器的方式:
<mvc:interceptors>
<mvc:interceptor>
<!-- classpath:org/exmple/两个星星/*.xml, 这种语法在spring中叫 ant 语法 -->
<mvc:mapping path="/user/**"></mvc:mapping>
<mvc:mapping path="/person/**"></mvc:mapping>
<mvc:exclude-mapping path="/user/edit"></mvc:exclude-mapping>
<bean class="org.example.interceptor.UserInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
第一步,编写拦截器,实现 HandlerInterceptor 接口
第二步,配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 创建拦截器的实例
UserInterceptor userInterceptor = new UserInterceptor();
registry.addInterceptor(userInterceptor)
.addPathPatterns(Arrays.asList("/goods/**", "/first/**"))
.excludePathPatterns("/first/test");
// .addPathPatterns("/user/**", "/person")
}
BeanFactory是SpringIOC容器的顶级接口,它也是IOC的容器,它规范了对IOC容器中Bean的一系列操作;
FactoryBean是一个对象,用来创建Spring容器中的Bean,在Spring中所有的代理对象都是通过该对象来生成的(代理对象的生成是Spring的第三级缓存中生成)。