一:搭建项目
1.网关(zuul)
2.注册中心(eureka)
3.用户微服务(user)
4.搜索微服务(searcher)
6.rcp微服务
7.定时微服务(task)
8.web微服务(pc和app客户端)
9.admin微服务(后管)
10.common微服务(公共工具服务)
二:通用工具模块(工具类)
1.BeanHelper:实现Bean属性的拷贝,把一个Bean的属性拷贝到另一个Bean,前提是其属性名一致或部分一致
2.CookieUtils:实现cookie的读和写
3.IdWorker:生成Id
4.JsonUtils:实现实体类与Json的转换(序列化与反序列化)
5.RegexUtils:常用正则校验
6.RegexPattern:常用正则的字符串
三:统一异常处理(这种封装只返回状态码和信息)
1.统一异常处理(统一异常拦截器)
a. controller–try, service–抛
(因为service有事务,抛出异常才能回滚,如果try就不会回滚。)
①:如果是运行时异常不需要try,因为有事务(上面所述)
②:如果是编译时异常需要try,然后将异常转化为运行时异常抛
b.那么每个controller中的方法都需要try,有没有更好的办法进行统一处理,使用aop思想进行统一处理(controller中的方法不需要try)
c.我们使用SpringMVC提供的统一异常拦截器,因为是统一处理,我们放到common项目中。如下
@ControllerAdvice
@Slf4j
public class BasicExceptionAdvice {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleException(RuntimeException e) {
// 我们暂定返回状态码为400, 然后从异常中获取友好提示信息
return ResponseEntity.status(400).body(e.getMessage());
}
@ExceptionHandler(SQException.class)
public ResponseEntity<String> handleException(SQException e) {
// 我们暂定返回状态码为500, 然后从异常中获取友好提示信息
return ResponseEntity.status(e.getStatus()).body(e.getMessage());
}
}
解读:
①:@ControllerAdvice:默认情况下,会拦截所有加了@Controller的
②:@ExceptionHandler(RuntimeException.class):作用在方法上,声明要处理的异常类型,可以有多个,这里指定的是RuntimeException。被声明的方法可以看做是一个SpringMVC的Handler
③:- 参数是要处理的异常,类型必须要匹配
- 返回结果可以是ModelAndView、ResponseEntity等,基本与handler类似
2.自定义异常(SQException 继承 RuntimeException )
package com.leyou.common.exception;
import com.leyou.common.enums.ExceptionEnum;
import lombok.Getter;
/**
* @author
*/
@Getter
public class SQException extends RuntimeException {
/**
* 异常状态码
*/
private int status;
public SQException (ExceptionEnum em) {
super(em.getMessage());
this.status = em.getStatus();
}
public SQException (ExceptionEnum em, Throwable cause) {
super(em.getMessage(), cause);
this.status = em.getStatus();
}
}
3.自定义枚举(私有化构造,自己提供实例)
import lombok.Getter;
/**
*
*/
@Getter
public enum ExceptionEnum {
//1.枚举项
INVALID_FILE_TYPE(400, "无效的文件类型!"),
INVALID_PARAM_ERROR(400, "无效的请求参数!"),
INVALID_PHONE_NUMBER(400, "无效的手机号码"),
CATEGORY_NOT_FOUND(404, "商品分类不存在!"),
BRAND_NOT_FOUND(404, "品牌不存在!"),
SPEC_NOT_FOUND(404, "规格不存在!"),
DATA_TRANSFER_ERROR(500, "数据转换异常!"),
INSERT_OPERATION_FAIL(500, "新增操作失败!"),
UPDATE_OPERATION_FAIL(500, "更新操作失败!"),
UNAUTHORIZED(401, "登录失效或未登录!"),
;
//2.变量
private int status;
private String message;
//3.有参构造函数
ExceptionEnum(int status, String message) {
this.status = status;
this.message = message;
}
}
4.总结:
①:自定义枚举
②:自定义异常(从枚举中获取状态和信息)
③:统一异常处理(捕获异常–获取自定义异常返回)
四:nginx(作为web服务器,反向代理服务器)
1.统一环境
①:如果不同环境使用不同的ip去访问,可能会出现一些问题。为了保证所有环境的一致,我们会在各种环境下都使用域名来访问。(例如www.baidu.com)
2.域名解析
①:一个域名一定会被解析为一个或多个ip
②:解析一般会包含两步:
a.本地域名解析
浏览器会首先在本机的hosts文件中查找域名映射的IP地址,如果查找到就返回IP ,没
找到则进行域名服务器解析,一般本地解析都会失败,因为默认这个文件是空的。
- Windows下的hosts文件地址:C:/Windows/System32/drivers/etc/hosts
- Linux下的hosts文件所在路径: /etc/hosts
样式:
ip 域名
127.0.0.1 localhost
b.域名服务器解析
本地解析失败,才会进行域名服务器解析,域名服务器就是网络中的一台计算机,里面
记录了所有注册备案的域名和ip映射关系,一般只要域名是正确的,并且备案通过,一
定能找到。
3.解决域名解析问题
①:如果你不需要购买域名服务器解析,就是用本地域名即可
②:添加映射关系后
- 127.0.0.1 api.shequ.com :我们的网关Zuul
- 127.0.0.1 manage.shequ.com:我们的后台系统地址
③:验证是否通了–现在,ping一下域名试试是否畅通:
4.nginx作用(以及解决端口问题)–底层是c语言写的工具 - 反向代理
- 负载均衡
- 动态路由
- 请求过滤
①:nginx根据域名判断是静态资源还是动态数据,静态资源就直接返回页面,动态数据就路由到对应微服务调用
②:nginx可以和其他微服务部署同一台服务器,也可以自己部署一台服务器(安装和使用)
③:nginx进行反向代理(代理具体的某个微服务)
④:配置代理(conf配置文件中配置)–如图
upstream shequ-manage{
server 127.0.0.1:9001 weight=10; #加权重比例轮询(负载均衡的策略)
server 127.0.0.2:9001 weight=20;
}
upstream shequ-gateway{
server 127.0.0.1:9002;
}
upstream shequ-portal{
server 127.0.0.1:9003;
}
server {
listen 80;
server_name manage.shequ.com;
location / {
proxy_pass http://shequ-manage;
proxy_connect_timeout 600;
proxy_read_timeout 5000;
}
}
server {
listen 80;
server_name www.shequ.com;
location / {
proxy_pass http://shequ-portal;
proxy_connect_timeout 600;
proxy_read_timeout 5000;
}
}
server {
listen 80;
server_name api.shequ.com;
location / {
proxy_pass http://shequ-gateway;
proxy_connect_timeout 600;
proxy_read_timeout 5000;
}
}
- upstream:定义一个负载均衡集群,例如shequ-manage
- server:集群中某个节点的ip和port信息,可以配置多个,实现负载均衡,默认轮询
- server:定义一个监听服务配置
- listen:监听的断开
- server_name:监听的域名
- location:匹配当前域名下的哪个路径。例如:/,代表的是一切路径
- proxy_pass:监听并匹配成功后,反向代理的目的地,可以指向某个ip和port,或者指向upstream定义的负载均衡集群,nginx反向代理时会轮询中服务列表中选择。
5.总结:
①:域名进行页面访问–域名解析(hosts)
②:ip+80端口(默认)–访问到nginx
③:nginx进行反向代理–访问到具体的ip+端口(目标微服务)
流程解读:
- 浏览器准备发起请求,访问http://mamage.leyou.com,但需要进行域名解析
- 优先进行本地域名解析,因为我们修改了hosts,所以解析成功,得到地址:127.0.0.1(本机)
- 请求被发往解析得到的ip,并且默认使用80端口:http://127.0.0.1:80
本机的nginx一直监听80端口,因此捕获这个请求 - nginx中配置了反向代理规则,将manage.leyou.com代理到http://127.0.0.1:9001
- 主机上的后台系统的webpack server监听的端口是9001,得到请求并处理,完成后将响应返回到nginx
- nginx将得到的结果返回到浏览器
注意点:
1.ip 指向某台计算机, port指向这台计算机的某个进程(例如user服务)
2.解析完域名拿到ip,以及请求头中有host带有原始的域名去nginx中才能找到对应的代理路径。
3.反向代理和正向代理的区别
①:反向代理:比如,客户端访问代理,代理访问到具体服务器,但客户端(用户)不知道具体的服务器(反向代理的是服务端-服务器)
②:正向代理:比如,客户端访问谷歌,有防火墙拦截,用其他服务代理,访问到谷歌,客户端知道要访问的信息(正向代理的是客户端-用户)
③:通俗来讲,正向代理是客户端的代理,反向代理是服务器的代理。正向代理的对象是客户端,反向代理的对象的服务端。