springboot进阶
一 SpringBoot 整合其它框架
1.1 整合Thymeleaf(了解)
1.1.1 简介
Thymeleaf是一个用于展示页面的模板引擎,通俗来讲,就是java工程师用于开发html页面的,之前我们学的是jsp也可以开发页面,但是springboot 推荐用Thymeleaf,为什么呢?
原因有2个:
- Thymeleaf运行效率比jsp高
- Thymeleaf开发起来比jsp简单(9大内置对象、11个el隐式对象)
基于这两点原因,我们要用thymeleaf来开发页面;但是,现在我们处于前后端分离开发的时代,所以作为一个纯后台开发工程师,我们在企业中开发页面的机会非常小,我们只需要通过controller给前端提供json数据即可,如果你想在后台直接写页面,可以来学习一下thymeleaf,很简单…
1.1.2 搭建环境
第一步,创建java模块,导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatisPlus 起步依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!--thymeleaf起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
第二步,编写启动类
@SpringBootApplication
@MapperScan("com.itheima.mapper")
public class ThymeleafApplication {
public static void main(String[] args) {
SpringApplication.run(ThymeleafApplication.class, args);
}
}
1.1.3 视图解析器
springboot默认使用的就是Thymeleaf视图解析器
执行页面跳转的时候,自动的从resource中的templates
文件夹中找到对应的 xxx.html
页面
springboot启动时,加载
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
资源属性类
1.1.4 案例练习
需求
完成用户列表和详情页展示
① 导入页面资源
- 静态资源(static目录下:css、js、image等等)
- thymeleaf模板(templates目录下)
② 修改UserController
// @RestController
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findAll")
public String findAll(Model model) {
List<User> list = userService.findAll();
model.addAttribute("list", list); // 存入到request域
// 请求转发,执行Thymeleaf视图解析器拼接前后缀:templates/list.html
return "list";
}
@RequestMapping("/findById")
public String findById(Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "view";
}
}
③ 修改list.html
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>昵称</th>
<th>年龄</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<tr th:each="user : ${list}">
<td th:text="${user.id}">1</td>
<td th:text="${user.username}">张三</td>
<td th:text="${user.age}">30</td>
<td th:text="${user.email}">123@qq.com</td>
<td><a class="btn btn-default btn-sm" th:href="'/user/findById?id='+${user.id}">查看</a></td>
</tr>
</table>
④ 如果对此技术感兴趣
1.2 整合Redis【重点】
1.2.1 简介
spring为了让开发者简化Jedis的操作,提供了spring-data-redis
框架,它对reids底层开发包(Jedis)进行了高度封装,通过RedisTemplate
对象实现了redis各种操作、异常处理及序列化,支持发布订阅等功能。
"
1.2.2 搭建环境
① 导入依赖
<!--redis 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
② 启动redis
③ 配置redis
1.2.3 案例练习
需求
使用redis对用户列表数据进行缓存优化
① User
② UserService
@Autowired
private RedisTemplate redisTemplate;
@Override
public List<User> findAll() {
List<User> list = null;
if (redisTemplate.hasKey("userList")) {
// 1、先查询缓存
list = (List<User>) redisTemplate.opsForValue().get("userList");
System.out.println("查询缓存");
} else {
// 2、在查询db同步到缓存中
list = userMapper.selectList(null);
redisTemplate.opsForValue().set("userList", list);
System.out.println("查询数据库");
}
return list;
}
1.2.4 模板对象
模板对象 | 序列化方式 | 序列化效果 |
---|---|---|
RedisTemplate(父类) | JdkSerializationRedisSerializer | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJ5XocDr-1623738614971)(assets/image-20210203100027173.png)] |
StringRedisTemplate(子类) | StringRedisSerializer | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-edzlrd6z-1623738614972)(assets/image-20210203100145301.png)] |
API
//操作string类型
redisTemplate.opsForValue();
//操作hash类型
redisTemplate.opsForHash();
//操作list类型
redisTemplate.opsForList();
//操作set类型
redisTemplate.opsForSet();
//操作有序set类型
redisTemplate.opsForZSet();
二 SpringBoot工作原理【面试题】
思考一个问题:
为什么加载了redis的starter(起步依赖)之后,RedisTemplate对象会自动被new出来,可以@Autowired了呢?
2.1 自动装配
观察@EnableAutoConfiguration
注解内部使用 @Import(AutoConfigurationImportSelector.class)
读取META-INF/spring.factories
,
该配置文件中定义了大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean
2.2 装配Redis
并不是读取META-INF/spring.factories
所有的Bean都会被初始化,在配置类中使用@Condition
来加载满足条件的Bean
- ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
- ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
- ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
三 自定义启动器【作业】
有了上面的一些知识点,我们可以自定义一个发送短信的启动器 sms-spring-boot-starter
我们可参考MybatisPlus的启动器,因为MybatisPlus是第三方的(不是spring提供的)
效果:在工程中只需要导入起步依赖,通过@Autowired注入工具类发送短信
3.1 分析MybatisPlus启动器
springboot这么设计优点:集成所有支持自动的框架,并把它们的对象交给ioc容器,开发者直接注入使用即可~~~
3.2 代码实现
工程名:
sms-spring-boot-starter
① 导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--阿里云短信服务-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
② 编写SmsProperties
@Data
@ConfigurationProperties("sms")
public class SmsProperties {
private String accessKeyId;
private String accessKeySecret;
private String signName; // 签名
private String templateCode; // 模板
}
③ 编写SmsTemplate
public class SmsTemplate {
private SmsProperties properties;
// 在创建SmsTemplate对象时,需要知道发送短信的四个配置参数
public SmsTemplate(SmsProperties properties) {
this.properties = properties;
}
// 调用阿里云平台发送短信
public SendSmsResponse sendSms(String phoneNumbers, String code) throws ClientException {
//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", properties.getAccessKeyId(), properties.getAccessKeySecret());
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
IAcsClient acsClient = new DefaultAcsClient(profile);
//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers(phoneNumbers);
//必填:短信签名-可在短信控制台中找到
request.setSignName(properties.getSignName());
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(properties.getTemplateCode());
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam("{\"code\":\"" + code + "\"}");
//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997");
//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request.setOutId("yourOutId");
//hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
return sendSmsResponse;
}
}
④ 编写自动装配类
@Configuration // 声明当前是一个配置类
@ConditionalOnClass(SmsTemplate.class) // 只有导入了 sms的起步依赖才会触发@Bean创建
@EnableConfigurationProperties(SmsProperties.class)// 将属性的参数对象交给了ioc容器
public class SmsAutoConfiguration {
@Bean // 将短信工具类交个了ioc容器
public SmsTemplate smsTemplate(SmsProperties smsProperties) { // 从ioc容器中获取属性的参数对象
SmsTemplate smsTemplate = new SmsTemplate(s6msProperties);
return smsTemplate;
}
}
⑤ 编写自动装配文件
/META-INF/spring.factories
Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itheima.sms.autoconfigura.SmsAutoConfiguration
3.3 测试
① 导入起步依赖
<dependency>
<groupId>com.itheima</groupId>
<artifactId>sms-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
② 编写配置文件
sms:
access-key-id:
access-key-secret:
sign-name:
template-code:
③ 单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class SmsTest {
@Autowired
private SmsTemplate smsTemplate;
@Test
public void test01() throws Exception {
System.out.println(smsTemplate);
SendSmsResponse sendSmsResponse = smsTemplate.sendSms("18312341234", "123456");
}
}
四 SpringBoot项目部署
4.1 jar包发布(官方推荐)
4.1.1 配置打包插件
<build>
<finalName>ssm</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
4.1.2 执行java命令
通过maven命令package完成项目打包;找到jar包位置,以命令行窗口执行
注意:服务器必须安装jdk环境并配置环境变量
java -jar xxx.jar
4.2 war包发布(了解)
4.2.1 项目打包方式
找到项目的pom.xml文件修改默认打包方式为war
4.2.2 配置启动类
@SpringBootApplication
@MapperScan("com.itheima.mapper")
public class ThymeleafApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ThymeleafApplication.class, args);
}
// 排除springboot内置插件,从而选择外部的tomcat环境
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ThymeleafApplication.class);
}
}
4.2.3 部署到Tomcat
执行maven的package命令,将打好的war包放入Tomcat中运行即可