首頁 > 軟體

SpringBoot例外處理器的使用與新增員工功能實現流程介紹

2022-10-14 14:03:48

承接上文 傳送門

一.完善登入功能

按照常理,只有登陸過後才能進入首頁,若沒有登陸則應當直接跳轉到登陸頁面,這樣的場景不就完美契合過濾器的功效嗎

下面,針對此功能來設計一個過濾器

@Slf4j
@WebFilter(filterName = "loginFilterCheck", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        log.info("攔截到請求:{}", request.getRequestURI());//{}相當於一個預留位置 可以實現動態變更
        filterChain.doFilter(request,response);
    }
}

通過它可以攔截到來自頁面的請求

對於攔截的請求,我們要做如下的處理:

1、獲取本次請求的URI,並定義不需要放行的資源路徑

        //獲取本次請求的uri
        String requestURI = request.getRequestURI();
        //定義不需要處理的資源路徑
        String[] urls=new String[]{
          "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**"
        };

為了解決萬用字元的引入而造成的路徑比較問題,我們可以通過路徑匹配器AntPathMatcher()來解決(由Spring為我們提供的工具)

2、判斷本次請求是否需要處理

當我們拿到工具物件之後,就可以通過遍歷字串陣列的方式,將請求中的uri與事先設定中不需要攔截資源路徑進行對比,然後封裝成一個check方法,就像這樣:

    public boolean check(String[] urls,String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match){
                return true;
            }
        }
        return false;
    }

3.如果是不需要處理的資源路徑則直接放行

        //判斷是否需要處理
        boolean check = check(urls, requestURI);
        //如果不需要處理就直接放行
        if (check){
            filterChain.doFilter(request,response);
            return;
        }

4、判斷登入狀態,如果已登入,則直接放行,如果未登入則返回未登入結果(通過從Session裡獲得物件,檢視是否為空來進行評判)

        //檢視登陸狀態 如果已登入 則直接放行
        if (!(request.getSession().getAttribute("employee") == null)) {
            filterChain.doFilter(request, response);
            return;
        }
        //如果未登入,則通過輸出流的方式向用戶端頁面響應資料
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));

二.新增員工功能

前端頁面已將寫好,,當用戶錄入資訊,就伴隨著一次請求,而後端要做的就是將在請求中將表單裡的資料儲存到資料庫中

新增員工,其實就是將我們新增頁面錄入的員工資料插入到employee表。需要注意,employee表中對username欄位加入了唯一約束,因為username是員工的登入賬號,必須是唯一的

我們該如何實現?

1、當頁面傳送ajax請求,表單中輸入的資料以json的形式提交到伺服器端

2、伺服器端Controller層接收頁面提交的資料並呼叫Service層將資料進行儲存

3、Service呼叫Mapper運算元據庫,儲存資料

Controller層如何設計呢?

1.毋庸置疑的是,首先要封裝一個用於儲存的方法save()

2.其次HttpServletRequest裡已經封裝了表單的資料,當一次請求發生其中的資料就被當作形參傳入了方法內,隨即就是設定表單中沒有的屬性,比如:setCreateTime,setUpdateTime,setCreateUser,setUpdateUser

總而言之,方法裡涵蓋了表單裡提交的資料和請求發生後動態變更的資料,而我們寫好了save()方法之後,就得去用Service層(employeeService)來執行這個方法將資料儲存到資料庫中,就像這樣:

    @PostMapping //前端的請求路徑為employee,而上述@RequestMapping("/employee")已寫好
    public R<String> save(HttpServletRequest request, @RequestBody Employee employee) {
        log.info("新增員工:{}", employee.toString());
        //設定初始預設密碼
       employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
        //設定更新時間
        employee.setCreateTime(LocalDateTime.now());//建立時間
        employee.setUpdateTime(LocalDateTime.now());//更新時間
        //獲取當前登入使用者的id
        Long empID = (Long) request.getSession().getAttribute("employee");
        employee.setCreateUser(empID);
        employee.setUpdateUser(empID);
        return R.success("新增員工成功!");
    }

當我們在前端表單中填好了新增員工的資訊後,點選儲存,後臺就執行如下的SQL:

三.例外處理的運用

寫好了新增的方法,我激動得新增了好幾個員工,但是當我新增了一個同名員工之後,程式執行的戛然而止,後臺竟然丟擲了異常:java.sql.SQLIntegrityConstraintViolationException

前端也報出了介面錯誤500,結合之前的表設計,不難想到我的username索引設定的是unique呀!唯一約束!

很顯然

我們需要處理這個異常,很多人第一時間想到的可能是:這則錯誤是service層呼叫save()方法所導致的,那我把save()方法try-catch不就行了嗎?

這樣想確實沒毛病是我的話我也這樣,可是以後業務一旦複雜起來,需要這樣處理的方法多了怎麼辦呢?我要去一個一個try-catch嗎?多麻煩啊!

這不就是所謂的寫死問題嘛!處理這種問題咱們在一個地方統一設定一下不久統統解決啊,跟MyBatis解決JDBC寫死問題是一個道理!

所以,我們使用異常攔截器進行全域性異常捕獲,這樣設定就輕鬆化解:

/**
 * 全域性例外處理
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class}) //攔截有指定註解類的Controller
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {
    /**
     * 例外處理方法,一旦Controller發生此異常就會被攔截到
     * @return
     */
    @ExceptionHandler({SQLIntegrityConstraintViolationException.class})
    public R<String>  excpHandler(SQLIntegrityConstraintViolationException exception) {//捕獲到的異常被傳到方法的形參裡
       log.info("異常資訊:"+exception.getMessage());
        //細化新增失敗後的返回資訊
        if (exception.getMessage().contains("Duplicate entry")){
            String[] s = exception.getMessage().split(" ");
            String msg=s[2]+"已存在!";
            return R.error(msg);
        }
        return R.error("發生異常!新增失敗!");
    }
}

一旦Controller層發生此異常就會被攔截到!

通過Debug,當程式出現因為重複新增而引起的異常時我們的msg就被細化了出來

到此這篇關於SpringBoot例外處理器的使用與新增員工功能實現流程介紹的文章就介紹到這了,更多相關SpringBoot例外處理器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com