springBoot_swagger、异步任务、邮件发送、定时任务、集成redis、分布式(Dubbo、Zookeeper)
一、swagger
1、spring boot集成swagger
创建一个新spring项目,添加web依赖,编写一个hello程序,保证项目初始化正常
1、导入swagger依赖版本2.9.2,spring boot版本调整为2.5.6
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>
2、config目录中配置swagger
package com.jjl.swagger.config;import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration
@EnableSwagger2
public class SwaggerConfig {}
3、启动测试,访问:http://localhost:8080/swagger-ui.html
2、swagger基本信息配置
swagger的bean实例docket
package com.jjl.swagger.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;@Configuration
@EnableSwagger2
public class SwaggerConfig {//配置swagger的Docket实例//用docket()对象接管默认配置信息@Beanpublic Docket docket(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());}//配置Swagger信息=apiInfoprivate ApiInfo apiInfo(){Contact contact = new Contact("蒋樊","https://blog.csdn.net/qq_43427354","http:test@qq.com");return new ApiInfo("蒋樊SwaggerAPI文档","不忘初心","1.0","https://www.baidu.com/",contact,"Apache 2.0","http://www.apache.org/licenses/LICENSE-2.0",new ArrayList());}
}
重启测试
3、swagger配置扫描接口
@Bean
public Docket docket(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()//RequestHandlerSelectors,配置要扫描的方式//.basePackage:指定要扫描的包basePackage("com.jjl.swagger.controller")//.any():扫描全部//.none:都不扫描//.withClassAnnotation(RestController.class):扫描有RestController注解的类//.withMethodAnnotation(GetMapping.class)扫描有GetMapping注解的方法.apis(RequestHandlerSelectors.basePackage("com.jjl.swagger.controller")).paths(PathSelectors.ant("/jjl/**"))//过滤的路径,只扫描/jjl下的所有接口.build();//
}
4、配置是否启动swagger,默认true
配置当生产环境时则启动swagger,当发布或者测试环境时自动关闭swagger
1、新建两个springboot配置文件,一个用于生产环境时调用,一个用于发布时或测试时调用,通过默认的配置文件去激活要使用的配置文件。
2、去swagger中获取当前的环境
5、创建多个分组,模拟多人开发
添加多个Docket即可
@Beanpublic Docket docket1(){return new Docket(DocumentationType.SWAGGER_2).groupName("A组");}@Beanpublic Docket docket2(){return new Docket(DocumentationType.SWAGGER_2).groupName("B组");}@Beanpublic Docket docket3(){return new Docket(DocumentationType.SWAGGER_2).groupName("C组");}
6、添加注释
1、实体类注释
package com.jjl.swagger.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;@ApiModel("用户实体类") //==@Api("用户实体类")
public class User {@ApiModelProperty("用户名")public String username;@ApiModelProperty("密码")public String password;
}
3、方法的注释
package com.jjl.swagger.controller;import com.jjl.swagger.pojo.User;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloConterller {@RequestMapping("/hello")public String hello(){return "hello swagger";}//只要我们的接口中存在实体类,就会被扫描到@PostMapping(value = "/user")public User user(){return new User();}@ApiOperation("hello传参username")@PostMapping(value = "/hello2")public String hello2(@ApiParam("传入用户名") String username){return "hello2"+username;}}
4、接口测试
二、异步任务
1、模拟后台程序处理业务时的延时
package com.jjl.service;import org.springframework.stereotype.Service;@Service
public class AsyncService {public void hello() throws InterruptedException {Thread.sleep(3000);System.out.println("数据正在处理……………………");}
}
调用延时任务
package com.jjl.controller;import com.jjl.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AsyncController {@AutowiredAsyncService asyncService;@RequestMapping("/hello")public String hello() throws InterruptedException {asyncService.hello();return "ok";}
}
当调用这个延时任务时,前端页面会出现白屏等待
2、启用spring异步任务
启用spring异步任务之后,spring会继续处理延时任务,但是前端页面会跳过等待直接加载页面
在spring启动类上开启异步任务
测试目录
三、邮件发送
1、导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>
2、配置mail参数
spring.mail.username=17709966@qq.com
spring.mail.password=iurwbuhuclytfd
spring.mail.host=smtp.qq.com
# 开启安全验证
spring.mail.properties.mail.smtp.ssl.enable=true
4、测试简单邮件发送和带附件的邮件发送
package com.jjl;import com.jjl.config.SendMail;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMailMessage;
import org.springframework.mail.javamail.MimeMessageHelper;import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;@SpringBootTest
class Springboot09TestApplicationTests {@AutowiredJavaMailSenderImpl mailSender;@Testvoid contextLoads() {//简单邮件发生测试SimpleMailMessage message = new SimpleMailMessage();message.setSubject("spring mail test");message.setText("邮件发送测试");message.setTo("2959351531@qq.com");message.setFrom("1770990966@qq.com");mailSender.send(message);}@Testvoid contextLoads2() throws MessagingException {//复杂邮件发生测试MimeMessage message = mailSender.createMimeMessage();//组装MimeMessageHelper helper = new MimeMessageHelper(message,true);helper.setSubject("spring复杂邮件测试");//true,支持htmlhelper.setText("<p style='color:red'>邮件测试</p>",true);//添加附件helper.addAttachment("1.jpg",new File("E:\\desktop_wallpaper\\2.jpg"));helper.setTo("2959351531@qq.com");helper.setFrom("1770990966@qq.com");mailSender.send(message);}
}
四、定时任务
TaskScheduler 任务调度者
TaskExecutor 任务执行者
@EnableScheduling //开启定时任务
@Scheduled //执行的时间
1、写一个定时任务的测试类
package com.jjl.service;import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;@Service
public class ScheduledService {//在特定的时间执行//cron表达式:cron = "秒 分 时 日 月 周几"//网上有很多cron表达式的写法"0/2 * * * * ?”每两秒执行一次@Scheduled(cron = "0 32 9 * * ?") //在每天的9点32分执行public void hello(){System.out.println("定时任务测试");}
}
2、在spring启动类中开启定时任务
3、cron表达式
五、集成redis
参考笔记
1、导入redis依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
2、配置redis连接参数
3、测试连接
package com.jjl;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest
class Redis01SpringbootApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid contextLoads() {// opsForValue() 操作字符串 类似String//opsForList() 操作list 类似list/*//获取连接RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();connection.flushAll();connection.flushDb();*///往redis中放值redisTemplate.opsForValue().set("mykey","hello redis");//取值System.out.println(redisTemplate.opsForValue().get("mykey"));}}
4、序列化
为什么要序列化
1、当传入未序列化的实体类时,redis会报错
2、使用默认redis默认的Template时,向数据库中插入了一个中文字符串,虽然在 Java 端可以看到返回了中文,但是在 Redis 中查看是一串乱码。
可直接使用的redisTemplate模板
package com.jjl.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.net.UnknownHostException;@Configuration
public class RedisConfig {/*** 编写自定义的 redisTemplate* 这是一个比较固定的模板*/@Bean@SuppressWarnings("all")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {// 为了开发方便,直接使用<String, Object>RedisTemplate<String, Object> template = new RedisTemplate();template.setConnectionFactory(redisConnectionFactory);// Json 配置序列化// 使用 jackson 解析任意的对象Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);// 使用 objectMapper 进行转义ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);// String 的序列化StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key 采用 String 的序列化方式template.setKeySerializer(stringRedisSerializer);// Hash 的 key 采用 String 的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value 采用 jackson 的序列化方式template.setValueSerializer(jackson2JsonRedisSerializer);// Hash 的 value 采用 jackson 的序列化方式template.setHashValueSerializer(jackson2JsonRedisSerializer);// 把所有的配置 set 进 templatetemplate.afterPropertiesSet();return template;}
}
测试
127.0.0.1:6379> keys *
1) "user"
127.0.0.1:6379>
5、redis工具类
在项目真实开发中,基本不会使用redis自带的redisTemplate
因此为了方便所以会自定义一个工具类
package com.zxy.demo.redis;import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;/*** Redis工具类* @author ZENG.XIAO.YAN* @date 2018年6月7日*/
@Component
public final class RedisUtil {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// =============================common============================/*** 指定缓存失效时间* @param key 键* @param time 时间(秒)* @return*/public boolean expire(String key, long time) {try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据key 获取过期时间* @param key 键 不能为null* @return 时间(秒) 返回0代表为永久有效*/public long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}/*** 判断key是否存在* @param key 键* @return true 存在 false不存在*/public boolean hasKey(String key) {try {return redisTemplate.hasKey(key);} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除缓存* @param key 可以传一个值 或多个*/@SuppressWarnings("unchecked")public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete(CollectionUtils.arrayToList(key));}}}// ============================String=============================/*** 普通缓存获取* @param key 键* @return 值*/public Object get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);}/*** 普通缓存放入* @param key 键* @param value 值* @return true成功 false失败*/public boolean set(String key, Object value) {try {redisTemplate.opsForValue().set(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 普通缓存放入并设置时间* @param key 键* @param value 值* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期* @return true成功 false 失败*/public boolean set(String key, Object value, long time) {try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 递增* @param key 键* @param delta 要增加几(大于0)* @return*/public long incr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递增因子必须大于0");}return redisTemplate.opsForValue().increment(key, delta);}/*** 递减* @param key 键* @param delta 要减少几(小于0)* @return*/public long decr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递减因子必须大于0");}return redisTemplate.opsForValue().increment(key, -delta);}// ================================Map=================================/*** HashGet* @param key 键 不能为null* @param item 项 不能为null* @return 值*/public Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);}/*** 获取hashKey对应的所有键值* @param key 键* @return 对应的多个键值*/public Map<Object, Object> hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet* @param key 键* @param map 对应多个键值* @return true 成功 false 失败*/public boolean hmset(String key, Map<String, Object> map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** HashSet 并设置时间* @param key 键* @param map 对应多个键值* @param time 时间(秒)* @return true成功 false失败*/public boolean hmset(String key, Map<String, Object> map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建* @param key 键* @param item 项* @param value 值* @return true 成功 false失败*/public boolean hset(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建* @param key 键* @param item 项* @param value 值* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间* @return true 成功 false失败*/public boolean hset(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除hash表中的值* @param key 键 不能为null* @param item 项 可以使多个 不能为null*/public void hdel(String key, Object... item) {redisTemplate.opsForHash().delete(key, item);}/*** 判断hash表中是否有该项的值* @param key 键 不能为null* @param item 项 不能为null* @return true 存在 false不存在*/public boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);}/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回* @param key 键* @param item 项* @param by 要增加几(大于0)* @return*/public double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);}/*** hash递减* @param key 键* @param item 项* @param by 要减少记(小于0)* @return*/public double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);}// ============================set=============================/*** 根据key获取Set中的所有值* @param key 键* @return*/public Set<Object> sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();return null;}}/*** 根据value从一个set中查询,是否存在* @param key 键* @param value 值* @return true 存在 false不存在*/public boolean sHasKey(String key, Object value) {try {return redisTemplate.opsForSet().isMember(key, value);} catch (Exception e) {e.printStackTrace();return false;}}/*** 将数据放入set缓存* @param key 键* @param values 值 可以是多个* @return 成功个数*/public long sSet(String key, Object... values) {try {return redisTemplate.opsForSet().add(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 将set数据放入缓存* @param key 键* @param time 时间(秒)* @param values 值 可以是多个* @return 成功个数*/public long sSetAndTime(String key, long time, Object... values) {try {Long count = redisTemplate.opsForSet().add(key, values);if (time > 0)expire(key, time);return count;} catch (Exception e) {e.printStackTrace();return 0;}}/*** 获取set缓存的长度* @param key 键* @return*/public long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 移除值为value的* @param key 键* @param values 值 可以是多个* @return 移除的个数*/public long setRemove(String key, Object... values) {try {Long count = redisTemplate.opsForSet().remove(key, values);return count;} catch (Exception e) {e.printStackTrace();return 0;}}// ===============================list=================================/*** 获取list缓存的内容* @param key 键* @param start 开始* @param end 结束 0 到 -1代表所有值* @return*/public List<Object> lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取list缓存的长度* @param key 键* @return*/public long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 通过索引 获取list中的值* @param key 键* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推* @return*/public Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();return null;}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/public boolean lSet(String key, Object value) {try {redisTemplate.opsForList().rightPush(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/public boolean lSet(String key, Object value, long time) {try {redisTemplate.opsForList().rightPush(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存* @param key 键* @param value 值* @param time 时间(秒)* @return*/public boolean lSet(String key, List<Object> value) {try {redisTemplate.opsForList().rightPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存* * @param key 键* @param value 值* @param time 时间(秒)* @return*/public boolean lSet(String key, List<Object> value, long time) {try {redisTemplate.opsForList().rightPushAll(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据索引修改list中的某条数据* @param key 键* @param index 索引* @param value 值* @return*/public boolean lUpdateIndex(String key, long index, Object value) {try {redisTemplate.opsForList().set(key, index, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 移除N个值为value* @param key 键* @param count 移除多少个* @param value 值* @return 移除的个数*/public long lRemove(String key, long count, Object value) {try {Long remove = redisTemplate.opsForList().remove(key, count, value);return remove;} catch (Exception e) {e.printStackTrace();return 0;}}
}
六、dubbo及Zookeeper安装测试
狂神说SpringBoot17:Dubbo和Zookeeper集成
1、源码下载
- 下载:apache-zookeeper-3.8.0-bin.tar.gz
- 下载:incubator-dubbo-ops-develop
2、解压运行
1、apache-zookeeper-3.8.0-bin.tar.gz
将apache-zookeeper-3.8.0-bin\conf的zoo_sample.cfg复制一个为zoo.cfg
并且在里面添加一行,修改它默认admin服务端口(8080):admin.serverPort=8088,因为dubbo-server启动时需要8080
测试:
zookeeper启动成功
2、incubator-dubbo-ops-develop
测试文档参考:Dubbo控制台
七、springboot整合分布式
1、开始zookeeper和dubbo-admin服务
2、创建一个springboot项目模拟分布式接口提供者
1、创建spring boot项目,导入一个web依赖
2、导入zookeeper和dubbo的依赖
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>3.1.0</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-dependencies-zookeeper --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-dependencies-zookeeper</artifactId><version>3.1.0</version><type>pom</type></dependency><!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient --><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version></dependency>
3、创建一个service接口
package com.jjl.service;public interface TicketService{public String getTicket();
}
4、创建一个serviceImpl接口实现接口
导入两个注解
- import org.apache.dubbo.config.annotation.DubboService;
- import org.springframework.stereotype.Component;
package com.jjl.service;import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;@DubboService // 被扫描并注册到注册中心
@Component //将接口放入容器中
public class TicketServiceImpl implements TicketService{@Overridepublic String getTicket() {return "远程调用测-服务端";}
}
5、配置application.properties
由于是本机模拟远程,需要启动两springboot项目,会涉及端口冲突,还有idea热部署问题
- 修改springboot默认端口
- 修改dubbo服务端口
- 配置提供者这名字
- 配置注册中心ip
server.port=8001# 服务应用名字
dubbo.application.name=prioder-server
# 注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 那些服务要被注册
dubbo.scan.base-packages=com.jjl.servicedubbo.protocol.name=dubbo
dubbo.protocol.port=20881
dubbo.protocol.host=192.168.58.44
6、启动项目,在dubbo-admin中查看服务是否被注册
3、创建一个springboot项目模拟分布式接口消费者
1、创建spring boot项目,导入一个web依赖
2、导入zookeeper和dubbo的依赖(与提供者依赖一样)
3、新建service目录,在目录中创建一个与提供者项目中一模一样的接口,因为消费者需要靠这个接口名称去注册中心寻址
4、创建一个模拟调用远程方法的类
注意导入的两个注解
- import org.apache.dubbo.config.annotation.DubboReference;
- import org.springframework.stereotype.Service;
package com.jjl.service;import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;@Service //放在容器中
public class UserService {//拿到prioder里面的方法@DubboReference //远程调用TicketService ticketService;public void BuyTicket(){String ticket = ticketService.getTicket();System.out.println("通过远处调用在注册中心成功调取接口==> " + ticket);}
}
5、配置application.properties
修改springboot端口
配置消费者项目名称
配置注册中心ip
server.port=8090 # 当前服务名字 dubbo.application.name=consumer-server #注册中心地址 dubbo.registry.address=zookeeper://127.0.0.1:2181
6、编写测试类
package com.jjl;import com.jjl.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class ConsumerServerApplicationTests {@AutowiredUserService userService;@Testvoid contextLoads() {userService.BuyTicket();}}
7、处理ieda启动多个项目,报端口被占用问题
8、启动测试类,调用远程方法
9、查看dubbo
springBoot_swagger、异步任务、邮件发送、定时任务、集成redis、分布式(Dubbo、Zookeeper)相关推荐
- Redis分布式锁 Spring Schedule实现任务调度
一看到标题就知道,这一篇博客又是总结分布式工作环境中集群产生的问题,个人觉得分布式没有那么难以理解,可能也是自己见识比较浅,对我来说,分布式只是一种后端业务演进时的一种工作方式,而真正实现这种工作方式 ...
- Java全能手册火了!Redis/Nginx/Dubbo/Spring全家桶啥都有!
前言 本文是为了帮大家快速回顾了Java中知识点,这套面试手册涵盖了诸多Java技术栈的面试题和答案,相信可以帮助大家在最短的时间内用作面试复习,能达到事半功倍效果. 本来想将文件上传到github上 ...
- 利用Spring框架封装的JavaMail现实同步或异步邮件发送
利用Spring框架封装的JavaMail现实同步或异步邮件发送 作者:张纪豪 J2EE简单地讲是在JDK上扩展了各类应用的标准规范,邮件处理便是其中一个重要的应用.它既然是规范,那么我们就可以通过J ...
- mysql自动备份发邮箱,定时任务自动备份数据库并邮件发送
我原本是使用Vastar的第一个脚本方案来自动备份WordPress数据库并邮件发送的,不过后来因为更换服务器,不知道为什么造成了会二次备份并有错误提示.刚好Vastar又给了一个更简洁的方法,于是昨 ...
- Spring Boot最新版集成邮件发送功能大全
Spring Boot最新版集成邮件发送功能大全 前言 一.开启SMTP服务并获取授权码 二.创建Spring Boot项目 1.配置邮箱基本信息: 2.简单邮件发送: 3.发送带附件的邮件: 5.使 ...
- SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊)
SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊) 目录 SpringBoot整合定时任务和邮件发送(邮箱 信息轰炸 整蛊) 1.概述 2.最佳实践 2.1创建项目引入依赖(mail) ...
- node.js集成sendgrid邮件发送及其它功能
1.简介 https://github.com/sendgrid/sendgrid-nodejs 这个是sendgrid官方的nodejs库,可以方便的集成sendgrid功能 2.分包 @ send ...
- python-flask(二)集成bootstrap、集成web表单、集成邮件发送
文章目录 一.flask集成bootstrap 1. 什么是Bootstrap? 2. Flask中如何集成Bootstrap? 3. Flask-Bootstrap实现了什么? 二.Flask中集成 ...
- java发送s mime邮件_SpringBoot集成实现各种邮件发送
JavaMail是提供给开发者处理电子邮件相关的编程接口.它是Sun发布的用来处理email的API.正常我们会用JavaMail相关api来写发送邮件的相关代码. 使用过Spring的众多开发者都知 ...
最新文章
- Hulu视频如何提升推荐多样性?
- 2018年强化学习领域十篇重要论文(附源码)
- Jquery 改变样式
- 【原创】QT在嵌入式系统中显示中文的方法
- 论文浅尝 | 用图网络做小样本学习
- 算法真的太重要了!CSDN用动画帮你快速 get 核心原理
- 收藏功能_六款多功能榻榻米,装完你家会大一半!超实用,收藏
- 如何使用十六进制颜色值
- xgboost的原理没你想像的那么难
- Dubbo负载均衡算法初步解析
- Arduino GPS 车速表(Arduino流体力学燃油效率计)(更新:2022.7.3)
- socks5 python_用Python写socks5服务器端
- length()、size()、sizeof()三者的区别
- 基于PHP+MySQL的服装购物商城系统#毕业设计
- 录制失败因为媒体服务失败_杨丽萍62岁被判人生失败,因为她一生无子女.........
- VMware 兼容性列表与产品互操作性列表使用收集(持续更新中...)
- java设计模式之状态机模式
- 基于FPGA的卷积神经网络实现(七)数据读写
- android 虹软人脸存储,用虹软Android SDK做人脸识别
- POJ - 1579 Function Run Fun
热门文章
- 进制的转换规则简单口诀
- 关于计算机的英语演讲稿三分钟,大学英语演讲稿3分钟
- 开火车的纸牌游戏-python版本
- 计算机win10+上锁,老司机应对win10系统给电脑屏幕上锁的方案
- 搅拌站ERP:砼车过磅流程
- java application 路径_java项目获取根路径(web项目和application项目的区分)
- JSP高校学生积分管理系统myeclipse开发mysql数据库bs框架java编程jdbc详细设计
- 知识变现海哥|如何运营一个培训类社群
- 蓝奏云文件真实地址分析
- 界面扩大缩小操作按钮_《微图4.0》软件功能界面说明1.0