1. 程式人生 > 其它 >入門專案記錄(個人學習記錄)

入門專案記錄(個人學習記錄)

1.登入驗證。未登入使用者需要設定過濾器進行過濾。

        @注:Filter是過濾器,可以過濾任何路徑。HandleInterceptor是攔截器,基於aop,用於攔截  訪問控制器前的請求。攔截器不通過的話,需要攜帶請求和響應,進行請求轉發。攔截器定義好之後,需要在配置類中進行配置,才能生效。

  1.1定義一個類,新增webFilter註解,宣告過濾器名稱和過濾物件

  1.2實現Filter介面,重寫方法

    定義一個ant路徑匹配器,常量

    獲取本次請求的uri。定義不需要攔截的uri。判斷是否需要進行攔截

    判斷是否登入,登入的話則放行,如果沒有登入,則根據前端要求,進行資料輸出


/*檢查使用者是否登入*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
/*定義路徑匹配器,支援萬用字元*/
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
/*1.獲取本次的url*/
String requestURI = request.getRequestURI();
log.info("攔截到請求:{}",requestURI);
/*2.判斷是否需要處理*/
/*定義不需要處理的url,登入登出、靜態資源*/
String[] urls =new String[]{
"/employee/login",
"/employee/logout",
"/backend/**", // 後臺管理 靜態資源,html和js檔案
"/front/**", // 前臺門戶 靜態資源,html和js檔案
"dkljfghdjklghdfg"
};
// 例如:http://localhost:8080/backend/index.html /backend/index.html


/*判斷url與urls*/
boolean check = check(urls, requestURI);
/*遍歷結束,還是沒有包含,就需要進行處理*/
if(check){
log.info("本次請求{}不需要處理",requestURI);
/*如果結果為true,表示包含有路徑,直接放行*/
filterChain.doFilter(request,response);
return;
}
/*3.如果不需要處理直接放行*/

/*4.如果已經登入直接放行*/
/*判斷是否登入*/
/* HttpSession session = request.getSession();
Object id = session.getAttribute("employee");//獲取當時傳入session的id
*//*判斷id是否為空,非空就放行*//*
if(id != null){
log.info("使用者已登入,使用者id為:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
}*/
if(request.getSession().getAttribute("employee") != null){
Long employeeId = (Long) request.getSession().getAttribute("employee");
log.info("使用者已登入,使用者id為:{}",employeeId);

/*將id設定進入TreadLocal中*/
BaseContext.setCurrentId(employeeId);
/*放行*/
filterChain.doFilter(request,response);
return;
}
log.info("使用者未登入");
/*5.如果沒有登入就返回登入頁面*/
/*如果到了這裡,證明需要進行處理,返回登入頁面
* 根據前端程式碼要求,需要用輸出流,去輸出data.message=未登入*/
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}

/**
*
* @param urls
* @param requestURL
* @return
*/
public boolean check(String[] urls,String requestURL){
for (String url : urls) {
// 匹配url
boolean match =PATH_MATCHER.match(url, requestURL);
if(match){
/*遍歷urls如果匹配,則返回ture*/
return true;
}
}
return false;
}

public boolean checkMyPath(String[] urls,String requestURL) {
for (String url : urls) {
// 包含backend,代表當前匹配路徑是後臺管理的靜態資源。且本次請求路徑包含/backend,代表本次請求的是後臺靜態資源
if (url.contains("backend") && requestURL.contains("/backend")) {
return true;
}
}
return false;
}
}

2.異常處理。如果資料庫中的需要唯一的欄位重複了,需要提示使用者,此名稱已經存在。

  2.1定義一個全域性異常處理類。添加註解 annotations ={##.class},#代表需要進行處理的類。一般設定為controller、RestController

  2.2定義public方法,新增exceptionHandler註解(#.class),標明需要攔截的異常類。


/*全域性異常處理,攔截所有restcontroller類*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody//這個方法需要返回json資料,
public class GlobalExceptionHandler {

/**/
@ExceptionHandler(Exception.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
/*列印異常資訊*/
System.out.println(ex.getMessage());

/*按照空格將錯誤資訊的語句拆分,並放入陣列中*/
String[] message = ex.getMessage().split(" ");
//拿到第三個單詞
return R.error(message[2]+"已存在");
}

@ExceptionHandler(CustomException.class)//標明要處理的異常類
public R<String> exceptionHandler(CustomException ex){
/*列印異常資訊*/
System.out.println(ex.getMessage());
return R.error(ex.getMessage());
}
}

3.雪花演算法id處理。需要配置一個json轉換string工具

 

4.公共欄位填充。需要配置一個可以自動填充的類。

  4.1建立一個類,實現元資料物件處理器MetaObjectHandler,新增conmponent交給spring容器。重寫兩個方法,更新時填充和建立時填充,並且需要在pojo物件中新增Filed(fill)註解

  4.2需要注意的是,自動填充的時候,需要獲取當前已經登入的id,而這個Id需要靠TreadLocal方法來獲取

    4.2.1BaseContext 是一個基於TreadLocal的實現類,需要自己new一個TreadLocal,並提供get和set方法


/**
* 這是一個元資料物件處理器
*/
@Slf4j
@Component//交給spring管理
public class MyMetaObjectHandle implements MetaObjectHandler {//根據框架要求實現MetaObjectHandler,重寫兩個方法

@Override
public void insertFill(MetaObject metaObject) {
/*新增時自動填充*/
log.info("新增時自動填充....");
log.info(metaObject.toString());

/*填充方法*/
metaObject.setValue("createTime",LocalDateTime.now());
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("createUser",BaseContext.getCurrentId());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}

@Override
public void updateFill(MetaObject metaObject) {
/*更新時自動填充*/
log.info("更新時自動填充....");
log.info(metaObject.toString());
/*填充方法*/

metaObject.setValue("updateTime",LocalDateTime.now());

metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}

5.返回值型別。需要定義一個R型別的返回值,根據前端要求,進行處理返回值。