「小程式JAVA實戰」小程式的springboot後臺攔截器(60)
之前咱們把使用者登入,註冊成功的資訊都放到redis裡面了,如果產品經理有一種場景,就是同一個使用者在同一個時間以最後一個登入為準,那麼前一個就需要重新登入,並且清空前一個使用者快取。這就用到了springboot的快取機制。原始碼:https://github.com/limingios/wxProgram.git 中No.15和springboot
攔截器的建立
通過前端傳遞過來的userToken,和從redis裡面獲取到的userToken對比,如果不一致,前端傳遞過來的這個session獎盃提示使用者被擠出,直接快取失效。需要重新登入。
package com.idig8.controller.interceptor; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.idig8.utils.JSONResult; import com.idig8.utils.JsonUtils; import com.idig8.utils.RedisOperator; public class MiniInterceptor implements HandlerInterceptor { @Autowired public RedisOperator redis; public static final String USER_REDIS_SESSION = "user-redis-session"; /** * 攔截請求,在controller呼叫之前 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { String userId = request.getHeader("headerUserId"); String userToken = request.getHeader("headerUserToken"); if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) { String uniqueToken = redis.get(USER_REDIS_SESSION + ":" + userId); if (StringUtils.isEmpty(uniqueToken) && StringUtils.isBlank(uniqueToken)) { System.out.println("請登入..."); returnErrorResponse(response, new JSONResult().errorTokenMsg("請登入...")); return false; } else { if (!uniqueToken.equals(userToken)) { System.out.println("賬號被擠出..."); returnErrorResponse(response, new JSONResult().errorTokenMsg("賬號被擠出...")); return false; } } } else { System.out.println("請登入..."); returnErrorResponse(response, new JSONResult().errorTokenMsg("請登入...")); return false; } /** * 返回 false:請求被攔截,返回 * 返回 true :請求OK,可以繼續執行,放行 */ return true; } public void returnErrorResponse(HttpServletResponse response, JSONResult result) throws IOException, UnsupportedEncodingException { OutputStream out=null; try{ response.setCharacterEncoding("utf-8"); response.setContentType("text/json"); out = response.getOutputStream(); out.write(JsonUtils.objectToJson(result).getBytes("utf-8")); out.flush(); } finally{ if(out!=null){ out.close(); } } } /** * 請求controller之後,渲染檢視之前 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { } /** * 請求controller之後,檢視渲染之後 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { } }
每一個攔截器有需要實現HandlerInterceptor介面,這個介面有三個方法,每個方法會在請求呼叫的不同時期完成,因為我們需要在介面呼叫之前攔截請求判斷是否登陸,所以這裡需要使用preHandle方法,在裡面是驗證邏輯,最後返回true或者false,確定請求是否合法。
攔截器加入配置中
原來咱們在spring mvc的時候都是通過xml配置檔案的方法,springboot為了簡化,都是通過java來進行配置,剛建立的攔截器需要配置在webconfig裡面
package com.idig8; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.idig8.controller.interceptor.MiniInterceptor; @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Value("${server.file.path}") private String fileSpace; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //資源的路徑.swagger2的資源.所在的目錄, registry.addResourceHandler("/**") .addResourceLocations("classpath:/META-INF/resources/") .addResourceLocations("file:"+fileSpace); } @Bean public MiniInterceptor miniInterceptor() { return new MiniInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(miniInterceptor()).addPathPatterns("/user/**") .addPathPatterns("/video/upload", "/video/uploadCover") .addPathPatterns("/bgm/**"); super.addInterceptors(registry); } }
小程式針對返回的502問題新增判斷
在通過userId獲取使用者的資訊時,在header中新增使用者的userId,userToken,針對登入後返回502進行提示並清空使用者資訊快取。
“` javascript
// pages/mine/mine.js
const app = getApp()
var videoUtils = require(‘../../utils/videoUtils.js’)
Page({
/**
* 頁面的初始資料
*/
data: {
faceImage: “../../resource/images/noneface.png”,
nickname: “暱稱”,
fansCounts: 0,
followCounts: 0,
receiveLikeCounts: 0,
},
/**
* 使用者登出
*/
logout: function(e) {
var user = app.getGlobalUserInfo();
wx.showLoading({
title: ‘正在登出中。。。’
});
wx.request({
url: app.serverUrl + “/logout?userId=” + user.id,
method: “POST”,
header: {
‘content-type’: ‘application/json’ // 預設值
},
success: function(res) {
console.log(res.data);
var status = res.data.status;
wx.hideLoading();
if (status == 200) {
wx.showToast({
title: “使用者登出成功~!”,
icon: ‘none’,
duration: 3000
})
// app.userInfo = null;
wx.removeStorageSync(“userInfo”);
wx.redirectTo({
url: ‘../userRegister/userRegister’,
})
} else if (status == 500) { wx.showToast({ title: res.data.msg, icon: 'none', duration: 3000 }) } } })
},
/**
* 頭像上傳
*/
uploadFace: function(e) {
// var user = app.userInfo;
var user = app.getGlobalUserInfo();
var me = this;
wx.chooseImage({
count: 1, // 預設9
sizeType: [‘compressed’], // 可以指定是原圖還是壓縮圖,預設二者都有
sourceType: [‘album’, ‘camera’], // 可以指定來源是相簿還是相機,預設二者都有
success: function(res) {
// 返回選定照片的本地檔案路徑列表,tempFilePath可以作為img標籤的src屬性顯示圖片
var tempFilePaths = res.tempFilePaths
if (tempFilePaths.length > 0) {
console.log(tempFilePaths[0]);
wx.uploadFile({
url: app.serverUrl + “/user/uploadFace?userId=” + user.id, //僅為示例,非真實的介面地址
filePath: tempFilePaths[0],
name: ‘file’,
success: function(res) {
var data = JSON.parse(res.data);
console.log(data);
wx.hideLoading();
if (data.status == 200) {
wx.showToast({
title: “使用者上傳成功~!”,
icon: ‘none’,
duration: 3000
})
me.setData({
faceUrl: app.serverUrl + data.data
})
} else if (data.status == 500) { wx.showToast({ title: data.msg, icon: 'none', duration: 3000 }) } } }) } } })
},
/**
* 生命週期函式–監聽頁面載入
*/
onLoad: function(options) {
var me = this;
var userInfo = app.getGlobalUserInfo();
wx.showLoading({
title: ‘正在獲取使用者資訊。。。’
});
wx.request({
url: app.serverUrl + “/user/queryByUserId?userId=” + userInfo.id,
method: “POST”,
header: {
‘content-type’: ‘application/json’, // 預設值
‘headerUserId’: userInfo.id,
‘headerUserToken’: userInfo.userToken
},
success: function(res) {
console.log(res.data);
var status = res.data.status;
if (status == 200) { var userInfo = res.data.data; wx.hideLoading(); var faceImage = me.data.faceUrl; if (userInfo.faceImage != null && userInfo.faceImage != '' && userInfo.faceImage != undefined) { faceImage = app.serverUrl + userInfo.faceImage; } me.setData({ faceImage: faceImage, fansCounts: userInfo.fansCounts, followCounts: userInfo.followCounts, receiveLikeCounts: userInfo.receiveLikeCounts, nickname: userInfo.nickname }) } else if (status == 502){ wx.showToast({ title: res.data.msg, duration:3000, icon:'none', complete:function(){ wx.removeStorageSync("userInfo"); wx.navigateTo({ url: '../userLogin/userLogin', }) } }) } } })
},
uploadVideo: function(e) {
videoUtils.uploadVideo();
},
/**
* 生命週期函式–監聽頁面初次渲染完成
*/
onReady: function() {
},
/**
* 生命週期函式–監聽頁面顯示
*/
onShow: function() {
},
/**
* 生命週期函式–監聽頁面隱藏
*/
onHide: function() {
},
/**
* 生命週期函式–監聽頁面解除安裝
*/
onUnload: function() {
},
/**
* 頁面相關事件處理函式–監聽使用者下拉動作
*/
onPullDownRefresh: function() {
},
/**
* 頁面上拉觸底事件的處理函式
*/
onReachBottom: function() {
},
/**
* 使用者點選右上角分享
*/
onShareAppMessage: function() {
}
})
““
PS:通過攔截器的方式很好的保護後臺的程式正常的執行。
ofollow,noindex" target="_blank" href="http://zhanzhang.baidu.com/sitesubmit/index?sitename=https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudespringboothoutailanjieqi60/">百度未收錄
>>原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝!
>>原文連結地址: