專案中常用技術點
Nginx
-
反向代理
#反向代理
server {
#監聽埠
listen 90;
location /{
#跨域問題
add_header 'Access-Control-Allow-Origin' '$http_origin';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS, DELETE, PUT';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#跨域OPTIONS請求,set response header後直接204返回
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#代理的地址(此處代理的是負載均衡的兩個地址)
proxy_pass http://test;
}
}-
負載均衡
-
輪詢(預設)
-
權重自己設定(weight)
-
ip_hash(訪問ip跟伺服器繫結)
-
#負載均衡
upstream test {
#權重數字越大接收請求越多
server localhost:8081 weight=9;
#ip_hash
ip_hash
server localhost:8082;
} -
-
靜態伺服器搭建
server {
#監聽埠
listen 8888;
location / {
#本地存放的位置
root E:/static_server/img;
autoindex on;
}
}
-
靜態資源的部署
將前端打包部署到html資料夾下
redis查詢時是一個單執行緒的,持久化時,開啟的時多執行緒。多執行緒中有3種方案:同步阻塞IO、同步非阻塞IO、非同步非阻塞IO
redis叢集搭建 1.主從同步:一主一從 資料一致(高可用) 2.主從分離:一主兩從 資料存在不同redis中 3.叢集搭建:3主3從:使用哨兵模式,進行主節點選舉
Redis五種資料儲存型別
Sting(字串)
Hash(物件)
List(可重複集合)
Set(無序、不可重複)
Zset(有序、去重)
-
導包
-
配置
#埠號
Spring.redis.prot=6379
#伺服器
Spring.redis.host=
-
使用
-
快取同步
當資料庫修改後怎麼同步redis
1.修改資料庫時首先判斷redis中是否有該值對應的key如果有的直接刪除key
2.修改資料庫時同時修改redis中的資料
-
快取穿透
當用戶使用資料庫不存在的key進行訪問時,會穿過redis直接訪問資料庫
1.給這個key設定null值 並設定定時
-
快取擊穿
當redis中的key被高併發請求訪問時 該key突然失效 請求會全部訪問到資料庫 造成資料庫壓力增大
1.可以設定key永不失效
-
快取雪崩
和快取擊穿相差不大 雪崩是大量key失效
1.設定加長失效時間
2.避免快取同一時間失效
-
redis持久化
-
AOF
持續的日誌新增,操作一次redis就會記錄一次日誌
-
RDB
快照,每30秒,對當前redis中的記憶體進行儲存記錄到磁碟中
-
支付寶支付
-
導包
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.57.ALL</version>
</dependency>
-
配置
alipay:
#支付寶appid
appid: 2021000119603005
#公鑰
publickey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhj/8JJXO9tXArnzvUr2gqSqO+o4pnGeZUumhnsbF5gl8dwp6MlxpZO2VHwhnzte/lQXH8hsGS8WotUypbaqaks7S6GHmMgcoseTeq8kPbAIu8SCmlO/tPG8XCGWWqcr2IKuFUdzLgx9UDphtbLCFr6Pm76N2OTHFMcsvJHyBY+GEQbnP050mmH+39ft19F49vWzC7BAzlHWI4g2+KNgPCBlrgrhbcd1ydofJEIAj7UGvV8DwtlIg27Dmw58F4NW3CDtDIAsqT1TPIiFSjNo+VTrXE4IMSZm7a/oZIXdB8rKrXh7O1zd7zmfFeVhwftCqJ/MeDX0/0750ckmX5bTmNQIDAQAB
#私鑰
securitykey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCGP/wklc721cCufO9SvaCpKo76jimcZ5lS6aGexsXmCXx3CnoyXGlk7ZUfCGfO17+VBcfyGwZLxai1TKltqpqSztLoYeYyByix5N6ryQ9sAi7xIKaU7+08bxcIZZapyvYgq4VR3MuDH1QOmG1ssIWvo+bvo3Y5McUxyy8kfIFj4YRBuc/TnSaYf7f1+3X0Xj29bMLsEDOUdYjiDb4o2A8IGWuCuFtx3XJ2h8kQgCPtQa9XwPC2UiDbsObDnwXg1bcIO0MgCypPVM8iIVKM2j5VOtcTggxJmbtr+hkhd0HysqteHs7XN3vOZ8V5WHB+0Kon8x4NfT/TvnRySZfltOY1AgMBAAECggEAU1kGQfCAPd8XcT0/mC8CwAQcIJKCYwguuLs0DE98LgVVsNJga0PUa0TVgB7H1DM+Tlb4e+crUX+17llaFywEK4EckAm30PeA3HErjZuWZ4gzfKC4y17p+ss9kYkAsQnBJSdX7isWbqHUnfskdIZjeVhY2A60J24u72smKZDjBA7naVUZ5jo+X6N1IsjuBisQCuiBH5OyG3KlTae5F+eU2x/xkC4I5NadzdgkEmt6CoaBsU1bLrmn8ygnJeA5tt/ef8YBFWcSXDFSaCzpaNvuWCVXFe4RsQ+VkkfEhDQrdZdK62O+t62OSw6gJMGmnVCD12IlIhM4H2ewL14t0q3lQQKBgQDO36rNFzVWynXhQXyS1RCTXqoyZmU3lHPAIlauvabLaqvCs4BmXnhElds6wzzsM0gMnArFjzjOMKy5dcJrPKtk2yLt4KlNaCpYXFz50+j3VMV1f6D4nLYX8cFhi83dexPjhoIRqZ00IwcReQyQ4kLs0IjRi5aHrYG2GEOpOYrRHwKBgQCmIVnJfCcnUwKPfj9cO27ynNGW0DuiaRMx8hFrB4bAhwy8iima9Zm2J5uhqhTutDvMdifYbYlTMQFk4rQ9E1f9neqGAAKurPTRAy3WUgaS4VQqVyTHX8TkmSS987tqCxUQGvfHxvG5K1jHz8NLoqZLoxSNHCxrHxdMJjBuneV6KwKBgBm/kwW11si3qFZiDTxFUqvVA4AEaKKzUnjejUVwi3sUCs7QArI7HeMDd+bneAS6GUSgg2K1gc+AFW977bflNDv4Xm+XH9tnlKWs0VGzA3MNVQpb2VA4SR3P1E7s1LG1aPNPwY6rOsrLdUzCcULzNns9NVpHcnPur49Xk8xTQijnAoGBAJiDQ49yV+uFDHO5PeepdFhsWQkwD58xAXs3tH/if/XdxXaNDFcDI+MTB5BpuR/O/Jre2gOZw5lJAvOgIEF1sbDWOYhdGBlOFM6RMZJw6TIMhJz+NXiHVhVa9l0gFazrkaGgcFrKK/2HatC8zphwMGR9yY8mDy0kdNnmsU3LzPDTAoGAVi37NXztwq+orACzS9tVvGExRCeMHZW/2Y8uUZMtz153vMWFOO5NcQpDXpvROBHKoCRJxDTeV5g2ZTwqrC4CUNqX0IMjW/agX/B0SqSqBtplR72VOOd+Q9fSip4imAnKlmYBJTodbYn6Xl8p7/C95QR9aBr4HwAhlbsVDS9FUpo=
#支付寶公鑰
alipaypublickey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh71b3Xa142+fdvEZL6klvehRuV8Tj1q6nzKI90XafhkCb0pCq/Lxj8UBchsglaDgfKp/MGe4gUZahUQYs6NZCcCkf/CL0uN87u85OebVW/J0UNSUroXNzqsLKchPTLCzsdC+NQL7D4BAljDNDdq14DFbR5oOpsKrY6SJz8zsVQG9/mC620Pq0Gj0bW3+lgh6y4HQnFIPwLQ2wzNIUtjBFiNBWa3IjgOXPGQHqNHcnPk95d9m5hZxK900tCB9T6ll7SgEnltNVLYZORYCHVJ74yyHv/FyhRrvPXcs3xVQLqBBpvsxrt9oc+mJf2VqeDB+foY+0F/tOg29Mgd6zSDPpQIDAQAB
#非同步回撥的地址,後端介面的地址
notifyUrl: http://pc38k4.natappfree.cc/pay/callback
#同步回撥的地址,前端頁面的地址
returnUrl: http://localhost:8081/#/orderinfo
#支付寶閘道器
serverUrl: https://openapi.alipaydev.com/gateway.do
-
使用(工具類)
流程:1.將訂單傳入支付(pay)方法 同時修改訂單狀態為正在支付
2.在回撥函式中執行驗籤(callback)方法,驗簽完畢執行邏輯將訂單狀態修改為已支付
//將訂單傳入支付
//從配置檔案中獲取值
@Value("${alipay.appid}")
private String appid;
@Value("${alipay.publickey}")
private String publickey;
@Value("${alipay.securitykey}")
private String securitykey;
@Value("${alipay.alipaypublickey}")
private String alipaypublickey;
@Value("${alipay.notifyUrl}")
private String notifyUrl;
@Value("${alipay.returnUrl}")
private String returnUrl;
@Value("${alipay.serverUrl}")
private String serverUrl;
private static Logger logger = LoggerFactory.getLogger(AlipayUtils.class);
public String pay(QfOrder order){
AlipayClient alipayClient = new DefaultAlipayClient( serverUrl , appid, securitykey, "json", " utf-8", alipaypublickey, "RSA2"); //獲得初始化的AlipayClient
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); //建立API對應的request
alipayRequest.setReturnUrl( returnUrl );
alipayRequest.setNotifyUrl( notifyUrl ); //在公共引數中設定回跳和通知地址
JSONObject jsonObject = new JSONObject();
jsonObject.put("out_trade_no",order.getOrderid());
jsonObject.put("product_code","FAST_INSTANT_TRADE_PAY");
jsonObject.put("total_amount",order.getOrderPay());
jsonObject.put("subject","課程購買!");
jsonObject.put("body","課程購買!");
alipayRequest.setBizContent(jsonObject.toJSONString()); //填充業務引數
String form= "" ;
try {
form = alipayClient.pageExecute(alipayRequest).getBody(); //呼叫SDK生成表單
} catch (AlipayApiException e) {
e.printStackTrace();
}
return form;
}
//驗籤操作
public Map callBack(HttpServletRequest request){
Map map = verfiryCallbackReq(request);
logger.debug("進入了支付寶的驗籤:引數為{}"+map);
try {
boolean signVerified = AlipaySignature.rsaCheckV1(map, alipaypublickey, "utf-8", "RSA2");
logger.debug("進入了支付寶的驗簽結果為:"+signVerified);
if (signVerified){
return map;
}else{
return null;
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return null;
}
//
public Map verfiryCallbackReq(HttpServletRequest request){
Map<String, String> retMap = new HashMap<String, String>();
Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
for (Map.Entry<String, String[]> entry : entrySet) {
String name = entry.getKey();
String[] values = entry.getValue();
int valLen = values.length;
if (valLen == 1) {
retMap.put(name, values[0]);
} else if (valLen > 1) {
StringBuilder sb = new StringBuilder();
for (String val : values) {
sb.append(",").append(val);
}
retMap.put(name, sb.toString().substring(1));
} else {
retMap.put(name, "");
}
}
return retMap;
}
MyBatis分頁外掛
1.導包
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
2.使用
//page頁數 size每頁大小
PageHelper.startPage(page,size);
進行資料庫查詢得到結果
PageInfo.of(查詢結果)
JWT使用
-
導包
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.19.1</version>
</dependency>
-
使用
//獲得令牌
//map中儲存的是使用者資訊
public String signToken(Map map){
//1.宣告 演算法以及 金鑰
Algorithm algorithm = Algorithm.HMAC256(securt);
//2.宣告頭部資訊
Map headMap = new HashMap<>();
headMap.put("typ","JWT");
headMap.put("alg","HS256");
//3.建立token 載荷資訊
String token = JWT.create().withHeader(headMap)
//1.簽發人
.withIssuer("gzs")
//2.主題
.withSubject("login")
//3.受眾
.withAudience("users")
//自定義載荷
.withClaim("name", map.get("name").toString())
.withClaim("id",map.get("id").toString())
.sign(algorithm);
return token;
}
//解密將令牌傳入返回不等於0解密成功
public Integer verfiy(String token){
try {
//1.宣告演算法
Algorithm algorithm = Algorithm.HMAC256(securt);
//宣告解密物件
JWTVerifier jwtVerifier = JWT.require(algorithm).withIssuer("gzs").build();
//使用解密物件對token進行解密
DecodedJWT verify = jwtVerifier.verify(token);
String id = verify.getClaim("id").asString();
return Integer.valueOf(id);
}catch (Exception e){
System.out.println(e.getMessage());
return 0;
}
}
攔截器
實現HandlerInterceptor(區域性攔截)
實現WebMvcConfigurer(全域性攔截 針對跨域)
HandlerInterceptor
preHandle
呼叫controller之前 一般用來攔截未登入使用者
postHandle
呼叫方法檢視渲染前
afterCompletion
檢視渲染後
WebMvcConfigurer
addInterceptors
設定攔截放行
public void addInterceptors(InterceptorRegistry registry) {
//攔截所有/** 放行/user/**
registry.addInterceptor(myInterceptor).addPathPatterns("/**")
.excludePathPatterns("/user/**","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**")
.excludePathPatterns("/pay/callback");
}
addCorsMappings
配置全域性跨域
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowCredentials(true).allowedOrigins("http://localhost:8080").allowedMethods("GET","POST");
}
Linux部署
-
docker安裝
-
docke 執行資料庫
docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=密碼 資料庫標識
-
連線資料庫 將本地資料庫內容匯入雲資料庫
-
修改本地埠為雲伺服器埠
-
打包上傳專案
-
使用nohup啟動
nohup java -jar 專案包 &
檢視日誌 tail -f nohup.out
-
可以使用nginx代理
首先在/opt/nginx下建html conf包
對映到docker中
前端放入nginx中html
在conf中 配置nginx中的代理
啟動nginx並對映
docker run -d -p 8000:8000 -p 9000:9000 --name nginx -v /opt/nginx/html:/usr/share/nginx/html -v /opt/nginx/conf:/etc/nginx/conf.d fa5269854a5e
Aop實現
@Aspect類上加註解表示切面類
//定義切面方法
使用@Pointcut()定義路徑
第一個*表示返回值 剩下表示路徑
@Pointcut(value = "execution(* *.*.*.*.impl.*.*(..))")
public void pt1(){
}
//在方法上加
@Around(value = "pt1()")
@Component
@Aspect
public class LoggerAop {
private Logger logger = LoggerFactory.getLogger(LoggerAop.class);
/**
* 定義切點
* 第一個*返回值
* *.*.*.*.impl.*.*(..)表示路徑到方法引數
*/
/**
* 1.定義切面類@Aspect
* 2.定義切點方法使用@Pointcut()註解 切點就是日誌的使用域
* 3.定義日誌使用方式@Around(value="切點")
* 4.在定義的方法中傳參ProceedingJoinPoint 通過getSignature獲取執行的方法 通過getArgs獲取方法的引數
*/
@Pointcut(value = "execution(* *.*.*.*.impl.*.*(..))")
public void pt1(){
}
@Around(value = "pt1()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
logger.debug("進入");
//獲取執行方法
MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
//獲得引數
Object[] args = proceedingJoinPoint.getArgs();
Date date = new Date();
String s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
logger.debug("進入時間:"+s);
logger.debug("進入執行的方法:"+signature.getMethod());
logger.debug("當前引數:"+ Arrays.toString(args));
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
logger.debug("返回的引數:"+signature.getReturnType());
return proceed;
}catch (Throwable e) {
e.printStackTrace();
logger.error("方法:"+signature.getMethod()+"發生異常:"+e.getMessage());
}finally {
return proceed;
}
}
}