SpringBoot異常處理器的使用與添加員工功能實現流程介紹
承接上文 傳送門
一.完善登錄功能
按照常理,只有登陸過后才能進入首頁,若沒有登陸則應當直接跳轉到登陸頁面,這樣的場景不就完美契合過濾器的功效嗎
下面,針對此功能來設計一個過濾器
@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());//{}相當于一個占位符 可以實現動態(tài)變更 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、判斷登錄狀態(tài),如果已登錄,則直接放行,如果未登錄則返回未登錄結果(通過從Session里獲得對象,查看是否為空來進行評判)
//查看登陸狀態(tài) 如果已登錄 則直接放行 if (!(request.getSession().getAttribute("employee") == null)) { filterChain.doFilter(request, response); return; } //如果未登錄,則通過輸出流的方式向客戶端頁面響應數據 response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
二.添加員工功能
前端頁面已將寫好,,當用戶錄入信息,就伴隨著一次請求,而后端要做的就是將在請求中將表單里的數據保存到數據庫中
新增員工,其實就是將我們添加頁面錄入的員工數據插入到employee表。需要注意,employee表中對username字段加入了唯一約束,因為username是員工的登錄賬號,必須是唯一的
我們該如何實現?
1、當頁面發(fā)送ajax請求,表單中輸入的數據以json的形式提交到服務器端
2、服務端Controller層接收頁面提交的數據并調用Service層將數據進行保存
3、Service調用Mapper操作數據庫,保存數據
Controller層如何設計呢?
1.毋庸置疑的是,首先要封裝一個用于保存的方法save()
2.其次HttpServletRequest里已經封裝了表單的數據,當一次請求發(fā)生其中的數據就被當作形參傳入了方法內,隨即就是設置表單中沒有的屬性,比如:setCreateTime,setUpdateTime,setCreateUser,setUpdateUser
總而言之,方法里涵蓋了表單里提交的數據和請求發(fā)生后動態(tài)變更的數據,而我們寫好了save()方法之后,就得去用Service層(employeeService)來執(zhí)行這個方法將數據保存到數據庫中,就像這樣:
@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());//創(chuàng)建時間 employee.setUpdateTime(LocalDateTime.now());//更新時間 //獲取當前登錄用戶的id Long empID = (Long) request.getSession().getAttribute("employee"); employee.setCreateUser(empID); employee.setUpdateUser(empID); return R.success("添加員工成功!"); }
當我們在前端表單中填好了新增員工的信息后,點擊保存,后臺就執(zhí)行如下的SQL:
三.異常處理的運用
寫好了添加的方法,我激動得添加了好幾個員工,但是當我添加了一個同名員工之后,程序運行的戛然而止,后臺竟然拋出了異常:java.sql.SQLIntegrityConstraintViolationException
前端也報出了接口錯誤500,結合之前的表設計,不難想到我的username索引設置的是unique呀!唯一約束!
很顯然
我們需要處理這個異常,很多人第一時間想到的可能是:這則錯誤是service層調用save()方法所導致的,那我把save()方法try-catch不就行了嗎?
這樣想確實沒毛病是我的話我也這樣,可是以后業(yè)務一旦復雜起來,需要這樣處理的方法多了怎么辦呢?我要去一個一個try-catch嗎?多麻煩??!
這不就是所謂的硬編碼問題嘛!處理這種問題咱們在一個地方統(tǒng)一配置一下不久統(tǒng)統(tǒng)解決啊,跟MyBatis解決JDBC硬編碼問題是一個道理!
所以,我們使用異常攔截器進行全局異常捕獲,這樣設置就輕松化解:
/** * 全局異常處理 */ @ControllerAdvice(annotations = {RestController.class, Controller.class}) //攔截有指定注解類的Controller @Slf4j @ResponseBody public class GlobalExceptionHandler { /** * 異常處理方法,一旦Controller發(fā)生此異常就會被攔截到 * @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("發(fā)生異常!添加失?。?); } }
一旦Controller層發(fā)生此異常就會被攔截到!
通過Debug,當程序出現因為重復添加而引起的異常時我們的msg就被細化了出來
到此這篇關于SpringBoot異常處理器的使用與添加員工功能實現流程介紹的文章就介紹到這了,更多相關SpringBoot異常處理器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Boot單元測試中使用mockito框架mock掉整個RedisTemplate的示例
今天小編就為大家分享一篇關于Spring Boot單元測試中使用mockito框架mock掉整個RedisTemplate的示例,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12