6. springmvc的工作流程是什么?
SpringMVC流程
1、 用戶向服務(wù)端發(fā)送一次請求,這個請求會先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到請求后會調(diào)用HandlerMapping處理器映射器。由此得知,該請求該由哪個Controller來處理(并未調(diào)用Controller,只是得知)
3、DispatcherServlet調(diào)用HandlerAdapter處理器適配器,告訴處理器適配器應(yīng)該要去執(zhí)行哪個Controller
4、HandlerAdapter處理器適配器去執(zhí)行Controller并得到ModelAndView(數(shù)據(jù)和視圖),并層層返回給DispatcherServlet
5、DispatcherServlet將ModelAndView交給ViewReslover視圖解析器解析,然后返回真正的視圖。
6、DispatcherServlet將模型數(shù)據(jù)填充到視圖中
7、DispatcherServlet將結(jié)果響應(yīng)給用戶
7. mybatis的工作原理是什么? mybatis的緩存的理解?
Mybatis工作原理
1.通過SqlSessionFactoryBuilder從mybatis-config.xml配置文件中構(gòu)建出SqlSessionFactory。
2.SqlSessionFactory的實例開啟一個SqlSession
3.SqlSession實例獲得Mapper對象并運行Mapper映射的SQL語句,完成對數(shù)據(jù)庫的CRUD和事務(wù)提交以及事務(wù)失敗的回滾,之后關(guān)閉Session。
mybatis的緩存的理解?
當(dāng)一個查詢發(fā)生的時候,Mybatis 會在當(dāng)前會話中查找是否已經(jīng)有過相同的查詢,有的話就直接拿緩存,不去數(shù)據(jù)庫查了,線程執(zhí)行完畢,緩存就被清掉了。二級緩存是進程級別的,通過在 mapper 文件中增加節(jié)點來啟用,一個mapper可以含有多個會話。
8. mybatis中#{}和${}的區(qū)別?
#{}是預(yù)編譯處理,${}是字符串替換;
Mybatis在處理#{}時,會將sql中的#{}替換為?號,調(diào)用PreparedStatement的set方法來賦值;
Mybatis在處理${}時,就是把${}替換成變量的值;
使用#{}可以有效的防止SQL注入,提高系統(tǒng)安全性。
9. springboot的異常處理?
SpringBoot中有一個ControllerAdvice的注解,使用該注解表示開啟了全局異常的捕獲,我們只需在自定義一個方法使用ExceptionHandler注解然后定義捕獲異常的類型即可對這些捕獲的異常進行統(tǒng)一的處理。
10. spring中如何配置攔截器、過濾器?
創(chuàng)建一個攔截器,實現(xiàn)HandlerInterceptor接口,重寫此接口的三個方法,preHandle、postHandle、afterCompletion,只有第一個方法返回true時,才會進入Controller,否則不會處理Controller內(nèi)容,也不會執(zhí)行后邊兩個方法。
然后在xml文件里配置攔截路徑
過濾器:定義一個類實現(xiàn)Filter接口
這一接口含有三個過濾器必須執(zhí)行的方法:
doFilter(ServletRequest, ServletResponse, FilterChain):這是一個完成過濾行為的方法。這同樣是上游過濾器調(diào)用的方法。引入的FilterChain對象提供了后續(xù)過濾器所要調(diào)用的信息。如果該過濾器是過濾器鏈中的最后一個過濾器,則將請求交給被請求資源。也可以直接給客戶端返回響應(yīng)信息。
init(FilterConfig):由Web容器來調(diào)用完成的初始化工作。它保證了在第一次doFilter()調(diào)用前由容器調(diào)用。您能獲取在 web.xml 文件中指定的初始化參數(shù)。
destroy():由Web容器來調(diào)用來釋放資源,doFilter()中的所有活動都被該實例終止后,調(diào)用該方法。
配置過濾器:在web.xml配置文件里配置filter和filter-mapping的<url-pattern>/*</url-pattern>屬性即可
11.spring管理的bean是否會存在并發(fā)?
Spring的bean默認(rèn)scope屬性為singleTon,即單例的,有線程安全問題
如果設(shè)置@Scope(“prototype”),則每次都會創(chuàng)建新對象,不存在線程安全問題
12.spring-session的原理是什么?
Spring Session是為了解決多進程session共享的問題
原理:攔截請求,將之前在服務(wù)器內(nèi)存中進行 Session 創(chuàng)建銷毀的動作,改成在 Redis 中創(chuàng)建。
13. spring的類加載器是什么?
ClassLoader即常說的類加載器,其功能是用于從Class文件加載所需的類,主要場景用于熱部署、代碼熱替換等場景。

從java虛擬機的角度講,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap ClassLoader),由C++實現(xiàn),另一種就是所有其它的加載器,是由java實現(xiàn)的,獨立于虛擬機外部,并且全都繼承自java.lang.ClassLoader。
從java開發(fā)人員來講,類加載器還可以劃分的更細(xì)致一些:
1、 啟動類加載器(Bootstrap ClassLoader):這個類加載器負(fù)責(zé)將存放在<JAVA_HOME>\lib目錄中,或者被-XbootClasspath參數(shù)所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如rt.jar,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中。啟動類加載器無法直接被java程序引用,用戶在編寫自定義類加載器時,如果需要把加載請求委派給引導(dǎo)類加載器,那直接使用null代替即可。
2、 擴展類加載器(Extension ClassLoader):這個加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負(fù)責(zé)加載<JAVA_HOME>\lib\ext目錄中,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的類庫,開發(fā)者可以直接使用擴展類加載器。
3、 應(yīng)用程序類加載器(Application ClassLoader):這個類加載器由sun.misc.Launcher$AppClassLoader實現(xiàn)。由于這個類加載器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也稱它為系統(tǒng)類加載器,它負(fù)責(zé)加載用戶類路徑(classpath)上指定的類庫,開發(fā)者可以直接使用這個類加載器,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中的默認(rèn)類加載器
14. springCloud的組件有哪些?作用分別是什么?
eureka (提供服務(wù)注冊與發(fā)現(xiàn)功能)
ribbon(提供負(fù)載均衡功能)
Feign(整合了ribbon和Hystrix,具有負(fù)載均衡和熔斷限流等功能)
Ribbon 和 Feign 的區(qū)別
Ribbon基于http和tcp的客戶端負(fù)載均衡工具,通過restTemplate模擬http請求 步驟相當(dāng)繁瑣
Feign在ribbon的基礎(chǔ)上進行過改進,使用起來更加方便 并且他默認(rèn)集成了ribbon的負(fù)載均衡機制
Hystrix (提供了熔斷限流,合并請求等功能)
Zuul (提供了智能路由的功能)
Hystrix Dashboard (提供了服務(wù)監(jiān)控的功能,提供了數(shù)據(jù)監(jiān)控和友好的圖形化界面)
Hystrix Turbine (Hystrix Turbine將每個服務(wù)Hystrix Dashboard數(shù)據(jù)進行了整合。也是監(jiān)控系統(tǒng)的功能)
spring cloud config (提供了統(tǒng)一配置的功能)
Spring Cloud Bus (提供了配置實時更新的功能)
15. dubbo和 springcloud的區(qū)別和優(yōu)缺點?
dubbo由于是二進制的傳輸,占用帶寬會更少
springCloud是http協(xié)議傳輸,帶寬會比較多,同時使用http協(xié)議一般會使用JSON報文,消耗會更大
dubbo的開發(fā)難度較大,原因是dubbo的jar包依賴問題很多大型工程無法解決
dubbo的注冊中心可以選擇zk,redis等多種,springcloud的注冊中心只能用eureka或者自研
16. Gateway的動態(tài)路由如何實現(xiàn)?

配置Nacos監(jiān)聽器,監(jiān)聽路由配置信息的變化
創(chuàng)建配置類
添加Nacos路由配置
測試
啟動網(wǎng)關(guān)通過 /actuator/gateway/routes 端點查看當(dāng)前路由信息
17.鑒權(quán)框架的了解和使用?
一般有shiro和spring-security
第一步:
構(gòu)建一個spring boot工程,這個利用idea的Spring Initializr很容易就構(gòu)建了
第二步:
引入spring boot為spring security的包裝的起步依賴,也就是上面提到的spring-boot-starter-security
spring security和shiro的異同
相同點
1、認(rèn)證功能2、授權(quán)功能3、加密功能4、會話管理5、緩存支持
6、rememberMe功能
不同點
1、Spring Security 基于Spring 開發(fā),項目若使用 Spring 作為基礎(chǔ),配合 Spring Security 做權(quán)限更加方便,而 Shiro 需要和 Spring 進行整合開發(fā);
2、Spring Security 功能比 Shiro 更加豐富些,例如安全維護方面;
3、Spring Security 社區(qū)資源相對比 Shiro 更加豐富;
Spring Security對Oauth、OpenID也有支持,Shiro則需要自己手動實現(xiàn)。而且Spring Security的權(quán)限細(xì)粒度更高
spring security 接口 RequestMatcher 用于匹配路徑,對路徑做特殊的請求,類似于shiro的
抽象類 PathMatchingFilter,但是 RequestMatcher 作用粒度更細(xì)
4、Shiro 的配置和使用比較簡單,Spring Security 上手復(fù)雜些;
5、Shiro 依賴性低,不需要任何框架和容器,可以獨立運行.Spring Security 依賴Spring容器;
6、shiro 不僅僅可以使用在web中,還支持非web項目它可以工作在任何應(yīng)用環(huán)境中。在集群會話時Shiro最重要的一個好處或許就是它的會話是獨立于容器的。
apache shiro的話,簡單,易用,功能也強大,spring官網(wǎng)就是用的shiro,可見shiro的強大
18. mybatis同時操作同一條數(shù)據(jù)該怎么解決并發(fā)問題?
樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基于數(shù)據(jù)版本(Version)記錄機制實現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個 “version” 字段來實現(xiàn)。
讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進行比對,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。
對于上面修改用戶帳戶信息的例子而言,假設(shè)數(shù)據(jù)庫中帳戶信息表中有一個version字段,當(dāng)前值為1;而當(dāng)前帳戶余額字段(balance)為1000元。假設(shè)操作員A先更新完,操作員B后更新。
a、操作員A此時將其讀出(version=1),并從其帳戶余額中增加100(1000+100=1100)。
b、在操作員A操作的過程中,操作員B也讀入此用戶信息(version=1),并從其帳戶余額中扣除50(1000-50=950)。
c、操作員A完成了修改工作,將數(shù)據(jù)版本號加一(version=2),連同帳戶增加后余額(balance=1100),提交至數(shù)據(jù)庫更新,此時由于提交數(shù)據(jù)版本大于數(shù)據(jù)庫記錄當(dāng)前版本,數(shù)據(jù)被更新,數(shù)據(jù)庫記錄version更新為2。
d、操作員B完成了操作,也將版本號加一(version=2)試圖向數(shù)據(jù)庫提交數(shù)據(jù)(balance=950),但此時比對數(shù)據(jù)庫記錄版本時發(fā)現(xiàn),操作員B提交的數(shù)據(jù)版本號為2,數(shù)據(jù)庫記錄當(dāng)前版本也為2,不滿足 “提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新 “的樂觀鎖策略,因此,操作員B的提交被駁回。
這樣,就避免了操作員B用基于version=1的舊數(shù)據(jù)修改的結(jié)果覆蓋操作員A的操作結(jié)果的可能。
悲觀鎖
總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會阻塞直到它拿到鎖(共享資源每次只給一個線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨占鎖就是悲觀鎖思想的實現(xiàn)。
總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號機制和CAS算法實現(xiàn)。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫提供的類似于write_condition機制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現(xiàn)方式CAS實現(xiàn)的。
從上面對兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點,不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下(多讀場景),即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。但如果是多寫的情況,一般會經(jīng)常產(chǎn)生沖突,這就會導(dǎo)致上層應(yīng)用會不斷的進行retry,這樣反倒是降低了性能,所以一般多寫的場景下用悲觀鎖就比較合適
19. mybatis中傳遞參數(shù)有哪些方式?
方式一、順序傳遞參數(shù)
mapper.java文件:
publicUserselectUser(String name,intdeptId);
mapper.xml文件:
<selectid="selectUser"resultType="com.wyj.entity.po.User">select * from user where userName = #{0} and deptId = #{1}</select>
注意:里面的數(shù)字代表你傳入?yún)?shù)的順序,不是特別建議使用這種方法傳遞參數(shù),特別是參數(shù)個數(shù)多的時候
mapper.java文件:
publicUserselectUser(@Param("userName")String name,int@Param("deptId")id);
mapper.xml文件:
<selectid="selectUser"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
注意:在xml文件中就只能以在@Param注解中聲明的參數(shù)名稱獲取參數(shù)
mapper.java文件:
publicUserselectUser(Map<String,Object>params);
mapper.xml文件:
<selectid="selectUser"parameterType="java.util.Map"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
mapper.java文件:
publicUserselectUser(User user);
mapper.xml文件:
<selectid="selectUser"parameterType="com.wyj.entity.po.User"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
20. spring中bean的作用域有哪些?生命周期?


Bean 的生命周期
1 單例bean對象
1 對象創(chuàng)建: 當(dāng)應(yīng)用加載, 創(chuàng)建spring容器時, 對象就被創(chuàng)建了
2 對象存活: 只要容器存在, 對象一直存活
3 對象銷毀: 當(dāng)應(yīng)用卸載, 銷毀容器時, 對象被銷毀
2 多例bean對象
1 對象創(chuàng)建: 當(dāng)使用對象時, 創(chuàng)建新的對象實例
2 對象存活: 只要對象在使用中, 對象一直存活
3 對象銷毀: 當(dāng)對象長時間不用時, 被java的垃圾回收器回收
21.怎么實現(xiàn) mybatis批量插入?
包括以下兩種具體方式:
1.mapping.xml中insert語句可以寫成單條插入,在調(diào)用方循環(huán)1000次
2.insert標(biāo)簽加上foreach標(biāo)簽
測試xml:
<insert id="insertList">
insert intouser_info(id,user_name,age)values
<foreach collection="list"item="item"separator=",">
(#{item.id},#{item.userName},#{item.age})
</foreach>
</insert>
其實就是insert標(biāo)簽加上foreach標(biāo)簽
用來測試批量插入的數(shù)據(jù)和服務(wù)層:
@ServicepublicclassUserInfoService{@AutowiredprivateUserInfoDao userInfoDao;publicvoidinsertList(){List<UserInfo>userInfoList=Lists.newArrayList();
userInfoList.add(newUserInfo("1","jiejie","17"));
userInfoList.add(newUserInfo("2","jiejie","18"));
userInfoList.add(newUserInfo("3","jiejie","30"));
userInfoDao.insertList(userInfoList);}}
測試結(jié)果:
可以發(fā)現(xiàn)已經(jīng)實現(xiàn)批量插入的功能了。
總結(jié)
通過insert標(biāo)簽加上foreach標(biāo)簽,可以實現(xiàn)Mybatis批量插入的功能。
22. Junit如何使用?
導(dǎo)入jar包 添加Test注解即可
springboot整合:
1.在pom.xml中添加junit環(huán)境的依賴
<dependency>
? ? <groupId>org.springframework.boot</groupId>
? ? <artifactId>spring-boot-starter-test</artifactId>
</dependency>
2.在src/test/java下建立測試類
例:
@RunWith(value = SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={app.class})
public class serviceTest {
? ? @Autowired
? ? private serviceImpl serviceimpl;
? ? @Test
? ? public void testAdd() {
? ? ? ? this.serviceimpl.add();
? ? }
}
說明:@RunWith:啟動器
SpringJUnit4ClassRunner.class:讓 junit 與 spring 環(huán)境進行整合
@SpringBootTest(classes={App.class}) 1,當(dāng)前類為 springBoot 的測試類2,加載 SpringBoot 啟動類。啟動SpringBoot
23. spring的工廠模式如何使用?
1.把工廠假設(shè)為一個汽車制造廠
2.首先抽象出產(chǎn)品的父類
3.實現(xiàn)具體的產(chǎn)品類
4.實現(xiàn)一個工廠類,并寫一個靜態(tài)方法根據(jù)參數(shù)的不同返回不同的實例
24. springboot是如何對線程進行封裝的?
配置類上加上@EnableAsync注解,就可以在想多線程支持的方法上加上@Async該方法就可以自持多線程了
25. springboot中 Starter種類有哪些?如何寫一個springboot的 Starter組件?
spring-boot-starter-tomcat
spring-boot-starter-jdbc?
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-mongodb
spring-boot-starter-data-redis
如果你想要自己創(chuàng)建一個starter,那么基本上包含以下幾步
創(chuàng)建一個starter項目,關(guān)于項目的命名你可以參考這里
創(chuàng)建一個ConfigurationProperties用于保存你的配置信息(如果你的項目不使用配置信息則可以跳過這一步,不過這種情況非常少見)
創(chuàng)建一個AutoConfiguration,引用定義好的配置信息;在AutoConfiguration中實現(xiàn)所有starter應(yīng)該完成的操作,并且把這個類加入spring.factories配置文件中進行聲明
打包項目,之后在一個SpringBoot項目中引入該項目依賴,然后就可以使用該starter了
26.設(shè)計一個開放接口,如何保證接口安全性?
1.簽名? ?
根據(jù)用戶名或者用戶id,結(jié)合用戶的ip或者設(shè)備號,生成一個token。在請求后臺,后臺獲取http的head中的token,校驗是否合法(和數(shù)據(jù)庫或者redis中記錄的是否一致,在登錄或者初始化的時候,存入數(shù)據(jù)庫/redis)?
2.加密
客戶端和服務(wù)器都保存一個秘鑰,每次傳輸都加密,服務(wù)端根據(jù)秘鑰解密。
1.文件上傳和下載如何實現(xiàn)?
文件上傳
文件上傳的本質(zhì)是IO流的從操作;客戶端:
1.必須使用post,post才能攜帶大數(shù)據(jù)
2.必須設(shè)置type=“file” name="file"必須要有名字
3.必須要設(shè)置enctype="multipart/form-data"服務(wù)器端:通過request.getInputStream()獲取字節(jié)輸入流,讀取請求正文內(nèi)容;將上傳內(nèi)容得到,保存在服務(wù)器端,就完成了文件上傳;實際使用直接用框架中的api就可以,commons-fileupload是apache提供的一套文件上傳工具;
文件下載有兩種方法:
1.超鏈接下載:如果文件能被瀏覽器解析,點擊就會打開文件,如果要下載,需要使用右鍵另存為,不能被瀏覽器解析的文件,點擊就下載;
2.通過服務(wù)器流回寫到瀏覽器下載;要設(shè)置MIME,即設(shè)置setcontentType(String mimeType);瀏覽器能解析的直接顯示,不能解析的直接下載;
獲取文件的mimeType類型:String mimeType=this.getServletContext().getMimeType(filename);
如果設(shè)置響應(yīng)頭response.setHeader("content-disposition","attachment;filename=下載的文件名稱");不管瀏覽器能不能解析,
都是下載操作;
2.第三方的工作流有哪些?如何使用的?
常見的工作流框架
Activity5.1.3、JBPM4.4、OSWorkFlow、WorkFlow
在Java領(lǐng)域,JBPM和Activity是兩個主流的工作流系統(tǒng),而Activity的出現(xiàn)無疑將會取代JBPM(Activity的開發(fā)者就是從Jbpm開發(fā)者出來的)。
avtivity的基本操作:
設(shè)計流程圖(各種組件,如連線、用戶任務(wù)、網(wǎng)關(guān))
流程定義增刪改查
流程變量增刪改查
啟動流程定義
任務(wù)增刪改查
完成任務(wù)
歷史信息查詢
java工作流怎么用activity
常用的是:activiti-engine-5.91.jar,activiti-spring-5.9.jar;
解釋:以上兩個只是activiti工作流的常用包,通常會配置如spring開發(fā)的java包,還有數(shù)據(jù)庫jar包等進行使用,但具體要用到什么包,這個和業(yè)務(wù)開發(fā)的邏輯有關(guān)系,也沒辦法進行詳細(xì)說明的,所以只需要先下載常用的兩個,其余的輔助包如:日志包、spring包、數(shù)據(jù)庫包、hibernate包、struts包、mybatis包等根據(jù)實際需要添加即可。
3.對 activemq、 rabbitmq、 kafka的了解和使用?消息發(fā)送失敗如何處理?如何防止消息的重復(fù)消費?
ActiveMQ介紹?MQ是消息中間件,是一種在分布式系統(tǒng)中應(yīng)用程序借以傳遞消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的開源項目,完全支持JMS1.1和J2EE1.4規(guī)范的JMS Provider實現(xiàn)。 特點: 1、支持多種語言編寫客戶端 2、對spring的支持,很容易和spring整合 3、支持多種傳輸協(xié)議:TCP,SSL,NIO,UDP等 4、支持AJAX 消息形式: 1、點對點(queue) 2、一對多(topic)
RabbitMQ是由erlang語言開發(fā),基于AMQP(Advanced Message Queue 高級消息隊列協(xié)議)協(xié)議實現(xiàn)的消息隊列,它是一種應(yīng)用程序之間的通信方法,消息隊列在分布式系統(tǒng)開發(fā)中應(yīng)用非常廣泛。
Kafka是分布式發(fā)布-訂閱消息系統(tǒng),它最初是由LinkedIn公司開發(fā)的,之后成為Apache項目的一部分,Kafka是一個分布式,可劃分的,冗余備份的持久性的日志服務(wù),它主要用于處理流式數(shù)據(jù)。

消息發(fā)送失敗如何處理
就回滾,捕捉異常,把預(yù)處理的這條數(shù)據(jù)給刪除了,數(shù)據(jù)庫就沒有數(shù)據(jù)了,消費方就不會有消息執(zhí)行。雙方數(shù)據(jù)一致。
如何防止消息的重復(fù)消費?
1、對于需要保存到數(shù)據(jù)庫的數(shù)據(jù),我們可以設(shè)置某條數(shù)據(jù)的某個值,比如訂單號之類的,設(shè)置一個唯一索引,這樣的話即使重復(fù)消費也不會生效數(shù)據(jù)
2、樂觀鎖,也就是我們每次插入一條數(shù)據(jù)或者更新的時候判斷某個版本號是不是與預(yù)期一樣,如果不是,那么就不進行操作
3、使用redis進行存儲,每次操作數(shù)據(jù)的時候先去redis進行判斷,如果存在的話,那么這條數(shù)據(jù)就是重復(fù)消費的,然后我們可以丟棄或者做其他處理。
4.svn和git沖突如何解決?
pull一下,更新程序 同步 查看沖突代碼 人工修改 保持本地最新版 提交修改 再pull一下 更新 人工合并 更新到最新版? commit提交 push
5.如何測試自己的接口?
用postman swagger等工具
6.poi導(dǎo)入 excel時如果數(shù)據(jù)溢出如何解決?
可以將excel的xlsx格式轉(zhuǎn)換為易讀取的csv格式進行讀取
7. linux常用命令有哪些?
1.1 pwd命令該命令的英文解釋為print working directory(打印工作目錄)。輸入pwd命令,Linux會輸出當(dāng)前目錄。
1.2 cd命令cd命令用來改變所在目錄。
cd / 轉(zhuǎn)到根目錄中
cd ~ 轉(zhuǎn)到/home/user用戶目錄下
1.3 ls命令
ls命令用來查看目錄的內(nèi)容。
1.4 cat命令
cat命令可以用來合并文件,也可以用來在屏幕上顯示整個文件的內(nèi)容。
8.如何調(diào)用第三方的接口?
SpringBoot-RestTemplate
public User doGetWith2(String url){
? ? ? ? User user? = restTemplate.getForObject(url, User.class);
? ? ? ? return user;
? ? }
9.分布式、集群、微服務(wù)的理解?
分布式是指將不同的業(yè)務(wù)分布在不同的地方。分布式的每一個節(jié)點,都完成不同的業(yè)務(wù),一個節(jié)點垮了,那這個業(yè)務(wù)就不可訪問了。
而集群指的是將幾臺服務(wù)器集中在一起,實現(xiàn)同一業(yè)務(wù),集群,有一個組織性,一臺服務(wù)器垮了,其它的服務(wù)器可以頂上來。
微服務(wù)是一種架構(gòu)風(fēng)格,一個大型復(fù)雜軟件應(yīng)用由一個或多個微服務(wù)組成。系統(tǒng)中的各個微服務(wù)可被獨立部署,各個微服務(wù)之間是松耦合的。每個微服務(wù)僅關(guān)注于完成一件任務(wù)并很好地完成該任務(wù)。在所有情況下,每個任務(wù)代表著一個小的業(yè)務(wù)能力。
10.分布式事務(wù)的處理邏輯?怎么實現(xiàn)的?
這些小操作分布在不同服務(wù)器上,分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。
現(xiàn)在的分布式事務(wù)實現(xiàn)方案有多種,有些已經(jīng)被淘汰,如基于XA的兩段式提交、TCC解決方案,還有本地消息表、MQ事務(wù)消息,還有一些開源的事務(wù)中間件,如LCN、GTS。
11.事務(wù)的特性?分布式如何保證數(shù)據(jù)一致性?
特性:原子性,一致性,隔離性,持續(xù)性。
原子性:事物是數(shù)據(jù)庫的邏輯工作單位,事物中包括的操作要么都做,要么都不做。
一致性:事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。
隔離性:一個事務(wù)的執(zhí)行不能被其它事物干擾。即一個事物內(nèi)部的操作及使用的數(shù)據(jù)對其它并發(fā)事物是隔離的,并發(fā)執(zhí)行的各個事物之間不能互相煩擾。
持續(xù)性:也稱永久性,只一個事物一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就應(yīng)該是永久性的。接下來的其它操作或故障不應(yīng)該對其執(zhí)行結(jié)果有任何影響
分布式如何保證數(shù)據(jù)一致性
當(dāng)更新操作完成之后,任何多個后續(xù)進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。
12. docker的常用命令有哪些?
基礎(chǔ)操作:
1.docker images查看鏡像信息列表 鏡像是靜態(tài)的
2.docker ps -a查看運行中的所有容器
3.docker pull? [images]:[version]從dockerhub拉取指定鏡像
4.docker rm [containerID]刪除容器
5.docker rmi [imageID]刪除鏡像
13.模板引擎的了解和使用?
模板引擎(這里特指用于Web開發(fā)的模板引擎)是為了使用戶界面與業(yè)務(wù)數(shù)據(jù)(內(nèi)容)分離而產(chǎn)生的,它可以生成特定格式的文檔,用于網(wǎng)站的模板引擎就會生成一個標(biāo)準(zhǔn)的HTML文檔。
使用
1、導(dǎo)入文件
2、定義模板
3、準(zhǔn)備對象(需要填充的數(shù)據(jù))
4、將數(shù)據(jù)填充到模板
template(模板ID,填坑的數(shù)據(jù))
14.項目中定時任務(wù)怎么寫的?
1、實現(xiàn)了Runnable接口。run方法中,先打印一個當(dāng)前系統(tǒng)時間,然后呢,接著執(zhí)行sleep方法,休眠30秒
2、實現(xiàn)TimerTask接口。
15.如何實現(xiàn)郵箱和短信的發(fā)送?
郵箱:用163或者騰訊郵箱的smtp服務(wù) 創(chuàng)建一個第三方郵件客戶端的專用密碼
在郵箱工具類里把專用密碼 SMTP服務(wù)器的地址 和要發(fā)送的內(nèi)容 以及發(fā)送對象的郵箱地址填上即可
短信 可以用阿里云的云通信服務(wù) 在控制臺里的國內(nèi)消息中設(shè)置一個短信模板
把模板code和個人中心的accesskey填進工具類即可
16.兩個異構(gòu)項目之間的實時數(shù)據(jù)互通你會怎么做?
ESB
17. nginx的了解和使用?
nginx是一個使用c語言開發(fā)的高性能的http服務(wù)器及反向代理服務(wù)器。
反向代理方式實際上就是一臺負(fù)責(zé)轉(zhuǎn)發(fā)的代理 服務(wù)器,貌似充當(dāng)了真正服務(wù)器的功能,但實際上并不是,代理服務(wù)器只是充當(dāng)了轉(zhuǎn)發(fā)的作用,并且從真正的服務(wù)器那里取得返回的數(shù)據(jù)。
使用
下載后解壓
打開cmd命令窗口,切換到nginx解壓目錄下,輸入命令 nginx.exe 或者 start nginx ,回車即可
直接在瀏覽器地址欄輸入網(wǎng)址 http://localhost:80,回車,出現(xiàn)以下頁面說明啟動成功
nginx的配置文件是conf目錄下的nginx.conf,默認(rèn)配置的nginx監(jiān)聽的端口為80,如果80端口被占用可以修改為未被占用的端口即可
18. maven如何解決jar包沖突?
1.可以借助Maven Helper插件中的Dependency Analyzer分析沖突的jar包,然后在對應(yīng)標(biāo)紅版本的jar包上面點擊execlude,就可以將該jar包排除出去
2.手動排除?在pom.xml中使用標(biāo)簽去排除沖突的jar包
版本鎖定原則:一般用在繼承項目的父項目中
正常項目都是多模塊的項目,如moduleA和moduleB共同依賴X這個依賴的話,那么可以將X抽取出來,同時設(shè)置其版本號,這樣X依賴在升級的時候,不需要分別對moduleA和moduleB模塊中的依賴X進行升級,避免太多地方(moduleC、moduleD…)引用X依賴的時候忘記升級造成jar包沖突,這也是實際項目開發(fā)中比較常見的方法。
19.樹形結(jié)構(gòu)的表怎么設(shè)計的?
左右值算法
20.如何實現(xiàn)菜單及增刪改查的功能權(quán)限管理?
在admin登錄時,將登錄時生成的token保存到vue組件。然后查詢對應(yīng)的角色信息,根據(jù)角色id查詢role_permission表所關(guān)聯(lián)的菜單權(quán)限信息,返回給vue里面控制管理系統(tǒng)左側(cè)菜單欄導(dǎo)航的顯示
后端使用自定義注解和AOP的方式實現(xiàn)增刪改查權(quán)限的控制
21.開發(fā)程序需要哪些文檔?
可行性研究報告、需求規(guī)格說明書、項目計劃、軟件測試計劃、概要設(shè)計說明書、詳細(xì)設(shè)計說明書、編程規(guī)范、軟件測試用例、軟件測試報告、用戶手冊、安裝手冊、項目總結(jié)報告
1.ajax請求方式、參數(shù)類型、狀態(tài)碼?



2. Jquery常用的選擇器?

3.前后端是如何做數(shù)據(jù)交互的?前端怎么傳給后端json數(shù)據(jù)?
1.第一種:ajax
傳給后臺的數(shù)據(jù)通過json封裝起來,再用ajax將json傳到后臺
2、通過form表單的action傳值
一般情況下數(shù)值在傳給后臺之前需要校驗,可以在form中的onsubmit調(diào)用js方法進行校驗,當(dāng)js方法返回值為true時,觸發(fā)action,當(dāng)js方法返回值為false時,action不觸發(fā)。這樣處理的好處在于當(dāng)用戶輸入不正確時,不會刷新頁面,表單仍然會保留用戶之前的輸入
JS方法: JSON.stringfiy(demo);
4.前端和后臺都是如何解決跨域問題的?
前端
利用反向代理實現(xiàn)跨域
反向代理需要用到nginx
實現(xiàn)原理
原理大體相同,但是處理的端不同,反向代理實在服務(wù)器端進行處理。首先修改hosts文件,將域名指向開發(fā)者的電腦本身,把自己偽裝成服務(wù)端,再通過nginx對不同的請求進行轉(zhuǎn)發(fā),把靜態(tài)資源指向開發(fā)者本地電腦的資源,將接口指向?qū)嶋H的服務(wù)器。
后臺
使用cors


5.前端如何防止表單重復(fù)提交?
利用Session防止表單重復(fù)提交(推薦)
實現(xiàn)原理:
服務(wù)器返回表單頁面時,會先生成一個subToken保存于session,并把該subToenk傳給表單頁面。當(dāng)表單提交時會帶上subToken,服務(wù)器攔截器Interceptor會攔截該請求,攔截器判斷session保存的subToken和表單提交subToken是否一致。若不一致或session的subToken為空或表單未攜帶subToken則不通過。
首次提交表單時session的subToken與表單攜帶的subToken一致走正常流程,然后攔截器內(nèi)會刪除session保存的subToken。當(dāng)再次提交表單時由于session的subToken為空則不通過。從而實現(xiàn)了防止表單重復(fù)提交。
6.Vue的生命周期?vue的指令?vue的雙向綁定如何實現(xiàn)?vue如何實現(xiàn)自定義事件?vue如何實現(xiàn)監(jiān)聽?vue如何實現(xiàn)請求?vue的路由跳轉(zhuǎn)方式?
生命周期:從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程,我們稱這是Vue的生命周期。通俗說就是Vue實例從創(chuàng)建到銷毀的過程,就是生命周期。
vue的指令:
v-text
v-text主要用來更新textContent,可以等同于JS的text屬性。
v-if
v-if可以實現(xiàn)條件渲染,Vue會根據(jù)表達(dá)式的值的真假條件來渲染元素。
v-for
用v-for指令根據(jù)遍歷數(shù)組來進行渲染
v-bind
v-bind用來動態(tài)的綁定一個或者多個特性。
3 vue的雙向綁定如何實現(xiàn)?
1 數(shù)據(jù)雙向綁定(v-model)配合vue中的data
vue如何實現(xiàn)自定義事件
使用 $on(eventName) 監(jiān)聽事件
使用 $emit(eventName) 觸發(fā)事件
vue如何實現(xiàn)監(jiān)聽?
$watch
vue如何實現(xiàn)請求
axios
vue的路由跳轉(zhuǎn)方式
router-link標(biāo)簽
ps : 區(qū)別
this.$router.push
跳轉(zhuǎn)到指定url路徑,并想history棧中添加一個記錄,點擊后退會返回到上一個頁面
this.$router.replace
跳轉(zhuǎn)到指定url路徑,但是history棧中不會有記錄,點擊返回會跳轉(zhuǎn)到上上個頁面 (就是直接替換了當(dāng)前頁面)
this.$router.go(n)
向前或者向后跳轉(zhuǎn)n個頁面,n可為正整數(shù)或負(fù)整數(shù)
7.get和post有什么區(qū)別?
1. Get是不安全的,因為在傳輸過程,數(shù)據(jù)被放在請求的URL中;Post的所有操作對用戶來說都是不可見的。
? 2. Get傳送的數(shù)據(jù)量較小,這主要是因為受URL長度限制;Post傳送的數(shù)據(jù)量較大,一般被默認(rèn)為不受限制。
? 3. Get限制Form表單的數(shù)據(jù)集的值必須為ASCII字符;而Post支持整個ISO10646字符集。
? 4. Get執(zhí)行效率卻比Post方法好。Get是form提交的默認(rèn)方法。
8. jquery如何獲取當(dāng)前日期?
var myDate = new Date();? ? ? ? ? ?
var year=myDate.getFullYear();? ? ? ? //獲取當(dāng)前年
var month=myDate.getMonth()+1;? //獲取當(dāng)前月
var date=myDate.getDate();? ? ? ? ? ? //獲取當(dāng)前日
var h=myDate.getHours();? ? ? ? ? ? ? //獲取當(dāng)前小時數(shù)(0-23)
var m=myDate.getMinutes();? ? ? ? ? //獲取當(dāng)前分鐘數(shù)(0-59)
var s=myDate.getSeconds();? ? ? ? //獲取當(dāng)前秒
var now=year+'-'+getNow(month)+"-"+getNow(date)+" "+getNow(h)+':'+getNow(m)+":"+getNow(s);
9.如何給畫面中所有的 checkbox標(biāo)簽添加一個事件?
var?x = document.getElementByTagName("checkbox").
var?i;
for?(i =?0; i < x.length; i++) {
x[i].onclick
}
10. jquery怎么打開一個模態(tài)窗口?
SimpleModal是一個輕量級的jQuery插件,它提供了一個強大的界面模態(tài)對話框發(fā)展。
SimpleModal提供2個簡單的方法來調(diào)用一個模式對話框。
(1)作為一個串連的jQuery函數(shù),你可以調(diào)用一個jQuery元素modal()函數(shù)使用該元素的內(nèi)容將顯示一個模式對話框。
$("#element-id").modal();
(2)作為一個獨立的功能,可以通過一個jQuery對象,一個DOM元素,或者一個普通的字符串(可以包含HTML)創(chuàng)建一個模態(tài)對話框。
$("#element-id").modal({options});
$.modal("<div><h1>SimpleModal</h1></div>", {options});
11.表單驗證是如何實現(xiàn)的?
用document獲取輸入框的value可以判斷是否為空或者是否為數(shù)字
其他類型的校驗 比如手機號 郵箱之類的可以用正則表達(dá)式校驗
12. readonly和 disable有什么區(qū)別?
readonly并沒有對input[type="button"]產(chǎn)生作用,按鈕效果仍然在,并沒有“不可用”;
而disabled直接對input[type="button"]的按鈕效果產(chǎn)生作用,導(dǎo)致按鈕不可點擊。
disabled屬性可以作用于所有的表單元素。
readonly只對可以輸入的表單元素有效
13.如何畫一個表格?如何合并單元格?
在<table></table>的標(biāo)簽內(nèi)只要有幾行就要寫幾個<tr></tr>,而<tr></tr>內(nèi)又包含著<td></td>。
在th或者td中設(shè)置rowspan屬性,用于合并兩行的同一列單元格
14.如何獲取一個文本框的內(nèi)容?
var textbox= document.getElementById("textbox");
var text = textbox.value;
15. Jquery如何獲取form表單的值?
把form表單的值序列化成一個Json對象,如{username:admin,password:123}
var?params?=?$('#searchForm').serializeObject();
把form表單的值序列化成一個字符串,如username=admin&password=admin
var?params?=?$('#searchForm').serialize();
將字符串轉(zhuǎn)換為Json對象
JSON.parse(str)
16.前端如何延時調(diào)用一個函數(shù)?
WindowsetTimeout()方法
jQuerydelay()方法
17.如何取出樹形結(jié)構(gòu)的數(shù)據(jù)?前端如何顯示樹形結(jié)構(gòu)數(shù)據(jù)?
首先先遍歷所有的節(jié)點數(shù)據(jù),生成id 和parent_id的關(guān)系,然后遍歷id 和parent_id的關(guān)系,因此將子節(jié)點數(shù)據(jù)放入children 這個集合當(dāng)中。
通過js遍歷數(shù)據(jù)對象,拼接成dom字符串,插入到html中
18.js中的this在各種情況下的指向?
情況1:如果一個函數(shù)中有this,但是它沒有被上一級的對象所調(diào)用,那么this指向的就是window,這里需要說明的是在js的嚴(yán)格版中this指向的不是window,但是我們這里不探討嚴(yán)格版的問題,你想了解可以自行上網(wǎng)查找。
情況2:如果一個函數(shù)中有this,這個函數(shù)有被上一級的對象所調(diào)用,那么this指向的就是上一級的對象。
情況3:如果一個函數(shù)中有this,這個函數(shù)中包含多個對象,盡管這個函數(shù)是被最外層的對象所調(diào)用,this指向的也只是它上一級的對象
19.如何將數(shù)據(jù)保存到前端?
雖然cookie可以存儲一些數(shù)據(jù),但是仍然存儲下面一些缺點
?。?)cookie需要在客戶端和服務(wù)器端之間來回傳送,會浪費不必要的資源
(2)cookie的存儲大小有限制,對于每個域,一般只能設(shè)置20個cookie,每個cookie大小不能超過4KB
?。?)cookie的安全性,cookie因為保存在客戶端中,其中包含的任何數(shù)據(jù)都可以被他人訪問,cookie安全性比較低
Web存儲機制
接下來,我們要說一下html5中的存儲啦,主要是sessionStorage和localStrorage
由于sessionStorage對象是Storage的一個實例,所以存儲數(shù)據(jù)時可以使用setItem()或者直接設(shè)置新的屬性來存儲數(shù)據(jù)
當(dāng)我們要獲取某個數(shù)據(jù)的時候,可以使用getItem來獲取數(shù)據(jù)
于localStorage也是Storage的實例,可以像使用sessionStorage一樣來使用它
20.如何實時刷新頁面?
頁面自動刷新:把如下代碼加入<head>區(qū)域中
<meta http-equiv="refresh" content="5">
21.什么是http協(xié)議無狀態(tài)協(xié)議?怎么解決http協(xié)議無狀態(tài)協(xié)議?
HTTP無狀態(tài)協(xié)議是指協(xié)議對于事務(wù)處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面,在服務(wù)器不需要先前信息時它的應(yīng)答就較快。
1、通過Cookies保存狀態(tài)信息
通過Cookies,服務(wù)器就可以清楚的知道請求2和請求1來自同一個客戶端。

2、通過Session保存狀態(tài)信息
Session機制是一種服務(wù)器端的機制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)(也可能就是使用散列表)來保存信息。
當(dāng) 程序需要為某個客戶端的請求創(chuàng)建一個session的時候,服務(wù)器首先檢查這個客戶端的請求里是否已包含了一個session標(biāo)識 - 稱為 session id,如果已包含一個session id則說明以前已經(jīng)為此客戶端創(chuàng)建過session,服務(wù)器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端創(chuàng)建一個session并且生成一個與此session相關(guān)聯(lián)的session id,session id的值應(yīng)該是一個既不會重復(fù),又不容易被找到規(guī)律以仿造的字符串,這個session id將被在本次響應(yīng)中返回給客戶端保存。
Session的實現(xiàn)方式:
1、使用Cookie來實現(xiàn)
服務(wù)器給每個Session分配一個唯一的JSESSIONID,并通過Cookie發(fā)送給客戶端。
當(dāng)客戶端發(fā)起新的請求的時候,將在Cookie頭中攜帶這個JSESSIONID。這樣服務(wù)器能夠找到這個客戶端對應(yīng)的Session。

2、使用URL回寫來實現(xiàn)
URL回寫是指服務(wù)器在發(fā)送給瀏覽器頁面的所有鏈接中都攜帶JSESSIONID的參數(shù),這樣客戶端點擊任何一個鏈接都會把JSESSIONID帶會服務(wù)器。如果直接在瀏覽器輸入服務(wù)端資源的url來請求該資源,那么Session是匹配不到的。
Tomcat 對Session的實現(xiàn),是一開始同時使用Cookie和URL回寫機制,如果發(fā)現(xiàn)客戶端支持Cookie,就繼續(xù)使用Cookie,停止使用URL回 寫。如果發(fā)現(xiàn)Cookie被禁用,就一直使用URL回寫。jsp開發(fā)處理到Session的時候,對頁面中的鏈接記得使用 response.encodeURL() 。
重寫和重載的區(qū)別
首先是重載,重載就是在同一個類當(dāng)中有多個名稱相同方法,但各個相同方法的參數(shù)列表不同(無關(guān)返回值類型)。如下,在test3中三個方法名相同的add方法,第一個是兩個int類型的書相加,第二個是三個int相加,第三個是兩個float相加,他們的參數(shù)個數(shù)不同或類型不同就構(gòu)成了重載。

重寫則發(fā)生在不同的類當(dāng)中,并且兩者要有繼承關(guān)系,重寫是方法名字和參數(shù)的列表是要完全一致的,重寫的意義在于父類的方法已經(jīng)不能滿足時,子類重寫為自己需要的。如下,在父類Test3中num方法是想做兩數(shù)的加法運算,而在子類Test4中我想做兩數(shù)的減法運算,則繼承的num方法不能滿足,則重寫為test4中的num方法進行減法運算

值傳遞和引用傳遞的區(qū)別
1、按值傳遞:值傳遞是指在調(diào)用函數(shù)時將實際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進行修改,將不會影響到實際參數(shù)。簡單來說就是直接復(fù)制了一份數(shù)據(jù)過去,因為是直接復(fù)制,所以這種方式在傳遞時如果數(shù)據(jù)量非常大的話,運行效率自然就變低了
2、按引用傳遞:引用傳遞其實就彌補了上面說的不足,如果每次傳參數(shù)的時候都復(fù)制一份的話,如果這個參數(shù)占用的內(nèi)存空間太大的話,運行效率會很底下,所以引用傳遞就是直接把內(nèi)存地址傳過去,也就是說引用傳遞時,操作的其實都是源數(shù)據(jù)