scala-springmvc-hibernate
scala上使用springmvc、hibernate與在java上使用相同,內存數據庫,jsp前端
mvc:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
viewResolver做爲視圖解析器
採用的攔截器
<mvc:annotation-driven/>
<mvc:interceptors>
<ref bean="openSessionInViewInterceptor"/>
</mvc:interceptors>
<bean id="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
說明一下Open Session in View的做用,就是容許在每次的整個request的過程當中使用同一個hibernate session,能夠在這個request任什麼時候期lazy loading數據。
若是是singleSession=false的話,就不會在每次的整個request的過程當中使用同一個hibernate session,而是每一個數據訪問都會產生各自的seesion,等於沒有Open Session in View.
OpenSessionInViewFilter默認是不會對session 進行flush的,而且flush mode 是 never
spring的OpenSessionInViewFilter過濾器,主要是爲了實現Hibernate的延遲加載功能,基於一個請求一個hibernate session的原則。
盡 管Open Session In View看起來還不錯,其實反作用很多。看回上面OpenSessionInViewFilter的doFilterInternal方法代碼,這個方法其實是被父類的doFilter調用的,所以,咱們能夠大約瞭解的OpenSessionInViewFilter調用流程:
request(請求)->open session並開始transaction->controller->View(Jsp)->結束transaction並 close session.
一切看起來很正確,尤爲是在本地開發測試的時候沒出現問題,但試想下若是流程中的某一步被阻塞的話,那在這期間connection就一直被佔用而不釋放。最有可能被阻塞的就是在寫Jsp這步,一方面多是頁面內容大,response.write的時間長,另外一方面多是網速慢,服務器與用戶間傳輸時間久。當大量這樣的狀況出現時,就有鏈接池鏈接不足,形成頁面假死現象。
ModelAndView詳解
ModelAndView(View view)
ModelAndView(View view, Map model)
ModelAndView(View view, String modelName, Object modelObject)
ModelAndView類別就如其名稱所示,是表明了MVC Web程序中Model與View的對象,不過它只是方便您一次返回這兩個對象的holder,Model與View二者還是分離的概念。
最簡單的ModelAndView是持有View的名稱返回,以後View名稱被view resolver,也就是實做org.springframework.web.servlet.View接口的實例解析,例如 InternalResourceView或JstlView等等:
ModelAndView(String viewName)
若是您要返回Model對象,則可使用Map來收集這些Model對象,而後設定給ModelAndView,使用下面這個版本的ModelAndView:
ModelAndView(String viewName, Map model)
Map對象中設定好key與value值,以後能夠在視圖中取出,若是您只是要返回一個Model對象,則可使用下面這個ModelAndView版本:
ModelAndView(String viewName, String modelName, Object modelObject)
藉由modelName,您能夠在視圖中取出Model並顯示。
ModelAndView類別提供實做View接口的對象來做View的參數:
ModelAndView(View view)
ModelAndView(View view, Map model)
ModelAndView(View view, String modelName, Object modelObject)
一個例子是org.springframework.web.servlet.view.RedirectView,ModelAndView預設是使 用forward來轉發請求結果至視圖,使用RedirectView的話,則會使用redirect將請求重導至視圖,例如:
…
public ModelAndView handleRequest(....) … {
....
return new ModelAndView(new RedirectView(this.getViewPage()));
}
....
在這邊,viewPage的地址是從服務器網頁根目錄開始指定,而不是Web應用程序的根目錄,因此您的getViewPage()傳回的地址必須像是 /springapp/pages/index.htm這樣的地址,其中springapp是您的Web應用程序目錄。
使用forward的話,網址列上並不會出現被轉發的目標地址,並且forward是在Web應用程序以內進行,能夠訪問Web應用程序的隱藏目錄,像是WEB-INF,然而forward只能在Web應用程序中進行,不能指定至其它的Web應用程序地址。
使用redirect的話,是要求客戶端瀏覽器從新發出一個指定的請求地址,所以網址列上會出現被重導的目錄地址,重導的請求是由瀏覽器發出,因此不能 訪問Web應用程序中的隱藏目錄,像是WEB-INF,然而重導是從新要求一個網頁,因此能夠指定至其它的Web應用程序地址。
DispatcherServlet會根據傳回的ModelAndView來解析View名稱,並處理給予的Model。View名稱的解析是委託給實 做org.springframework.web.servlet.ViewResolver接口的實例,ViewResolver接口定義以下:
public interface ViewResolver {
public view resolveViewName(String, Locale locale) throws ServletException;
}
ViewResolver的一個實例是InternalResourceViewResolver,名稱解析完以後,實際的View繪製與Model轉 換處理是交給實做org.springframework.web.servlet.View的實例,View接口以下:
public interface View {
public void render(Map model, HttpServletResquest resquest, HttpServletResponse response) throws ServletException, IOException;
}
View的實做以前用過org.springframework.web.servlet.view.InternalResourceView,另外也還有JstlView、TilesView、VelocityView等等的實做,分別進行不一樣的表現展處理 。
ModelAndView()
這個構造方法構造出來的ModelAndView
不能直接使用,應爲它沒有指定view,也沒有綁定對應的model對象。固然,model對象不是必須的,可是view確實必須的。
用這個構造方法構造的實例主要用來在之後往其中加view設置和model對象。
給ModelAndView
實例設置view的方法有兩
個:setViewName(String viewName) 和 setView(View view)。前者是使用view
name,後者是使用預先構造好的View對象。其中前者比較經常使用。事實上View是一個接口,而不是一個能夠構造的具體類,咱們只能經過其餘途徑來獲取
View的實例。對於view
name,它既能夠是jsp的名字,也能夠是tiles定義的名字,取決於使用的ViewNameResolver如何理解這個view name。
如何獲取View的實例之後再研究。
而對應如何給ModelAndView
實例設置model則比較複雜。有三個方法可使用:
addObject(Object modelObject)
addObject(String modelName, Object modelObject)
addAllObjects(Map modelMap)
ModelAndView
能夠接收Object類型的對象,ModelAndView
將它視爲其衆多model中的一個。當使用Object類型的對象的時候,必須指定一個名字。ModelAndView
也能夠接收沒有明顯名字的對象,緣由在於ModelAndView
將調用spring本身定義的Conventions 類的.getVariableName()方法來爲這個model生成一個名字。顯然,對model而言,名字是必須的。
Conventions.getVariableName()生成名字的規則是使用對象的類名的小寫模式來做model名字。當這個model是集合或數組的時候,使用集合的第一個元素的類名加s來做model的名字。
ModelAndView
也能夠接收Map類型的對象,ModelAndView
將這個Map中的元素視爲model,而不是把這個Map自己視爲model。可是其餘的集合類能夠用自己做爲model對象。
實際上,ModelAndView
對model的支持來自於類ModelMap,這個類繼承自HashMap。
從uri上取參數,相似rest風格:
@RequestMapping(value = Array("/customers/{customerId}"), method = Array(DELETE))
def deleteCustomer(@PathVariable customerId: Long) = {
customerRepository.delete(customerId)
"redirect:/"
}
先後臺聯交: @ModelAttribute
@RequestMapping(value = Array("/customers/{customerId}"), method = Array(POST))
def editCustomer(
@PathVariable customerId: Long,
@Valid @ModelAttribute("customerData") customerData: CustomerPageData,
bindingResult: BindingResult): ModelAndView = {
val customer = customerRepository.get(customerId)
if (bindingResult.hasErrors) {
new ModelAndView("customer/customer-edit", "customer", customer)
} else {
customerData.copyTo(customer)
customerRepository.update(customer)
new ModelAndView("redirect:/customers/{customerId}.html")
}
}
從參數中取值:
@RequestParam(required = false) edit: Stringhtml