史上最全SpringBoot的基础入门内容和使用方法
SpringBoot的概念
-
SpringBoot是Spring公司的一个顶级项目,与Spring Framework是一个级别的。SpringBoot实际上是利用Spring Framework 4自动配置特性完成的。
-
在编写项目时不需要编写xml文件。到现在,各种主流技术都提供了SpringBoot的启动器。
-
启动器?Spring框架在项目中的作用经常是整合各种其他技术,让其他技术使用的更加的便捷。SpringBoot的启动器实际上就是一个maven的依赖,一个依赖中包含了相关技术的jar包,还包含了该技术的自动配置,使得以前绝大数xml文件已经不需要再配置了,例如mybaist-config.xml、jdbc.properties、log4j.properties、applicationContext.xml、springmvc.xml等等的配置文件都无需再进行配置。但是还是需要在SpringBoot的配置文件中进行少量的配置。
-
Spring官方提供的启动器命名规则为** spring-boot-starter-xxx,而如果是第三方技术提供的启动器命名规则是:xxx-spring-boot-starter**
-
SpringBoot的本质就是Spring Framework,学习SpringBoot就是在学习如何整合其他技术
创建第一个SpringBoot的MVC项目
创建maven项目,使用jar的打包方式
默认就是jar的打包方式。如果默认不是的,自行选择。
在pom文件中引入SpringBoot依赖的两种方式,并引入web开发所需的启动器
通过继承的方式
<!-- 第一种:引入springboot的依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
</parent>
<dependencies>
<!-- spring web开发模式启动器,内包含web开发所需的jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
通过依赖的方式
<!-- 第二种引入SpringBoot依赖的方式:注意type和scope必须要为pom和import,记得注释掉其中一种 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.10.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>-->
创建一个Controller进行测试
@Controller
public class MyController {
@RequestMapping("/demo")
@ResponseBody
public String helloSpringBoot() {
return "hello Spring boot";
}
}
创建项目的包结构,并在最后一级的包之前的上一个包中创建SpringBoot的启动java类
/**
* 对了,这里会相当于有一个包扫描,扫描位置为该类所在包的子包。
*/
@SpringBootApplication
public class FristSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(FristSpringBootApplication.class, args);
}
}
项目的目录结构
访问测试
看到该URL可以知道,默认的path虚拟路径为 /
使用Springboot完成各类的技术整合
首先了解一下SpringBoot的配置文件
-
SpringBoot项目在启动的时候,会默认查找根路径resources(不唯一)下的application.properties或application.yml文件,读取其中的配置进行加载。
-
至于SpringBoot寻找配置文件的路径,以及配置文件的加载顺序,这里就不做深究,有兴趣的可以自行查询其他文章
-
以下有一篇文章由SpringBoot官方提供,展示了SpringBoot配置文件的各种能配置的基础属性。
SpringBoot配置属性介绍 -
示例:配置SpringBoot内置tomcat服务的端口号和path虚拟路径
-
重新运行FristSpringBootApplicaiton中的main方法并访问测试
SpringBoot整合Junit进行单元测试
引入SpringBoot官方提供的测试启动器
<!-- SpringBoot 单元测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
创建一个测试类,代码如下
// 告诉SpringBoot需要使用哪个单元测试的工具,这里使用Junit4
@RunWith(SpringJUnit4ClassRunner.class)
// 标识当前类为测试类。并且指定SpringBoot启动类的Class
@SpringBootTest(classes = FristSpringBootApplication.class)
public class MyTest {
@Autowired
private MyController myController;
@Test
public void test(){
System.out.println(myController.helloSpringBoot());
}
}
SpringBoot整合Mybaits并完成分页开发pageHelper
首先引入Mybaits提供的SpringBoot启动器以及PageHelper的启动器
对了,别忘了springboot提供的web启动器
<!-- 配置mybaits启动器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- 配置分页插件启动器 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>
<!-- SpringBoot的默认mysql驱动版本就是8,而我用的也是mysql8,用mysql5的可以自行添加版本信息 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
在SpringBoot的配置文件中进行如下配置
spring:
datasource:
# 注意改成自己的配置
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root
mybatis:
# 扫描你Mpper.xml文件所在的位置
mapper-locations: classpath:mapper/*Mapper.xml
编写一个Mapper、实体类、xml文件,具体存放位置后面会放一个项目结构图
public interface UserMapper {
List<User> findAll();
}
public class User {
private Integer id;
private String uname;
private String pwd;
}
<mapper namespace="com.it.mapper.UserMapper">
<select id="findAll" resultType="com.it.entity.User">
select * from t_user
</select>
</mapper>
启动类中给类加上@MapperScan("com.it.mapper")注解,这里面写自己的mapper层路径
编写一个测试类
// 告诉SpringBoot需要使用哪个单元测试的工具,这里使用Junit4
@RunWith(SpringJUnit4ClassRunner.class)
// 标识当前类为测试类。并且指定SpringBoot启动类的Class
@SpringBootTest(classes = FristSpringBootApplication.class)
public class MyTest {
@Autowired
private UserMapper userMapper;
@Test
public void test(){
PageHelper.startPage(2,1);
System.out.println(userMapper.findAll());
}
}
SpringBoot整合Druid数据源
介绍:
Druid是由阿里巴巴推出的数据库连接池。它结合了C3P0、DBCP、PROXOOL等数据库连接池的优点。之所以从众多数据库连接池中脱颖而出,还有一个重要的原因:就是它包含控制台记录操作日志。
引入Druid数据源的启动器
<!-- 配置Druid数据源的启动器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
在SpringBoot的配置文件中进行配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo1?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root
# 配置使用Durid的数据源
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 连接池的配置信息
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 配置DruidStatFilter
web-stat-filter:
enabled: true
url-pattern: "/*"
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
# 配置DruidStatViewServlet
stat-view-servlet:
url-pattern: "/druid/*"
# IP白名单(没有配置或者为空,则允许所有访问)
allow: 127.0.0.1,192.168.21.128
# IP黑名单 (存在共同时,deny优先于allow)
deny: 192.168.21.129
# 禁用HTML页面上的“Reset All”功能
reset-enable: false
# 登录名
login-username: admin
# 登录密码
login-password: 123456
在浏览器访问Druid的控制台(前提:启动项目)
SpringBoot整合LogBack
直接在resources目录下添加logback.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!--每分钟查看一下配置有没有变化,并重新加载-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义参数常量 -->
<property name="log.level" value="debug"/>
<property name="log.maxHistory" value="30"/>
<!--修改生成的日志所在文件夹-->
<property name="LOG_HOME" value="logs/"/>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- 控制台设置 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<!-- 转换成字符串并输出 -->
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- DEBUG ,根据文件的大小或者是时间来生成新的日志文件-->
<appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--生成日志文件名称-->
<FileNamePattern>
${LOG_HOME}/debug/%d{yyyy-MM-dd}.%i.log
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</FileNamePattern>
</rollingPolicy>
<!-- 转换成字符串并输出,并输出到文件里面 -->
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!--过滤器,只保留DEBUG相关信息-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- INFO -->
<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${LOG_HOME}/info/%d{yyyy-MM-dd}.%i.log
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</FileNamePattern>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!--过滤器,只保留 INFO 相关信息-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- ERROR -->
<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${LOG_HOME}/error/%d{yyyy-MM-dd}.%i.log
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</FileNamePattern>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<!--过滤器,只保留 ERROR 相关信息-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--logger需要关注哪个package,根据自己项目包名命名不同修改-->
<logger name="com.it" level="${log.level}" additivity="true">
<!--对其要输出的logger进行绑定-->
<appender-ref ref="debugAppender"/>
<appender-ref ref="infoAppender"/>
<appender-ref ref="errorAppender"/>
</logger>
<root level="info">
<appender-ref ref="consoleAppender"/>
</root>
<!--输出sql语句-->
<logger name="com.it.mapper" level="DEBUG"></logger>
</configuration>
SpringBoot整合JSP
(因为SpringBoot默认是不支持jsp的)所以需要引入如下依赖
<!-- jsp jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- 添加对jsp的支持 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
在main目录下创建一个目录,名叫webapp,并指定为web目录
在SpringBoot的配置文件中配置视图解析器
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
编写一个公共的JSP访问方法
@RequestMapping("/{url}")
public String url(@PathVariable String url) {
return url;
}
启动项目,测试运行
SpringBoot整合Thymeleaf
在原SpringBoot项目下添加Thymeleaf的启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在resoureces目录下创建文件夹 templates(因为默认templates的视图解析器就是这个位置)
该文件名不能随意更改
在templates目录下创建任意一个html,修改其命名空间,这里还对一些常用标签进行了示例
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf的学习与使用</title>
</head>
<body>
<!-- th:text :填充标签的内容信息,相当于js方法的innerText-->
<p th:text="你好呀"></p>
<!-- 从request作用域用获取数据 -->
<p th:text="${reqMsg}"></p>
<!-- 从session作用域用获取数据 -->
<p th:text="${session.sesMsg}"></p>
<!-- th:value 设置表单的value属性值时使用 -->
<p>
<input type="text" th:value="我是thymeleaf设置的默认值--对了这里也能使用el表达式" />
</p>
<!-- th:if 进行逻辑判断,如果为true则显示标签,否则不显示 -->
<p>
<span th:if="${reqMsg!=null}">如果reqMsg不等于null我就会显示</span>
</p>
<!--
th:each,对集合或数组进行遍历
这里写的item是每次遍历出来的值,
而这个state是一个对象,其中有4个属性
index:当前的索引,默认从0开始
count:当前遍历的个数,默认从1开始
size:当前遍历的list对象一共有几个元素
current:与item是一致的,都是每次遍历出来的值
-->
<ul>
<li th:each="item,state:${reqList}">
<span th:text='${"姓名:" + item + " --- 当前索引对象:" + state}'></span>
</li>
</ul>
<!-- th:href 为a标签添加链接,当然,也可以在link中使用,th:src同理 -->
<p>
<!--
默认会以项目名称作为基础路径进行查找,也会拼接上多层的请求转发的路径,例如该页面是用/user/demo访问的,
那么则普通的a标签超链接则会以 : 项目基础路径/user/aaa.js查找资源
-->
<a href="aaa.js">我是一个普通的超链接</a>
<!-- 始终以项目的基础路径进行查找,不会拼接上请求转发到该html的路径 -->
<a th:href="@{/aaa.js}">我是一个th:href设置的超链接</a>
</p>
</body>
</html>
声明控制器完成请求转发
@RequestMapping("/demo")
public String url(HttpServletRequest request, HttpSession session) {
request.setAttribute("reqMsg","request作用域的数据");
session.setAttribute("sesMsg","session作用域的数据");
// 存储一个List数据
List<String> list = Arrays.asList("zhangsan1","zhangsan2","zhangsan3","zhangsan4","zhangsan5");
request.setAttribute("reqList",list);
return "my";
}
thymeleaf默认错误页面
按照状态码来响应错误页面
- 在templdates路径下创建一个error文件夹,可以在error文件夹下创建: 状态码.html的页面,那么出现了状态码相同错误时,则会响应该html给浏览器。
- 例如在error文件夹中创建一个500.html,那么当浏览器访问服务器出现500错误时,就会跳转到该页面
- 当然,也可以进行模糊匹配
- 当出现5开头的错误时,显示页面可以命名为5xx.html
- 当出现4开头的错误时,显示页面可以命名为4xx.html
统一错误显示页面
- 在templdates文件夹下创建一个error.html
- 当出现的状态码匹配不到error文件夹下的错误页面时,会显示error.html作为错误显示页面
运行测试
SpringBoot整合Quartz
引入quartz提供的springboot启动器,如果需要进行持久化(驱动、jdbc等)
<parent>
<artifactId>spring-boot-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
编写一个SpringBoot启动类
@SpringBootApplication
public class SpringBootQuartzApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootQuartzApplication.class, args);
}
}
编写SpringBoot的配置文件,在resources目录下
spring:
datasource:
# 注意改成自己的配置
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/quartz?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root
quartz:
jdbc:
initialize-schema: never # 永不重建数据表
job-store-type: jdbc # 设置持久化
# properties: 可以定义一些自定义的属性,可用于配置集群、rmi等
编写job任务类,继承QuartzJobBean类,这里可以直接使用依赖注入
public class MyJob extends QuartzJobBean {
/**
* 这里的话博主随便写了一个User类,添加了@Component注解
*/
@Autowired
private User user;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("我是springboot整合quartz后的一个任务 " + user);
}
}
添加任务
@RunWith(SpringJUnit4ClassRunner.class)
// 标识当前类为测试类。并且指定SpringBoot启动类的Class
@SpringBootTest(classes = SpringBootQuartzApplication.class)
public class MyTest {
@Autowired
private Scheduler scheduler;
@Test
public void addJob() throws SchedulerException, InterruptedException {
scheduler.start();
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class)
.withIdentity("job1","g1")
.build();
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1","g1")
.forJob(jobDetail)
.startNow()
.withSchedule(
SimpleScheduleBuilder.repeatSecondlyForever(2)
).build();
scheduler.scheduleJob(jobDetail, trigger);
Thread.sleep(10000);
}
}
修改任务的触发(修改Trigger)
/**
* 重新调度job,使用新的触发器。
* @throws SchedulerException
* @throws InterruptedException
*/
@Test
public void rescheduleJob() throws SchedulerException, InterruptedException {
TriggerKey triggerKey = TriggerKey.triggerKey("trigger1","g1");
Trigger newTrigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger2","g1")
.startNow()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1))
.build();
// 此操作会替换之前在数据库中的Trigger
scheduler.rescheduleJob(triggerKey,newTrigger);
Thread.sleep(10000);
}
删除任务
@Test
public void deleteJob() throws SchedulerException, InterruptedException {
JobKey jobKey = JobKey.jobKey("job1","g1");
scheduler.deleteJob(jobKey);
}
暂停任务
@Test
public void pauseJob() throws SchedulerException, InterruptedException {
JobKey jobKey = JobKey.jobKey("job1","g1");
scheduler.pauseJob(jobKey);
}
开始暂停的任务
/**
* 开始暂停的任务
* @throws SchedulerException
* @throws InterruptedException
*/
@Test
public void resumeJob() throws SchedulerException, InterruptedException {
JobKey jobKey = JobKey.jobKey("job1","g1");
scheduler.resumeJob(jobKey);
}
查询当前所拥有的任务(任务管理后台会用到)
/**
* 查询任务
* @throws SchedulerException
* @throws InterruptedException
*/
@Test
public void selectJob() throws SchedulerException, InterruptedException {
// 获取到所有的组
GroupMatcher<JobKey> tGroupMatcher = GroupMatcher.anyGroup();
// 通过组获得到对应的JobKey
Set<JobKey> jobKeySet = scheduler.getJobKeys(tGroupMatcher);
// 遍历JobKey
for (JobKey jobKey : jobKeySet) {
// 通过jobKey获取到其触发器
List<? extends Trigger> triggerTriggerList= scheduler.getTriggersOfJob(jobKey);
System.out.println("-------------------------------");
for (Trigger trigger : triggerTriggerList) {
System.out.println("当前触发器的名称为:" + trigger.getKey().getName());
System.out.println("当前触发器的组为:" + trigger.getKey().getGroup());
System.out.println("当前触发器的状态为:" + scheduler.getTriggerState(trigger.getKey()));
// 将当前触发器转换为Cron触发器
CronTrigger cronTrigger = (CronTrigger) trigger;
System.out.println("当前触发器的Cron表达式:" + cronTrigger.getCronExpression());
}
}
}
SpringBoot的异常处理
SpringBoot除了设置错误页面,还可以通过注解的方式实现错误处理。
在控制器类中添加任意一个方法,结合@ExceptionHandler。但是只能对当前控制器中方法出现异常进行解决。
这里示例的是处理ArithmeticException异常
@ResponseBody
@ExceptionHandler(ArithmeticException.class)
public String errorByZeroHandler(Exception e){
return "出现了异常" + e.getMessage();
}
定义一个以@ControllerAdvice标注的Java类,并结合@ExceptionHandler进行异常处理
@ControllerAdvice
public class GlobalExceptionController {
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public String ariExceptioin(Exception e){
return "全局异常处理:" + e.getMessage();
}
}
#### 全局异常、局部异常、错误页面的执行顺序
- 如果有局部异常处理,则走局部异常处理,不执行全局异常处理。
- 没有局部异常处理则走全局异常处理。
- 如果全局异常处理也没有就走错误页面了。
局部异常 -> 全局异常 -> 错误页面
SpringBoot中的Bean管理
通过创建一个类,使用@Configuration标识,在其中就可以进行@Bean进行配置
@Configuration
public class MyBeanConfigure {
/**
* 在Spring容器中添加一个Bean
* 这个Bean注解中写的 user1相当于该bean的id属性
*/
@Bean("user1")
public User u1(){
return new User();
}
}
获取容器中的bean需要注意的2点
-
如果当前Spring容器中有2个同样类型的bean,需要注意id的区分,取的时候参数名称写id名
- 其实根据方法名区分也可以,取的时候,参数名称写方法名即可
-
如果取的时候,参数名称不想更改为bean的id名或方法名。
- 那么需要通过@Qualifier来指定bean的id(方法名不行)
Bean之间的依赖注入
@Bean("teacher")
public Teacher t1(){
return new Teacher();
}
@Bean("user1")
public User u1(Teacher teacher){
User user = new User();
user.setTeacher(teacher);
return user;
}
值得注意的点
-
只需要在方法的形参上声明即可自动注入。默认是根据类型进行注入。
-
注入的时候,如果Spring容器中只有一个bean,那么通过该需要依赖注入bean的方法名作为形参、id作为形参、或是任意写一个名称,都能够依赖注入成功。
-
如果当前Spring容器中有多个同类型的bean,则可以通过将形参名更改为需要注入的bean的id,此时无法根据方法名当作形参名注入,需要使用@Qualifier注解。例如:
@Bean("teacher1")
public Teacher t1(){
return new Teacher();
}
@Bean("teacher2")
public Teacher t2(){
return new Teacher();
}
@Bean("user1")
public User u1(@Qualifier("teacher1") Teacher t){
User user = new User();
user.setTeacher(t);
return user;
}
SpringBoot拦截器功能
创建一个类,实现HandlerInterceptor接口,并重写方法,我这里顺便将其添加到了Spring的容器
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("我是拦截器,嘿嘿,我执行了");
return true;
}
}
创建一个配置类,实现WebMvcConfigurer接口,重写addInterceptors方法
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 将该拦截器注册到SpringMVC中
registry.addInterceptor(myInterceptor).addPathPatterns("/demo1");
}
}
SpringBoot项目的打包运行
SpringBoot打包成jar包。
设置pom.xml文件,将打包方式设置为jar,并引入SpringBoot的打包插件
<packaging>jar</packaging>
<build>
<plugins>
<!-- SpringBoot打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果不配置打包插件,那么使用maven- install 打包出来的jar,运行时将会提示没有主清单属性。
使用maven执行打包
使用java -jar 你打包的jar即可运行
SpringBoot项目打包成war包
设置pom.xml文件中,添加打包插件并修改打包方式为war,web启动器中的tomcat依赖排除,并手动依赖
<packaging>war</packaging>
<!-- spring web开发模式启动器,内包含web开发所需的jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除tomcat,因为打包成war后我们就会放在tomcat中运行,所以该自带的tomcat就不要了 -->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--
手动依赖tomcat插件,为啥排除了还要依赖呢?
因为我们SpringBoot项目本地运行测试时还会用到
而打包成war包的时候就不需要了,所以scope为provided
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
SpringBoot的启动类继承SpringBootServletInitializer并重写configure方法
@SpringBootApplication
public class ThymeleafApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ThymeleafApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ThymeleafApplication.class, args);
}
}
使用maven-install打包,然后将打包后的war放在tomcat运行即可正常访问