Java面試題集(五)
三、開源框架
什麽是mybaties?
Mybaties是支持普通sql查詢,存儲過程和高級映射的優秀持久層框架。Mybaties消除了幾乎所有的jdbc代碼和參數的手工設置以及結果集的檢索。Mybaties使用簡單的xml或註解用於配置和原始映射,將接口和Java的pojos(Plan Old Java Objects 普通的Java對象)映射成數據庫中的記錄。
Mybaties的動態sql語句是基於ognl表達式的,可以方便的在sql語句中實現某些邏輯,總體來說mybaties動態sql語句主要有以下幾類:
1:if語句(簡單的條件判斷)
2:choose(when otherwise),相當於Java語言中的switch與jstl中的choose很類似。
3:trim(where,set,對包含的內容加上prexif或者suffix等,前綴後綴)
4:where(主要是用來簡化sql語句中where條件判斷,能只能的處理and ,or,不必擔心多余導致語法報錯)
5:set(主要用於更新操作)
6:foreach 主要用在構建in條件中,它可以在sql語句中進行叠代一個集合。Foreach元素的屬性主要有item,index,collector,open,separator,close.
Item表示集合中每一個元素進行叠代時的別名;
Index指定一個名字,用於表示在叠代過程中,每次叠代到的位置;
Open表示該語句以什麽開始;
Separator表示在每次進行叠代之間以什麽符號作為分隔符;
Close表示該語句以什麽結束。
註意:collector 若是list則為list,若為數組則為array,默認為map
Mybaties與hibernate的區別?
相對於hibernate的O/R而言,mybaties是一種“sql mapping”的ORM實現。
Hibernate對數據庫結構提供了較為完整的封裝,hibernate的o/r mapping實現了pojo和數據庫之間的映射,以及sql的自動生成和執行。程序員往往只需定義好pojo到數據庫表的映射關系,即可通過hibernate提供的辦法完成持久層操作。程序員甚至不需要對sql熟練掌握,hibernate會根據制定的存儲邏輯,自動生成對應的sql並調用jdbc接口加以執行。
而mybaties著力點則在於pojo與sql之間的映射關系。也就是說mybaties並不會為程序員在運行期間自動執行生成sql執行,具體的sql語句需要程序員自己寫,然後通過映射配置文件,將sql所需的參數以及返回的結果字段映射到指定pojo。
Hibernate是一個全自動的orm映射工具,它可以自動生成sql語句,而mybatis 需要我們自己在xml配置文件中寫sql語句,hibernate要比ibatis功能負責和強大很多。因為hibernate自動生成sql語句,我們 無法控制該語句,我們就無法去寫特定的高效率的sql。對於一些不太復雜的sql查詢,hibernate可以很好幫我們完成,但是對於特別復雜的查 詢,hibernate就很難適應了,這時候用mybatis就是不錯的選擇,因為mybatis還是由我們自己寫sql語句。
springMVC工作原理(重點)
在整個springMVC框架中,dispatcherServlet處於核心位置,負責協調和組織不同組件以完成請求處理並返回響應工作
1.客戶端發送一個請求匹配dispatcherServlet的請求映射路徑(web.xml),web容器將該請求轉交給dispatcherServlet處理。
2.dispatcherServlet接收到請求後,將請求信息(包括url,http,請求頭,請求參數,cook等)以及HandlerMapping的配置找到處理請求的處理器Handler
3.dispatcherServlet根據HandlerMapping得到對應請求的Handler後,通過HandlerAdapter對Handler進行封裝,再以統一的適配器接口調用Handler。
4.處理器完成業務邏輯的處理後將返回一個ModelAndView給dispatcherServlet,ModelAndView包含視圖邏輯名和模型數據信息。
5.dispatcherServlet借助ViewResoler完成邏輯視圖名到真實視圖對象的解析。
6.得到真實視圖對象後,dispatcherServlet使用這個view對ModelAndView中的模型數據進行視圖渲染。
SpringMVC註解
[email protected](value="url請求地址")寫在類的上面,表示該類的url請求地址
[email protected](value="請求路徑",method={RequestMethod.GET})寫在方法的上面,方法的路徑。
[email protected] 綁定單個請求數據,可以是url中的數據,表單提交的數據或者上傳的文件。
[email protected] 用來返回數據給客戶端。例如:
@ResponseBody
@RequestMapping(value = "/getGoodsByType", method = RequestMethod.POST)
public ResultModel<Goods> getGoodsByType(@RequestParam int typeId) {
return “modelresult”
}
[email protected] 用來處理Content-type不是application/x-www-form-urlencoded編碼的內容,例如application/json ,application/xml等。
[email protected] 綁定url模板變量值,@PathVariable(value="id")Integer id這裏value值必須和請求參數一致。
[email protected] 綁定數據到Model
[email protected] 綁定數據到session
[email protected] 綁定multipart/data數據,並可以根據類型進行對象轉換。
[email protected] 綁定請求頭數據
[email protected] 綁定Cookie數據
Springmvc常用標簽?
首先在jsp頁面引入springmvc標簽標識符
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
form標簽:<form:form modelAttribute=”contentModel” method=”post”>
input標簽:<form:input path=”username”>
password標簽:<form:password path=”password”>
checkbox標簽:
<form:checkbox path=”selectArray” value=${contentModel.testArray}>
SpringMVC與Struts2比較(重點)
1.springmvc是方法級別的攔截,攔截到方法後根據參數上的註解,把request數據註入進去,一個方法對應一個request上下文,而方法同時又跟一個url對應,而struts2是類級別的攔截,每次來了請求就創建一個Action,然後調用setter getter方法把request中的數據註入,struts2中一個Action對象對應一個request上下文,struts2中action一個方法對應一個url,但是其類的屬性被所有方法所共享。
2.springmvc的方法之間基本上獨立的,獨享request response數據,請求數據通過參數獲取,方法之間不共享變量。而struts2雖然方法之間也是獨立的,但其所有Action變量是共享的,這不會影響程序運行,卻給我們編碼讀程序時帶來麻煩。
3.springmvc的驗證也是一個亮點,支持JSR303,處理ajax的請求更是方便只需一個註解@ResponseBody然後直接返回響應文本即可,如下:
@RequestMapping(value=“/whitelists”) public String index(ModelMap map) { Account account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId()); List groupList = groupManager.findAllGroup(account.getId()); map.put(“account”, account); map.put(“groupList”, groupList); return “/group/group-index”; } // @ResponseBody ajax響應,處理Ajax請求也很方便
Spring最核心的2點:IOC和AOP(重點)
Spring是一個輕量級的控制反轉和面向切面的容器框架。
IOC(控制反轉也稱為 DI依賴註入):一個對象依賴的其對象通過被動的方式傳遞進來,而不是這個對象自己創建或者查找依賴對象,spring容器初始化時就將依賴傳遞給對象。
IOC(控制反轉):獲得依賴對象被反轉,即獲得依賴對象的過程由自身管理變為由IOC容器主動註入。依賴註入就是由IOC容器在運行期間,動態地將某種依賴關系註入到對象中。
一個對象依賴的其他對象通過被動的方式傳遞過來,而不是這個對象自己創建或者查找依賴對象,容器在對象初始化時不等對象請求就主動將依賴傳遞給它。
AOP:面向方面編程。能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任,例持久化管理,事務管理、日誌管理、權限控制,調試管理等封裝起來,便於減少系統的重復代碼,降低模塊間的耦合度,提高開發和調試效率
Spring的目的就是讓對象與對象之間的關系沒有通過代碼來關聯,都是通過配置類說明管理的(spring根據配置,內部通過反射去動態組裝對象)。
項目中如何體現spring的AOP和IOC的?
項目中體現AOP:
主要是橫切一個關註點,將一個關註點模塊化成一個切面,在切面上聲明一個通知(Advice)和切入點。通知中定義了要插入的方法,切入點內容是一個表達式,以描述需要在哪些對象的哪些方法上插入通知定義的方法。
項目中用到的spring中的切面編程最多的地方是聲明式事務管理。
1.定義一個事務管理
2.配置事務特性(相當於聲明通知,一般在業務層的類的一些方法上定義事務)
3.配置哪些類的哪些方法需要配置事務(相當於切入點,一般在業務類的方法上)
例如:
1.註解方式配置事務
@AspectJ風格的切面可以通過@Compenent註解標識其為Spring管理Bean,而@Aspect註解不能被Spring自動識別並註冊為Bean,
必須通過@Component註解來完成,如下:
@Component @Aspect public class TestAspect { @Pointcut(value="execution(* *(..))") private void pointcut() {} @Before(value="pointcut()") public void before() { System.out.println("=======before"); } }
2.攔截方式配置事務(在spring-hibernate.xml中配置)
Spring的聲明式事務配置:
首先配置sessionfactory
<bean id=”sessionFactory” class=”org.springframework.orm.hibernate4.LocalSessionFactoryBean”>
<property name=”configLocation”>
<value>/WEB/INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
然後配置事務管理器
<bean id=”transactionManager” class=”org.springframework.orm.hibernate4.HibernateTransactionManager”>
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
配置事務特征
-
<tx:advice id=”txAdvice” transaction-manager=”transactionManager”> <tx:attributes> <tx:method:nametx:method:name=”add.*” progagation=”REQUIRED”> <tx:method:nametx:method:name=”update.*” progagation=”SUPPORTS”> <tx:method name="delete*" rollback-for="Exception" /> </tx:attributes> </tx:advice>
配置哪些類的哪些方法配置事務
<aop:config> <aop:pointcut id=”transactionPoitcut”expression=”execution(*.com.ftsc.service.impl.*.*(..))”/> <aop:advisor advice-ref=”txAdvice”pointcut-ref=”transactiomPointcut”> </aop:config>
Spring的傳播機制:progagation定義了7個事務傳播機制。
REQUIRED:如果存在一個事務,則支持當前事務。如果沒有事務則開啟一個新的事務
SUPPORTS:如果存在一個事務,支持當前事務。如果沒有事務,則非事務的執行,但是對於事務同步的事務管理器,supports與不使用有少許不同。
REQUIRES_NEW:總是開啟一個新的事務如果一個事務已經存在,則將當前事務掛起
NOT_SUPPORTED:總是非事務執行,並掛起任務存在的事務
NEVER:總是非事務的執行,如果存在一個活動事務,則拋出異常
NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中,如果沒有活動事務,則按
TransactionDefinition.PROPAGATION_REQUIRED屬性執行
註:嵌套事務一個非常的概念及時內層事務依賴於外層事務。外層事務失敗時,會回滾內層事務所做的動作。而內層事務操作失敗並不會引起外層事務的回滾。
項目中體現IOC:
例如spring整合struts,讓spring的IOC容器管理struts2的action
首先在web.xml中引入struts配置文件如struts的過濾器,spring的配置文件如:
<context-parm> <param-name>contextConfigLocation</param-name> <param-name>classpath:applicationContext.xml</param-name> </context-parm>
啟動IOC容器的listener:
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
spring整合struts的插件struts-spring-plugin,該插件包的作用是:覆蓋struts的objectFactory來增強核心框架對象的創建,當創建一個對象的時候,它會用struts配置文件的class屬性去和spring配置文件中的id屬性進行關聯,如果能找到,則由spring創建,否則由struts框架自身創建,然後由spring來裝配
接著在spring的配置文件中配置struts的action實例,(註意需要配置scope屬性為prototype,因為struts的action是單例,這是為了解決線程安全問題。)在struts配置文件中配置action,但其class屬性不再指向該action的實現類,而是指向spring容器中action實例的ID
Spring依賴註入方式?
spring註入有3中方法:屬性名稱,setter方法,構造方法
開發中主要使用spring的什麽技術?
1.IOC容器管理各層組件
2.使用aop配置事務
3.整合其他框架
Spring註解?
@Component:通用註解,可用於任何bean
@Repository:通常用於註解dao類,即持久層
@Service:通常用於註解service類,即服務層。
@Controller:通常用於controller類,即控制層(MVC)
在聲明action時,需要指定為多例,解決線程安全問題。
Spring過濾器和攔截器區別?
Spring的攔截器與servlet的filter有相似之處,比如二者都是AOP編程思想的體現,都能實現權限檢查,日誌記錄等。
區別:
1.使用範圍不同:filter是servlet規範規定的,只能用於web程序中,而攔截器既可以用於web程序,也可以用於application,swing程序中;
2.規範不同:filter是在servlet規範中定義的,是servlet容器支持的,而攔截器是在spring容器內的,是spring框架支持的;
3.使用資源不同:同其他的代碼塊一樣,攔截器也是一個spring的組件,歸spring管理,配置在spring文件中,因此能使用spring裏的任何資源,對象。例如service對象,數據源,事務管理等,通過ioc註入到攔截器即可,而過濾器則不能;
4.深度不同:filter只在servlet前後起作用,而攔截器能夠深入到方法前後,異常拋出前後等,因此攔截器的使用具有更大的彈性,所以在spring框架的程序中,要優先使用攔截器。
案例:在web.xml中使用filter如字符集編碼
Struts2工作原理?
1.客戶端發送一個請求給strtusPrepareAndExecueFilter(在web.xml中),
2.strutsPrepareAndExecuteFilter詢問ActionMapper:該請求是否是一個strtus2的請求,
3.若actionMapper認為該請求是一個strtus請求,則strutsPrepareAndExecuteFilter把請求的處理交給actionProxy,
4.ActionProxy通過ConfigurationManager詢問框架的配置文件,確定需要調用action類及action方法,
5.actionProxy創建一個actionInvocation的實例,並進行初始化,
6.actionInvocation實例在調用action過程前後,涉及到相關攔截器(Intercepter)的調用,
7.Action執行完畢,actionInvocation負責根據strtus.xml找到對應的返回結果。調用結果的execute方法,渲染結果,在渲染的過程中可以使用strtus2框架的標簽,
8.執行各個攔截器invocation.invoke()之後的代碼
9.把結果發送給客戶端
Struts2:註意在頁面中展示的數據,都一視同仁的成為字符串在頁面上展現出來。
Struts2常用標簽?
首先在jsp頁面中引入strtus2標簽庫<%@taglib prefix=”s”uri=”/struts-tags”>
1.往action傳值:<input name=”userName” type=”text” >
2.顯示標簽property用於輸出指定值:<s:property value=”userName”>
3.用於從頁面往action中(user)的對象傳值:
<s:text name=”user.userName”id=”userName”>
4.叠代<s:iterator>用於將list,Map,ArrayList等集合數據循環遍歷
<s:iterator id=”user”status=”u”value=”userList”>
<s:property value=”userName”>
</s:iterator>
5.Set標簽用於將某個值放入指定範圍內如application,session
<s:set name=”user”value=”userName” scope=”request”>
El表達式:如
<s:set name=”name” value=”<%=request.getParamter(“name”)%>”/>
攔截器和過濾器的區別?
1.過濾器依賴於servlet容器,而攔截器不依賴於servlet容器。
2.Struts2攔截器只能對action請求起作用,而過濾器則對所有請求起作用。
3.攔截器可以訪問action的上下文,值棧裏的對象,而過濾器不能。
4.在action的生命周期中,攔截器可以調用多次,而過濾器只能在容器初始化時被調用一次。
談談你對MVC的理解?
MVC即Model-View-Controller的縮寫
Model:表示業務數據和業務處理,相當於Javabean,一個模型為多個視圖提供數據
View:用戶看到並與之交互的頁面,向用戶顯示相關數據,並接受用戶的輸入,如jsp
Controller:接受用戶請求並調用相應模型去處理請求,然後根據處理的結果調用相應的視圖來顯示處理的結果如servlet,struts2
MVC處理過程:首先控制器接受用戶的請求,並決定應該調用哪個模型來進行處理;然後根據用戶請求進行相應的業務邏輯處理,並返回數據;最後控制器調用相應的視圖格式化返回的數據,並通過視圖呈現給用戶。
Action 是單例還是多例?為什麽?
Action是單例,當多個用戶訪問一個請求時候,服務器內存中只有一個與之對應的 action類對象。因為當服務器第一次加載struts的配置文件時,創建一個action後,每發送一個請求,服務器都會去檢索相應的範圍是否存在這 樣一個action實例,如果存在,則使用這個實例,否則創建一個action實例。
Hibernate的緩存機制:一級緩存session緩存和二級緩存sessionfactory緩存?
hibernate:一個基於元數據的輕量級(占用資源少,沒有浸入性)orm(對象關系數據庫映射)框架。
Session是一級緩存,它是屬於事務範圍的緩存,由Hibernate管理,無需進行幹預。
SessionFactory是二級緩存,它是屬於進程範圍或群集範圍的緩存,可以進行配置和更改.
一級緩存又叫session緩存,輕量級的,創建和銷毀不需要消耗太多資源,但是它是線程不安全的,要避免多個線程共享一個session實例。我們框架使用的get,load,save,update,delete等都支持一級緩存的。
二級緩存又叫sessionfactory緩存,重量級的,創建和銷毀需要消耗太多資源,它是線程安全的,一個實例可以被應用的多個線程共享。
需要在配置文件中啟用二級緩存
<!--啟用二級緩存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
緩存的操作數據原理:
查詢數據時,會首先從一級緩存中取數據,如果取上,則直接使用,否則到二級緩存中取,如果取到則直接使用,否則,就會發送語句查詢數據庫。這樣利用一級和二級緩存會提高訪問效率。
lazy(Hibernate的延遲加載功能):表示查詢當前對象或關聯對象數據時,不真正訪問數據庫,當使用對象非主鍵屬性時,才真正發送查詢語句,訪問數據庫。
Hibernate工作原理?
1.讀取並解析配置文件
2.讀取並解析映射信息,創建sessionfantory
3.打開session
4.創建事務transaction
5.持久化操作
6.提交事務
7.關閉session
8.關閉sessionfactory
Hibernate的核心接口有5個:session,sessionFactory,transaction,query,configuration?
Session接口:負責進行被持久化對象的crud操作。Session是一級緩存,輕量級的,線程不安全的。
SessionFactory接口:負責初始化Hibernate,它充當數據存儲源的代理,並負責創建session對象,這裏用到工廠模式,sessionFactory是二級緩存,重量級的。
Configuration接口:負責配置並啟動Hibernate,創建sessionFactory對象。在Hibernate啟動過程中,configuration類的實例首先定義映射文件位置,讀取配置,然後創建sessionFactory對象。
Transact接口:負責相關事務相關的操作。
Query和criteria接口:負責各種數據庫查詢,用sql或者hql語句表達方式。
Hibernate中Java對象的狀態有哪些?
1.臨時態(transient)不處於session緩存中。Oid為null或等於id的unsaved-value屬性值
2.持久態(persistent)加入session緩存中
3.遊離態(detached)已經被持久化,但不再處於session的緩存中
Session的清理和清空有什麽區別?
清理緩存調用的是session.flush()方法,而清空調用的是session.clean()方法。
Session清理緩存是指按照緩存中對象的狀態變化來同步更新數據庫,但不清空緩存。而清空則是把session的緩存置空,不同步更新到數據庫。
Hibernate的load()方法與get()方法的區別?
Get加載數據不支持延遲加載,若沒有oid對象則返回的是null,而load加載數據支持延遲加載,返回的是一個代理對象
Hibernate優缺點?
優點:
1.對JDBC訪問數據庫的代碼做了封裝,簡化了數據訪問層繁瑣的重復性代碼
2.映射的靈活性, 它支持各種關系數據庫,從一對一到多對多的各種復雜關系.
3.非侵入性、移植性會好
4.緩存機制: 提供一級緩存和二級緩存。
缺點:
1.無法對 SQL 進行優化
2.框架中使用 ORM 原則, 導致配置過於復雜
3.執行效率和原生的JDBC相比偏差: 特別是在批量數據處理的時候
4.不支持批量修改、刪除
Hibernate的openSessionView問題?
用於解決懶加載異常問題,主要功能就是把hibernate session和一個請求的線程綁定在一起,直到頁面完整輸出,這樣就可以保證頁面讀取數據的時候session一直處於開啟狀態,如果去獲取延遲加載對象也不會報錯。
註意配置filter要放在strtus2過濾器的前面,因為它要頁面顯示完後再退出。
Hibernate的getCurrentSession()和openSession()的區別?
1.getCurrentSession()它會先檢查當前線程中是否綁定了session如果有則直接返回,沒有再創建,而openSession()則是直接new一個新的session並返回。
2.使用ThreadLocal來實現線程session的隔離。
3.getCurrentSession()在事務提交的時候會自動關閉session,而openSession()要手動關閉。
項目中為什麽使用SSH?
1.使用struts2是因為struts2是基於MVC設計模式,很好的將應用程序進行分層,使開發者更關註業務邏輯實現,其次struts有豐富的taglib,靈活運用,大大提高開發效率。
2.使用hibernate是因為它是基於orm模式的輕量級框架。
3.使用spring是因為基於IOC和AOP架構多層j2ee框架,采用IOC使得很容易實現bean的裝配,采用AOP實現事務管理。
Hibernate的update()和saveOrUpdate()的區別?
Update()和saveOrUpdate()是用來對跨session的po進行狀態管理的。
Update()方法操作的對象必須是持久化的對象,如果此對象在數據庫中不存在的話,就不能使用update()方法。
saveOrUpdate()方法操作的對象即可以是持久化的,也可以是未持久化的對象,如果該對象是已經持久化的則調用該方法會更新數據庫對象,如果該對象是未持久化的則調用該方法會save到數據庫。
什麽是hibernate的並發機制?怎麽去處理並發問題?
Hibernate的並發機制:1.hibernate的session對象是非線程安全的,對於單個請求,單個會話,單個工作單元,它通常只使用一次然後就丟棄。如果一個session實例會話允許共享的話,那些支持並發運行的,例如http request,session bean將會導致出現資源爭用。如果在http session中hibernate的session話,就可能出現同步訪問http session,只要用戶足夠快點擊瀏覽器的“刷新”。2.多個事務並發訪問同一塊資源,可能會引發第一類丟失更新,臟讀,幻讀,不可重復讀,第二類丟失更新一系列的問題。
解決方案:
1.設置事務隔離級別
Serializable串行化。隔離級別最高
Repeatable read:可重復讀
Read committed:已提交數據讀
Read uncommitted:未提交數據讀。隔離級別最差
設置鎖:樂觀鎖和悲觀鎖。
樂觀鎖:使用版本號或者時間戳檢測更新丟失,在<class>映射中設置optimistic-lock=“all”可以在沒有版本或者時間戳屬性映射的情況下實現版本檢查,此時hibernate將比較一行記錄的每個字段的狀態行。
悲觀鎖:hibernate總是使用數據庫的鎖定機制,從不在內存中鎖定對象,只要為jdbc連接指定一下隔離級別,然後讓數據庫去搞定一切就夠了。類LockMode定義了hibernate所需的不同的鎖定級別:
LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ
Java面試題集(五)