SpringBoot異常處理器的使用與添加員工功能實(shí)現(xiàn)流程介紹
承接上文 傳送門
一.完善登錄功能
按照常理,只有登陸過后才能進(jìn)入首頁(yè),若沒有登陸則應(yīng)當(dāng)直接跳轉(zhuǎn)到登陸頁(yè)面,這樣的場(chǎng)景不就完美契合過濾器的功效嗎
下面,針對(duì)此功能來設(shè)計(jì)一個(gè)過濾器
@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("攔截到請(qǐng)求:{}", request.getRequestURI());//{}相當(dāng)于一個(gè)占位符 可以實(shí)現(xiàn)動(dòng)態(tài)變更 filterChain.doFilter(request,response); } }
通過它可以攔截到來自頁(yè)面的請(qǐng)求
對(duì)于攔截的請(qǐng)求,我們要做如下的處理:
1、獲取本次請(qǐng)求的URI,并定義不需要放行的資源路徑
//獲取本次請(qǐng)求的uri String requestURI = request.getRequestURI(); //定義不需要處理的資源路徑 String[] urls=new String[]{ "/employee/login", "/employee/logout", "/backend/**", "/front/**" };
為了解決通配符的引入而造成的路徑比較問題,我們可以通過路徑匹配器AntPathMatcher()來解決(由Spring為我們提供的工具)
2、判斷本次請(qǐng)求是否需要處理
當(dāng)我們拿到工具對(duì)象之后,就可以通過遍歷字符串?dāng)?shù)組的方式,將請(qǐng)求中的uri與事先設(shè)定中不需要攔截資源路徑進(jìn)行對(duì)比,然后封裝成一個(gè)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),如果已登錄,則直接放行,如果未登錄則返回未登錄結(jié)果(通過從Session里獲得對(duì)象,查看是否為空來進(jìn)行評(píng)判)
//查看登陸狀態(tài) 如果已登錄 則直接放行 if (!(request.getSession().getAttribute("employee") == null)) { filterChain.doFilter(request, response); return; } //如果未登錄,則通過輸出流的方式向客戶端頁(yè)面響應(yīng)數(shù)據(jù) response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
二.添加員工功能
前端頁(yè)面已將寫好,,當(dāng)用戶錄入信息,就伴隨著一次請(qǐng)求,而后端要做的就是將在請(qǐng)求中將表單里的數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中
新增員工,其實(shí)就是將我們添加頁(yè)面錄入的員工數(shù)據(jù)插入到employee表。需要注意,employee表中對(duì)username字段加入了唯一約束,因?yàn)閡sername是員工的登錄賬號(hào),必須是唯一的
我們?cè)撊绾螌?shí)現(xiàn)?
1、當(dāng)頁(yè)面發(fā)送ajax請(qǐng)求,表單中輸入的數(shù)據(jù)以json的形式提交到服務(wù)器端
2、服務(wù)端Controller層接收頁(yè)面提交的數(shù)據(jù)并調(diào)用Service層將數(shù)據(jù)進(jìn)行保存
3、Service調(diào)用Mapper操作數(shù)據(jù)庫(kù),保存數(shù)據(jù)
Controller層如何設(shè)計(jì)呢?
1.毋庸置疑的是,首先要封裝一個(gè)用于保存的方法save()
2.其次HttpServletRequest里已經(jīng)封裝了表單的數(shù)據(jù),當(dāng)一次請(qǐng)求發(fā)生其中的數(shù)據(jù)就被當(dāng)作形參傳入了方法內(nèi),隨即就是設(shè)置表單中沒有的屬性,比如:setCreateTime,setUpdateTime,setCreateUser,setUpdateUser
總而言之,方法里涵蓋了表單里提交的數(shù)據(jù)和請(qǐng)求發(fā)生后動(dòng)態(tài)變更的數(shù)據(jù),而我們寫好了save()方法之后,就得去用Service層(employeeService)來執(zhí)行這個(gè)方法將數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中,就像這樣:
@PostMapping //前端的請(qǐng)求路徑為employee,而上述@RequestMapping("/employee")已寫好 public R<String> save(HttpServletRequest request, @RequestBody Employee employee) { log.info("新增員工:{}", employee.toString()); //設(shè)置初始默認(rèn)密碼 employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); //設(shè)置更新時(shí)間 employee.setCreateTime(LocalDateTime.now());//創(chuàng)建時(shí)間 employee.setUpdateTime(LocalDateTime.now());//更新時(shí)間 //獲取當(dāng)前登錄用戶的id Long empID = (Long) request.getSession().getAttribute("employee"); employee.setCreateUser(empID); employee.setUpdateUser(empID); return R.success("添加員工成功!"); }
當(dāng)我們?cè)谇岸吮韱沃刑詈昧诵略鰡T工的信息后,點(diǎn)擊保存,后臺(tái)就執(zhí)行如下的SQL:
三.異常處理的運(yùn)用
寫好了添加的方法,我激動(dòng)得添加了好幾個(gè)員工,但是當(dāng)我添加了一個(gè)同名員工之后,程序運(yùn)行的戛然而止,后臺(tái)竟然拋出了異常:java.sql.SQLIntegrityConstraintViolationException
前端也報(bào)出了接口錯(cuò)誤500,結(jié)合之前的表設(shè)計(jì),不難想到我的username索引設(shè)置的是unique呀!唯一約束!
很顯然
我們需要處理這個(gè)異常,很多人第一時(shí)間想到的可能是:這則錯(cuò)誤是service層調(diào)用save()方法所導(dǎo)致的,那我把save()方法try-catch不就行了嗎?
這樣想確實(shí)沒毛病是我的話我也這樣,可是以后業(yè)務(wù)一旦復(fù)雜起來,需要這樣處理的方法多了怎么辦呢?我要去一個(gè)一個(gè)try-catch嗎?多麻煩??!
這不就是所謂的硬編碼問題嘛!處理這種問題咱們?cè)谝粋€(gè)地方統(tǒng)一配置一下不久統(tǒng)統(tǒng)解決啊,跟MyBatis解決JDBC硬編碼問題是一個(gè)道理!
所以,我們使用異常攔截器進(jìn)行全局異常捕獲,這樣設(shè)置就輕松化解:
/** * 全局異常處理 */ @ControllerAdvice(annotations = {RestController.class, Controller.class}) //攔截有指定注解類的Controller @Slf4j @ResponseBody public class GlobalExceptionHandler { /** * 異常處理方法,一旦Controller發(fā)生此異常就會(huì)被攔截到 * @return */ @ExceptionHandler({SQLIntegrityConstraintViolationException.class}) public R<String> excpHandler(SQLIntegrityConstraintViolationException exception) {//捕獲到的異常被傳到方法的形參里 log.info("異常信息:"+exception.getMessage()); //細(xì)化添加失敗后的返回信息 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ā)生此異常就會(huì)被攔截到!
通過Debug,當(dāng)程序出現(xiàn)因?yàn)橹貜?fù)添加而引起的異常時(shí)我們的msg就被細(xì)化了出來
到此這篇關(guān)于SpringBoot異常處理器的使用與添加員工功能實(shí)現(xiàn)流程介紹的文章就介紹到這了,更多相關(guān)SpringBoot異常處理器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java運(yùn)行時(shí)數(shù)據(jù)區(qū)概述詳解
這篇文章主要介紹了Java運(yùn)行時(shí)數(shù)據(jù)區(qū)概述,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03Springboot動(dòng)態(tài)配置AOP切點(diǎn)詳解
這篇文章主要介紹了Springboot動(dòng)態(tài)配置AOP切點(diǎn)詳解,Springboot 可以定義注解切點(diǎn)去攔截注解修飾的類方法以及execution(xxxx)切點(diǎn)去攔截具體的類方法,默認(rèn)情況下我們都會(huì)使用注解@PointCut去定義切點(diǎn),然后定義切面攔截切點(diǎn),需要的朋友可以參考下2023-09-09Spring Boot單元測(cè)試中使用mockito框架mock掉整個(gè)RedisTemplate的示例
今天小編就為大家分享一篇關(guān)于Spring Boot單元測(cè)試中使用mockito框架mock掉整個(gè)RedisTemplate的示例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12Java使用原型模式展現(xiàn)每日生活應(yīng)用案例詳解
這篇文章主要介紹了Java使用原型模式展現(xiàn)每日生活應(yīng)用案例,較為詳細(xì)的分析了原型模式的概念、原理及Java使用原型模式展現(xiàn)每日生活案例的相關(guān)操作步驟與注意事項(xiàng),需要的朋友可以參考下2018-05-05