基于springCloud的微服务项目
微服务项目笔记
1、项目搭建
更改:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、接口开发规范
2.1 Api请求及响应规范
为了严格按照接口进行开发,提高效率,对请求及响应格式进行规范化。
1、get 请求时,采用key/value格式请求,SpringMVC可采用基本类型的变量接收,也可以采用对象接收。
2、Post请求时,可以提交form表单数据(application/x-www-form-urlencoded)和Json数据(Content-Type=application/json),文件等多部件类型(multipart/form-data)三种数据格式,SpringMVC接收Json数据使用@RequestBody注解解析请求的json数据。
4、响应结果统一信息为:是否成功、操作代码、提示信息及自定义数据。
5、响应结果统一格式为json。
2.2 Api定义约束
Api定义使用SpringMVC来完成,由于此接口后期将作为微服务远程调用使用,在定义接口时有如下限制:
1、@PathVariable 统一指定参数名称,如:@PathVariable(“id”)
2、@RequestParam统一指定参数名称,如:@RequestParam(“id”)
@PathVariable与@RequestParam区别**
**@PathVariable和@RequestParam,分别是从路径里面去获取变量,也就是把路径当做变量,后者是从请求里面获取参数。**
**1.@RequestParam :是从请求里面获取参数**
**请求的url: <http://localhost:8080/api?name=001>**
**2.@PathVariable :从路径里面去获取变量**
**请求的url: <http://localhost:8080/api/001**>
5、如何解决node.js相关问题
由于本机node.js之前是10版本,与开发环境不兼容,出现node-sass错误,改变版本为9版本
node-v 查看版本命令
npm -v 查看npm版本命令
npm config ls 查询NPM管理包路径
- Error: Can’t find Python executable “python”, you can set the PYTHON env variable.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hgKNVGp1-1593231783878)(img/1590321685(1)].jpg)
node需要python环境
解决办法
1、安装windows-build-tools
npm install --global --production windows-build-tools
2、安装node-gyp
npm install --global node-gyp
6、nginx 更改host文件?
ngnix中的域名需要在系统host文件中修改
host文件位置在:c\window\sys32\driver\etc
nginx -s reload 可以不关闭nginx的情况下更新配置文件.
nginx -s stop 相当于找到nginx进程kill
start nginx启动nginx命令
7 、maven爆红
- 对着文档的依赖手动导入进去而不是从文档复制进去,手动导入之后原本的unknown的错误就会消失!
- 把pom文件中的"." "-"这俩符号全部在敲一遍
- 从项目结构中设置
对于爆红的文件重新设置jar包
8 、idea 相关破解
H:\个人资料入口\软件及破解
9、 异常处理流程
10、消息队列
入口地址:进入浏览器,输入:http://localhost:15672
-
交换机类型,fanout(输出)、topic、direct、headers
-
消息队列工作模式
-
work queues 工作队列模式
-
Pulish/subscribe 发布订阅模式
- 生产者
在订阅者模式的生产者中,需要声明交换机,并且将交换机与相应的队列绑定
//声明交换机 /** * 参数 * 1 交换机名称 * 2 交换机类型 fanout,topic ,direct,headers */ channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM,BuiltinExchangeType.FANOUT); //声明队列 channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null); channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null); //绑定交换机 channel.queueBind(QUEUE_INFORM_EMAIL, EXCHANGE_FANOUT_INFORM, ""); channel.queueBind(QUEUE_INFORM_SMS, EXCHANGE_FANOUT_INFORM, "");
- 消费者
消费者在声明完交换机与队列之后,只需监听相应的队列就行了
//声明交换机 String exchange, BuiltinExchangeType type channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT); //声明队列 面对的是email队列 channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null); //定义消费方法 DefaultConsumer consumer = new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body); long deliveryTag = envelope.getDeliveryTag(); String exchange = envelope.getExchange(); //消息内容 String message = new String(body, "utf-8"); System.out.println(message); } }; //监听队列 channel.basicConsume(QUEUE_INFORM_EMAIL, true, consumer);
- 生产者
-
Routing 路由模式
路由模式与发布订阅模式区别 路由模式生产者与消费者需要绑定交换机时需要设置相应的路由key
而发布订阅模式的消费者不需要绑定路由key
/** * 参数明细 * 1、队列名称 * 2、交换机名称 * 3、路由key */ channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,QUEUE_INFORM_EMAIL);
生产者
//声明交换机 /** * 参数 * 1 交换机名称 * 2 交换机类型 fanout,topic ,direct,headers */ channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT); //声明队列 channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null); channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null); //绑定交换机 /** * 1、队列名称 * 2、交换机名称 * 3、路由key */ channel.queueBind(QUEUE_INFORM_EMAIL, EXCHANGE_ROUTING_INFORM, QUEUE_INFORM_EMAIL); channel.queueBind(QUEUE_INFORM_SMS, EXCHANGE_ROUTING_INFORM, QUEUE_INFORM_SMS);
消费者
//创建一个连接 Connection connection = factory.newConnection(); //创建与交换机的通道,每个通道代表一个会话 Channel channel = connection.createChannel(); //声明交换机 String exchange, BuiltinExchangeType type channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT); //声明队列 面对的是email队列 channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null); //交换机和队列绑定String queue, String exchange, String routingKey /** * 参数明细 * 1、队列名称 * 2、交换机名称 * 3、路由key */ channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,QUEUE_INFORM_EMAIL);
-
Topics 通配符模式
统配符规则:
中间以**“.”**分隔。
符号**#可以匹配多个词,符号可以匹配一个*词语。
-
生产者
//发送邮件消息 for (int i=0;i<10;i++){ String message = "email inform to user"+i; //向交换机发送消息 String exchange, String routingKey, BasicProperties props, byte[] body /** * 参数明细 * 1、交换机名称,不指令使用默认交换机名称 Default Exchange * 2、routingKey(路由key),根据key名称将消息转发到具体的队列,这里填写队列名称表示消息将发到此队列 * 3、消息属性 * 4、消息内容 */ channel.basicPublish(EXCHANGE_TOPICS_INFORM, "inform.email", null, message.getBytes()); System.out.println("Send Message is:'" + message + "'"); } //发送短信消息 for (int i=0;i<10;i++){ String message = "sms inform to user"+i; channel.basicPublish(EXCHANGE_TOPICS_INFORM, "inform.sms", null, message.getBytes()); System.out.println("Send Message is:'" + message + "'"); } //发送短信和邮件消息 for (int i=0;i<10;i++){ String message = "sms and email inform to user"+i; channel.basicPublish(EXCHANGE_TOPICS_INFORM, "inform.sms.email", null, message.getBytes()); System.out.println("Send Message is:'" + message + "'"); }
-
消费者队列绑定交换机指定通配符:
统配符规则:
中间以“.”分隔。
符号#可以匹配多个词,符号*可以匹配一个词语。
-
//声明队列 channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null); channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null); //声明交换机 channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM, BuiltinExchangeType.TOPIC); //绑定email通知队列 channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_TOPICS_INFORM,"inform.#.email.#"); //绑定sms通知队列 channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_TOPICS_INFORM,"inform.#.sms.#");
-
-
RPC模式
RPC即客户端远程调用服务端的方法 ,使用MQ可以实现RPC的异步调用,基于Direct交换机实现,流程如下:
1、客户端即是生产者就是消费者,向RPC请求队列发送RPC调用消息,同时监听RPC响应队列。
2、服务端监听RPC请求队列的消息,收到消息后执行服务端的方法,得到方法返回的结果
3、服务端将RPC方法 的结果发送到RPC响应队列
4、客户端(RPC调用方)监听RPC响应队列,接收到RPC调用结果
-
-
查看实现类
11, 页面发布服务
注意事项
- @ComponentScan注解顺序不要错
- 由于在消息服务的监听队列中设置了监听组件,因此一定要扫描本项目的所有类,避免组件失效
@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.cms")//扫描实体类
@ComponentScan(basePackages="com.xuecheng.framework")//扫描common工程下的类
@ComponentScan(basePackages="com.xuecheng.manage_cms_client")//扫描本项目下的所有类
public class ManageCmsClientApplication {
public static void main(String[] args) {
SpringApplication.run(ManageCmsClientApplication.class, args);
}
}