SpringBoot基础24_SpringBoot与其他技术整合5
一、SpringBoot整合Mybatis
步骤分析:
1、添加Mybatis的起步依赖
2、添加数据库驱动坐标
3、添加数据库连接信息
4、创建user表
5、创建实体Bean
6、编写Mapper
7、配置Mapper映射文件
8、在application.properties中添加mybatis的信息
9、编写测试Controller
10、测试
代码实现:
New Module-Spring Initializr创建一个工程:springboot_mybatis
项目框架:
1、添加Mybatis的起步依赖
<!--mybatis起步依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency>
2、添加数据库驱动坐标
<!-- MySQL连接驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
3、添加数据库连接信息
在application.properties中添加数据库的连接信息
#DB Configuration: spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=root
4、创建user表
在test数据库中创建user表
-- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `password` varchar(50) DEFAULT NULL, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', 'zhangsan', '123', '张三'); INSERT INTO `user` VALUES ('2', 'lisi', '123', '李四');
5、创建实体Bean
public class User { // 主键 private Long id; // 用户名 private String username; // 密码 private String password; // 姓名 private String name; //此处省略getter和setter方法 .. .. }
6、编写Mapper
@Mapper public interface UserMapper { public List<User> queryUserList(); }
注意:@Mapper标记该类是一个mybatis的mapper接口,可以被spring boot自动扫描到spring上下文中
7、配置Mapper映射文件
在src\main\resources\mapper路径下加入UserMapper.xml配置文件"
<?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="com.itheima.mapper.UserMapper"> <select id="queryUserList" resultType="user"> select * from user </select> </mapper>
8、在application.properties中添加mybatis的信息
#spring集成Mybatis环境 #pojo别名扫描包 mybatis.type-aliases-package=com.itheima.domain #加载Mybatis映射文件 mybatis.mapper-locations=classpath:mapper/*Mapper.xml
9、编写测试Controller
@Controller public class MybatisController { @Autowired private UserMapper userMapper; @RequestMapping("/query") @ResponseBody public List<User> queryUserList(){ List<User> users = userMapper.queryUserList(); return users; } }
10、测试
启动项目(main方法),浏览器访问http://localhost:8080/query
二、SpringBoot整合Junit
步骤分析:
1、添加Junit的起步依赖
2、编写测试类
3、测试
代码实现:
1、添加Junit的起步依赖
<!--测试的起步依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2、编写测试类
package com.itheima.test; import com.itheima.MySpringBootApplication; import com.itheima.domain.User; import com.itheima.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest(classes = MySpringBootApplication.class) public class MapperTest { @Autowired private UserMapper userMapper; @Test public void test() { List<User> users = userMapper.queryUserList(); System.out.println(users); } }
其中,SpringRunner继承自SpringJUnit4ClassRunner,使用哪一个Spring提供的测试测试引擎都可以
public final class SpringRunner extends SpringJUnit4ClassRunner
@SpringBootTest的属性指定的是引导类的字节码对象
3、执行test,控制台打印信息
三、SpringBoot整合Spring Data JPA
步骤分析:
1、添加Spring Data JPA的起步依赖
2、添加数据库驱动依赖
3、在application.properties中配置数据库和jpa的相关属性
4、创建实体配置实体
5、编写UserRepository
6、编写测试类
代码实现:
1、添加Spring Data JPA的起步依赖
<!-- springBoot JPA的起步依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
2、添加数据库驱动依赖
<!-- MySQL连接驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
3、在application.properties中配置数据库和jpa的相关属性
#DB Configuration: spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=root #JPA Configuration: spring.jpa.database=MySQL spring.jpa.show-sql=true spring.jpa.generate-ddl=true spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
4、创建实体配置实体
@Entity public class User { // 主键 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 用户名 private String username; // 密码 private String password; // 姓名 private String name; //此处省略setter和getter方法... ... }
5、编写UserRepository
public interface UserRepository extends JpaRepository<User,Long>{ public List<User> findAll(); }
6、编写测试类
@RunWith(SpringRunner.class) @SpringBootTest(classes=MySpringBootApplication.class) public class JpaTest { @Autowired private UserRepository userRepository; @Test public void test(){ List<User> users = userRepository.findAll(); System.out.println(users); } }
7、执行test,控制台打印信息
注意:如果是jdk9,执行报错如下:
原因:jdk缺少相应的jar
解决方案:手动导入对应的maven坐标,如下:
<!--jdk9需要导入如下坐标--> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency>
四、SpringBoot整合Redis
步骤分析:
1、添加redis的起步依赖
2、配置redis的连接信息
3、注入RedisTemplate测试redis操作
代码实现:
1、添加redis的起步依赖
<!-- 配置使用redis启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2、配置redis的连接信息
启动redis,软件目录中有redisbin,解压后双击redis-server.exe启动redis服务
#Redis spring.redis.host=127.0.0.1 spring.redis.port=6379
3、注入RedisTemplate测试redis操作
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringbootJpaApplication.class) public class RedisTest { @Autowired private UserRepository userRepository; @Autowired private RedisTemplate<String, String> redisTemplate; @Test public void test() throws JsonProcessingException { //从redis缓存中获得指定的数据 String userListData = redisTemplate.boundValueOps("user.findAll").get(); //如果redis中没有数据的话 if(null==userListData){ //查询数据库获得数据 List<User> all = userRepository.findAll(); //将list集合转换成json格式字符串 使用jackson进行转换 ObjectMapper om = new ObjectMapper(); userListData = om.writeValueAsString(all); //将数据存储到redis中,下次在查询直接从redis中获得数据,不用在查询数据库 redisTemplate.boundValueOps("user.findAll").set(userListData); System.out.println("=====从数据库中获得user的数据====="); }else{ System.out.println("=====从redis缓存中获得user的数据======"); } System.out.println(userListData); } }
执行test,控制台打印结果:
再次执行test,控制台打印结果:
五、SpringBoot整合MyBatis-Plus
步骤分析:
1、创建数据库表
2、添加mybatis-plus的起步依赖
3、在application.yml中添加mybatis-plus的信息
4、创建实体Bean
5、编写Mapper
6、编写Service
7、编写Controller
8、编写启动类
代码实现:
New Module-Spring Initializr创建一个工程:tensquare_article
1、创建数据库tensquare_article、数据表tb_article
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_article` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `tensquare_article`; /*Table structure for table `tb_article` */ DROP TABLE IF EXISTS `tb_article`; CREATE TABLE `tb_article` ( `id` varchar(20) NOT NULL COMMENT 'ID', `columnid` varchar(20) DEFAULT NULL COMMENT '专栏ID', `userid` varchar(20) DEFAULT NULL COMMENT '用户ID', `title` varchar(100) DEFAULT NULL COMMENT '标题', `content` text COMMENT '文章正文', `image` varchar(100) DEFAULT NULL COMMENT '文章封面', `createtime` datetime DEFAULT NULL COMMENT '发表日期', `updatetime` datetime DEFAULT NULL COMMENT '修改日期', `ispublic` varchar(1) DEFAULT NULL COMMENT '是否公开', `istop` varchar(1) DEFAULT NULL COMMENT '是否置顶', `visits` int(20) DEFAULT NULL COMMENT '浏览量', `thumbup` int(20) DEFAULT NULL COMMENT '点赞数', `comment` int(20) DEFAULT NULL COMMENT '评论数', `state` varchar(1) DEFAULT NULL COMMENT '审核状态', `channelid` varchar(20) DEFAULT NULL COMMENT '所属频道', `url` varchar(100) DEFAULT NULL COMMENT 'URL', `type` varchar(1) DEFAULT NULL COMMENT '类型', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文章';
2、添加mybatis-plus的起步依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>1.0.5</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.2.0</version> </dependency>
3、在application.yml中添加mybatis-plus的信息
server: port: 9004 #服务访问端口号 spring: application: name: tensquare-article #指定服务名 datasource: #数据库连接四大属性 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.240.134:3306/tensquare_article?characterEncoding=utf-8 password: root username: root mybatis-plus: #mapper-locations: classpath:/mapper/*Mapper.xml type-aliases-package: com.tensquare.article.pojo #实体扫描,多个package用逗号或者分号分隔 global-config: id-type: 1 #0:数据库ID自增 1:用户输入id db-column-underline: false #映射数据库下划线字段名到数据库实体类的驼峰命名映射 refresh-mapper: true #刷新mapper configuration: map-underscore-to-camel-case: true #开启驼峰功能,将数据库字段user_name转换为Java对象userName cache-enabled: true #配置的缓存的全局开关 lazyLoadingEnable: true #延时加载的开关,开启延时加载,当在真正需要数据的时候,才真正执行数据加载操作。 multipleResultSetsEnabled: true #允许单个语句返回多结果集 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用
4、创建实体Bean
package com.tensquare.article.pojo; @Data @TableName("tb_article") public class Article implements Serializable { @TableId(type = IdType.INPUT) private String id; //ID private String columnid; //专栏ID private String userid; //用户ID private String title; //标题 private String content; //文章正文 private String image; //文章封面 private Date createtime; //发表日期 private Date updatetime; //修改日期 private String ispublic; //是否公开 private String istop; //是否置顶 private Integer visits; //浏览量 private Integer thumbup; //点赞数 private Integer comment; //评论数 private String state; //审核状态 private String channelid; //所属频道 private String url; //URL private String type; //类型 }
package com.tensquare.entity; public class Result { private boolean flag;//是否成功 private Integer code;//返回码 private String message;//返回信息 private Object data;//返回数据 public Result() { } public Result(boolean flag, Integer code, String message) { this.flag = flag; this.code = code; this.message = message; } public Result(boolean flag, Integer code, String message, Object data) { this.flag = flag; this.code = code; this.message = message; this.data = data; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
package com.tensquare.entity; import java.util.List; /** * 返回分页结果 * @param <T> */ public class PageResult<T> { private Long total; private List<T> rows; public PageResult() { } public PageResult(Long total, List<T> rows) { this.total = total; this.rows = rows; } public Long getTotal() { return total; } public void setTotal(Long total) { this.total = total; } public List<T> getRows() { return rows; } public void setRows(List<T> rows) { this.rows = rows; } @Override public String toString() { return "PageResult{" + "total=" + total + ", rows=" + rows + '}'; } }
5、编写Mapper
ArticleMapper接口:继承BaseMapper<T>
, T为实体类Article,需要加上@Mapper
注解,如果不加注解需要在启动类上加@MapperScan
注解
package com.tensquare.article.mapper; public interface ArticleMapper extends BaseMapper<Article> { }
6、编写Service
package com.tensquare.article.service; @Service public class ArticleService { @Autowired private ArticleMapper articleMapper; public List<Article> findAll(){ return articleMapper.selectList(null); } public Article findById(String id){ return articleMapper.selectById(id); } }
7、编写测试Controller
package com.tensquare.article.controller; import com.baomidou.mybatisplus.plugins.Page; import com.tensquare.article.pojo.Article; import com.tensquare.article.service.ArticleService; import com.tensquare.entity.PageResult; import com.tensquare.entity.Result; import com.tensquare.entity.StatusCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @RestController @CrossOrigin //跨域处理,域名、端口、协议任一不同都是跨域 @RequestMapping("/article") public class ArticleController { @Autowired private ArticleService articleService;//文章全部列表
//@RequestMapping(method = RequestMethod.GET) @GetMapping public Result findAll(){ List list = articleService.findAll(); return new Result(true, StatusCode.OK,"查询成功",list); } //GET /article/{articleId} 根据ID查询文章 @RequestMapping(value = "/{id}",method = RequestMethod.GET) public Result findById(@PathVariable String id){ Article article = articleService.findById(id); return new Result(true,StatusCode.OK,"查询成功",article); } }
8、编写启动类
package com.tensquare.article; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication //配置Mapper包扫描 @MapperScan("com.tensquare.article.mapper") public class ArticleApplication { public static void main(String[] args) { SpringApplication.run(ArticleApplication.class); } }
执行main方法,浏览器访问http://localhost:9004/article,展示查询出的所有文章信息;访问http://localhost:9004/article/1,检查展示文章id为1的文章信息。
9、条件和分页查询
使用Mybatis Plus提供的EntityWrapper对象封装where查询条件。
使用 Mybatis Plus提供的Page对象,向Mybatis Plus中注入PaginationInterceptor插件
package com.tensquare.article.config; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisPlusConfig { @Bean public PaginationInterceptor createPaginationInterceptor(){ return new PaginationInterceptor(); } }
package com.tensquare.article.service; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; @Service public class ArticleService { @Autowired private ArticleMapper articleMapper; public Page findByPage(Map map, int page, int size) { //设置查询条件 EntityWrapper wrapper = new EntityWrapper<Article>(); Set<String> keySet = map.keySet(); for (String key : keySet) { // if(map.get(key) != null){ // wrapper.eq(key,map.get(key)); // } //和上面的if判断的写法是一样的效果,实现动态sql wrapper.eq(null != map.get(key), key, map.get(key)); } Page page1 = new Page(page,size); List list = articleMapper.selectPage(page1,wrapper); page1.setRecords(list); return page1; } }
package com.tensquare.article.controller; @RestController @CrossOrigin @RequestMapping("/article") public class ArticleController { @Autowired private ArticleService articleService; //之前接收文章数据使用的是pojo,但是现在根据条件查询 // //所有的条件都需要进行判断,遍历pojo的所有属性需要使用反射的方式,成本较高,性能较低 // 直接使用集合的方式遍历,这里接收数据改为map集合(可把Article转成map) @RequestMapping(value = "/search/{page}/{size}",method = RequestMethod.POST) public Result findByPage(@RequestBody Map map,@PathVariable int page,@PathVariable int size){ Page page1 = articleService.findByPage(map,page,size); return new Result(true,StatusCode.OK,"查询成功",new PageResult(page1.getTotal(),page1.getRecords())); } }
postman访问url:http://localhost:9004/article/search/2/1,body加入查询条件进行查询。
{ "id": "1838587904381816832", "title": "三2十" }
六、SpringBoot整合RabbitMQ
1. 生产者项目:
步骤分析:
1、添加mq依赖
2、在application.yml文件中配置rabbitMq
3、编写rabbitmq配置类
4、发送消息
代码实现:
1、添加mq依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
2、在application.yml文件中配置rabbitMq
server: port: 8021 #服务访问端口号 spring: application: name: rabbitmq-provider #指定服务名 rabbitmq: host: 121.196.111.120 #ip port: 5672 #端口 username: guest #用户名 password: guest #密码 virtual-host: /demo #虚拟机名称
3、编写rabbitmq配置类
package com.itheima.config; @Configuration public class RabbitDirectConfig { //注入队列 @Bean Queue queue() { return new Queue("directQueue"); } //注入交换机 @Bean DirectExchange directExchange() { //durable:重启后是否有效 autodelete:长期未使用是否删除掉 return new DirectExchange("directExchange", true, false); } //将队列和交换机进行绑定 @Bean Binding binding() { return BindingBuilder.bind(queue()).to(directExchange()).with("directRouting"); } }
4、发送消息
package com.itheima.mq; @RestController public class RabbitmqProducer{ //注入Rabbitmq发送消息的模板对象 @Autowired RabbitTemplate rabbitTemplate; @GetMapping("sendDirectMessage") public String sendDirectMessage() { //routingKey需要转发到对应队列的名字 object 消息对象 rabbitTemplate.convertAndSend("directExchange", "directRouting", "hello fff!haa"); return "OK"; } }
5、编写启动类
package com.itheima; @SpringBootApplication public class RabbitmqProviderApplication { public static void main(String[] args) { SpringApplication.run(RabbitmqProducerApplication.class,args); } }
执行启动类,浏览器访问http://localhost:8021/sendDirectMessage,进入rabbitMq管理页面查询消息发送成功
2. 消费者项目:
步骤分析:
1、添加mq依赖
2、在application.properties文件中配置rabbitMq
3、编写rabbitmq配置类
4、编写消息接收监听类
5、编写启动类
代码实现:
1、添加mq依赖-同生产者
2、在application.yml文件中配置rabbitMq
server: port: 8022 spring: #给项目来个名字 application: name: rabbitmq-consumer #配置rabbitMq 服务器 rabbitmq: host: 121.192.111.120 port: 5672 username: root password: root #虚拟host 可以不设置,使用server默认host virtual-host: /demo
3、编写rabbitmq配置类
package com.itheima.config; @Configuration public class DirectRabbitConfig { //队列 起名:directQueue @Bean public Queue TestDirectQueue() { return new Queue("directQueue",true); } //Direct交换机 起名:directExchange @Bean DirectExchange TestDirectExchange() { return new DirectExchange("directExchange"); } //绑定 将队列和交换机绑定, 并设置用于匹配键:directRouting @Bean Binding bindingDirect() { return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("directRouting"); } }
4、编写消息接收监听类
package com.itheima.listener; @Component @RabbitListener(queues = "directQueue")//监听的队列名称 directQueue public class DirectReceiver { @RabbitHandler public void process(String message) { //发送的消息是String类型,所以入参必须是String类型 System.out.println("DirectReceiver消费者收到消息 : " + message); } }
5、编写启动类,同生产者
执行启动类,可以看到把之前发送的那条消息消费下来了。
然后可以再继续调用RabbitmqProvider项目的推送消息接口,可以看到消费者即时消费消息。
那么直连交换机既然是一对一,那如果咱们配置多台监听绑定到同一个直连交互的同一个队列,会怎么样?
可以看到是实现了轮询的方式对消息进行消费,而且不存在重复消费。
3. 使用rabbitAdmin
RabbitAdmin 是 Spring-AMQP 中的核心基础组件,是我们在 Spring 中对 RabbitMQ 进行初始化的必须组件,其提供了 RabbitMQ 中声明交换机、声明队列、绑定交换机和队列,以及绑定路由 Key 等其他 API ,RabbitAdmin 正式由此得名。
在现实的业务中的话,服务端消息发送到绑定的exchange的时候,routingKey是根据不同业务的匹配规则动态生成,先撇开consumer端的消费来说,producer端获取数据并根据routingKey,发送到绑定的exchange时,这个过程很多情况下,是需要动态绑定生成的。
producer端在产生数据的时候,并不需要一定绑定一个或者多个queue。
package com.itheima.config; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.Queue; import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitDirectConfig { @Autowired private RabbitTemplate rabbitTemplate; //注入队列 @Bean Queue queue() { return new Queue("directQueue"); } //注入交换机 @Bean DirectExchange directExchange() { //durable:重启后是否有效 autodelete:长期未使用是否删除掉 return new DirectExchange("directExchange", true, false); } //将队列和交换机进行绑定 @Bean Binding binding() { return BindingBuilder.bind(queue()).to(directExchange()).with("directRouting"); } @Bean public RabbitAdmin rabbitAdmin(){ RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory()); rabbitAdmin.declareQueue(queue()); rabbitAdmin.declareExchange(directExchange()); rabbitAdmin.declareBinding(binding()); return rabbitAdmin; } }