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