天天看點

千人千面Elasticsearch實戰學習筆記

文章目錄

    • 千人千面Elasticsearch實戰學習筆記
      • 統一攔截異常處理
        • 一、建構通用傳回類
        • 二、錯誤傳回類
        • 三、統一異常傳回
        • 四、枚舉類錯誤定義
        • 五、全局異常切面
        • 六、@Valid 校驗傳入的參數
        • 七、異常工具類
      • 切面鑒權
        • 一、注解定義切面
        • 二、@Around() 環繞式
      • Elasticsearch注意點

千人千面Elasticsearch實戰學習筆記

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-pXHzw7Fo-1624441203417)(千人千面Elasticsearch實戰學習筆記.assets/image-20210621142015949.png)]

搜尋和推薦是不同的

搜尋目标是明确的,推薦是根據搜尋習慣推送給使用者

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-2IP92Drt-1624441203421)(千人千面Elasticsearch實戰學習筆記.assets/image-20210621142752593.png)]

技術分解子產品分析

統一攔截異常處理

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-jmkZqE2u-1624441203424)(千人千面Elasticsearch實戰-學習筆記.assets/image-20210623150840735.png)]

一、建構通用傳回類

// 先定義一個通用傳回類,用來傳回成功和錯誤的data
// 成功就封裝資料,和success;失敗則提供errCode和errMsg
package com.imooc.dianping.common;

public class CommonRes {

    //表明讀經請求的傳回處理結果,"success"或"fail"
    private String status;

    //若status=success時,表明對應的傳回的json類資料
    //若status=fail時,則data内将使用通用的錯誤碼對應的格式
    private Object data;

    //定義一個通用的建立傳回對象的方法
    public static CommonRes create(Object result){
        return CommonRes.create(result,"success");
    }

    public static CommonRes create(Object result,String status){
        CommonRes commonRes = new CommonRes();
        commonRes.setStatus(status);
        commonRes.setData(result);

        return commonRes;
    }


    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

           

二、錯誤傳回類

package com.imooc.dianping.common;


public class CommonError {
    //錯誤碼
    private Integer errCode;


    //錯誤描述
    private String errMsg;

    public CommonError(Integer errCode, String errMsg) {
        this.errCode = errCode;
        this.errMsg = errMsg;
    }

    public CommonError(EmBusinessError emBusinessError){
        this.errCode = emBusinessError.getErrCode();
        this.errMsg = emBusinessError.getErrMsg();
    }

    public Integer getErrCode() {
        return errCode;
    }

    public void setErrCode(Integer errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}

           

三、統一異常傳回

package com.imooc.dianping.common;


public class BusinessException extends Exception {
    private CommonError commonError;

    public BusinessException(EmBusinessError emBusinessError){
        super();
        this.commonError = new CommonError(emBusinessError);
    }

    public BusinessException(EmBusinessError emBusinessError,String errMsg){
        super();
        this.commonError = new CommonError(emBusinessError);
        this.commonError.setErrMsg(errMsg);
    }

    public CommonError getCommonError() {
        return commonError;
    }

    public void setCommonError(CommonError commonError) {
        this.commonError = commonError;
    }
}

           

四、枚舉類錯誤定義

package com.imooc.dianping.common;


public enum EmBusinessError {

    //通用的錯誤類型10000開頭
    NO_OBJECT_FOUND(10001,"請求對象不存在"),
    UNKNOWN_ERROR(10002,"未知錯誤"),
    NO_HANDLER_FOUND(10003,"找不到執行的路徑操作"),
    BIND_EXCEPTION_ERROR(10004,"請求參數錯誤"),
    PARAMETER_VALIDATION_ERROR(10005,"請求參數校驗失敗"),

    //使用者服務相關的錯誤類型20000開頭
    REGISTER_DUP_FAIL(20001,"使用者已存在"),

    LOGIN_FAIL(20002,"手機号或密碼錯誤"),

    //admin相關錯誤
    ADMIN_SHOULD_LOGIN(30001,"管理者需要先登入"),

    //品類相關錯誤
    CATEGORY_NAME_DUPLICATED(40001,"品類名已存在"),

    ;

    private Integer errCode;

    private String errMsg;

    EmBusinessError(Integer errCode, String errMsg) {
        this.errCode = errCode;
        this.errMsg = errMsg;
    }

    public Integer getErrCode() {
        return errCode;
    }

    public void setErrCode(Integer errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}

           

五、全局異常切面

package com.imooc.dianping.common;

import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 這個注解就是說,所有的Controller會被這個類檢測
@ControllerAdvice
public class GlobalExceptionHandler {
		// 這個注解是,隻要有類傳回 Exception或繼承了,則會執行doError。比如【BusinessException】
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public CommonRes doError(HttpServletRequest servletRequest, HttpServletResponse httpServletResponse,Exception ex){
        if(ex instanceof BusinessException){
            return CommonRes.create(((BusinessException)ex).getCommonError(),"fail");
        }else if(ex instanceof NoHandlerFoundException){
            CommonError commonError = new CommonError(EmBusinessError.NO_HANDLER_FOUND);
            return CommonRes.create(commonError,"fail");
        }else if(ex instanceof ServletRequestBindingException){
            CommonError commonError = new CommonError(EmBusinessError.BIND_EXCEPTION_ERROR);
            return CommonRes.create(commonError,"fail");
        } else {
            CommonError commonError = new CommonError(EmBusinessError.UNKNOWN_ERROR);
            return CommonRes.create(commonError,"fail");
        }

    }
}

           

如果是404如何處理:加入兩個配置項

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ToxOfwAJ-1624441203428)(千人千面Elasticsearch實戰-學習筆記.assets/image-20210623152739097.png)]

六、@Valid 校驗傳入的參數

最好是需要配合 BindingResult 做錯誤傳回

@RequestMapping("/register")
    @ResponseBody
    public CommonRes register(@Valid @RequestBody RegisterReq registerReq, BindingResult bindingResult)
            throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
        if(bindingResult.hasErrors()){
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,
                    CommonUtil.processErrorString(bindingResult));
        }

        UserModel registerUser = new UserModel();
        registerUser.setTelphone(registerReq.getTelphone());
        registerUser.setPassword(registerReq.getPassword());
        registerUser.setNickName(registerReq.getNickName());
        registerUser.setGender(registerReq.getGender());

        UserModel resUserModel = userService.register(registerUser);

        return CommonRes.create(resUserModel);
    }
           

七、異常工具類

用來處理BindingResult傳回的報錯String,給前端提供更詳細的傳回

package com.imooc.dianping.common;

import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

public class CommonUtil {
    public static String processErrorString(BindingResult bindingResult){
        if(!bindingResult.hasErrors()){
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        for(FieldError fieldError:bindingResult.getFieldErrors()){
            stringBuilder.append(fieldError.getDefaultMessage()+",");
        }
        return stringBuilder.substring(0,stringBuilder.length()-1);
    }
}
           

效果:

@RequestMapping("/get")
@ResponseBody
public CommonRes getUser(@RequestParam(name="id")Integer id) throws BusinessException {
    UserModel userModel = userService.getUser(id);
    if(userModel == null){
        //return CommonRes.create(new CommonError(EmBusinessError.NO_OBJECT_FOUND),"fail");
        throw new BusinessException(EmBusinessError.NO_OBJECT_FOUND);
    }else{
        return CommonRes.create(userModel);
    }

}
           

切面鑒權

沒有權限的直接跳轉到指定頁面,使用 Spring AOP做

課程4-6章

一、注解定義切面

package com.imooc.dianping.common;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AdminPermission {
    String produceType() default "text/html";
}

           

調Controller前置校驗

二、@Around() 環繞式

進入就啟用,return調方法
package com.imooc.dianping.common;

import com.imooc.dianping.controller.admin.AdminController;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Aspect
@Configuration
public class ControllerAspect {

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private HttpServletResponse httpServletResponse;

    @Around("execution(* com.imooc.dianping.controller.admin.*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public Object adminControllerBeforeValidation(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        AdminPermission adminPermission = method.getAnnotation(AdminPermission.class);
        if(adminPermission == null){
            //公共方法
            Object resultObject = joinPoint.proceed();
            return resultObject;
        }
        //判斷目前管理者是否登入,符合json傳回時的方法
        String email = (String) httpServletRequest.getSession().getAttribute(AdminController.CURRENT_ADMIN_SESSION);
        if(email == null){
            if(adminPermission.produceType().equals("text/html")){
                httpServletResponse.sendRedirect("/admin/admin/loginpage");
                return null;
            }else{
                CommonError commonError= new CommonError(EmBusinessError.ADMIN_SHOULD_LOGIN);
                return CommonRes.create(commonError,"fail");
            }

        }else{
            Object resultObject = joinPoint.proceed();
            return resultObject;
        }
    }
}

           

Elasticsearch注意點

Elasticsearch 作為非關系型資料庫

對于即使設定了mapping參數,但是如果新參數沒有産生沖突,還是會被記錄

千人千面Elasticsearch實戰學習筆記
千人千面Elasticsearch實戰學習筆記