Open rainit2006 opened 7 years ago
■参照サイト
Struct是一个web层的mvc框架(jsp, actionForm). 但是有了Spring MVC后基本上就不用Struct了。 Hibernate是一个ORM,处于持久层 Spring是一个容器框架。用于配置bean,并维护bean之间关系。Spring中有一个非常重要的概念:bean,是java的每一个对象(javabean/actions/service/数据源/dao) IOC: 控制反转 Inverse of Control。 DI (Dependency Injection): 依赖注入。
Sping横跨了Web层,业务层,DAO层,持久层。可以控制各个层的组件(bean),并维护各个组件之间的关系。
快速入门步骤:
3。在 ApplicationContext.xml 文件里配置bean。指定bean的id(相当于程序运行时创建的实例名称),路径,class,属性(Property。属性是一个class时可以引用在ApplicationContext.xml 文件里已声明的id。即“bean的引用”)。 Spring在加载时会自动创建这些bean对象,并放入内存(相当于一个HashMap或HashTable存储这些bean对象)。 对应的说,bean里必须实现这些Property的set方法。 4。在Main函数里调用
ApplicationContext ac=new ClassPathXmlApplicationContext(""); //默认路径是在src目录下。
UserService us = (UserService) ac.getBean("Bean的id");
us.sayHello(); //可以打印出ApplicationContext.xml 文件里配置的名称了。这个叫“属性注入”
可以看出: (1) 没有new对象了,交给spring处理了 (2)上述代码里没有调用Name属性的set方法,但是仍然可以输出Name属性值。
IOC: 控制反转 Inverse of Control。即把创建bean对象和维护bean对象关系的权利(控制权利)从程序中转移到Spring里(ApplicationContext.xml). 传统的代码里,创建bean对象和维护bean对象关系是在程序代码里实现的。
DI (Dependency Injection): 依赖注入。
本质上,IOC和DI是同一个概念。Spring的设计者认为DI更能表达Spring的特性。
达到“解耦”
Spring开发提倡接口編程。
InterfaceClass us = (InterfaceClass) ac.getBean("Bean的id");
それで、Interfaceを継承するクラスはApplicationContext.xmlで切り替える(プログラムコードは変更不要)ことが可能になる。
ApplicationContext.xml中のBeanの取得方法: 1. BeanFactory
ApplicationContext容器: 如果bean是singleton,则ApplicationContext.xml里的Bean会被自动创建。默认是singleton。 如果声明是prototypes类型,则不会自动创建。 (Bean的作用域: singleton,prototypes, request, session, global session ) 缺点:耗内存
BeanFactory容器:
BeanFactory factory = new XmlBeanFactory(new ClassResource("com/hsp/ioc/beans.xml"));
factory.getBean("bean的id");
仅仅实例化容器时,bean不会被创建。只有当使用getBean取得某个class对象时,才会被创建。 缺点:速度慢
实际上大多数项目工程里使用ApplicationContext方式,毕竟内存因素影响很小(价格便宜)。
ApplicationContext容器使用方法,有下面三种形式: 1,ClassPathXmlApplicationContext:从类路径中加载
官方文档: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc
Spring2.5引入注解式处理器 @Controller:用于标识是处理器类; @RequestMapping:请求到处理器功能方法的映射规则; @RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定; @ModelAttribute:请求参数到命令对象的绑定; @SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中; @InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;
Spring3.0引入RESTful架构风格支持(通过@PathVariable注解和一些其他特性支持),且又引入了更多的注解支持 @CookieValue:cookie数据到处理器功能处理方法的方法参数上的绑定; @RequestHeader:请求头(header)数据到处理器功能处理方法的方法参数上的绑定;@RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换);@ResponseBody:处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换); @ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和原因; @ExceptionHandler:注解式声明异常处理器; @PathVariable:请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定
■@ModelAttribute http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation @ModelAttribute can be used either as a method parameter or at the method level.
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
In the example, we show a method that adds an attribute named msg to all models defined in the controller class.
In general, Spring-MVC will always make a call first to that method, before it calls any request handler methods. That is, @ModelAttribute methods are invoked before the controller methods annotated with @RequestMapping are invoked. The logic behind the sequence is that, the model object has to be created before any processing starts inside the controller methods.
.2 As a Method Argument When used as a method argument, it indicates the argument should be retrieved from the model.
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
// Code that uses the employee object
return "employeeView";
}
The employee model attribute is populated with data from a form submitted to the addEmployee endpoint. Spring MVC does this behind the scenes before invoking the submit method:
◆ Form Example
Spring Bean的生命周期 http://www.cnblogs.com/zrtqsk/p/3735273.html
Bean装配 http://www.jianshu.com/p/f64dcfb534cc Spring容器提供了两种配置Bean的方式,其一是使用XML文件作为配置文件,其二是基于Java注解的配置方式。
<bean id="sonnet29" class="com.springinaction.springidol.Sonnet29"></bean>
<bean id="poeticDuke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<constructor-arg ref="sonnet29" />
</bean>
可以为Bean定义初始化和销毁操作,只需使用init-method和destroy-method参数来配置
<bean id="auditorium" class="com.springinaction.springidol.Auditorium"
init-method="turnOnLights" destroy-method="turnOffLights" />
注入内部Bean
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist">
<property name="song" value="Happy" />
<property name="instrument">
<bean class="com.springinaction.springidol.Saxophone" />
</property>
</bean>
集合元素 用途
AOP 面向切面(方面)编程,是对所有对象或者是一类对象编程。 核心是两个字: 不(在不增加代码的基础上,还增加功能),还()
场景: 共同的功能(切面)比如:事务,日志,安全
概念: 切面(aspect),连接点(joinpoint),通知(advice),切入点(pointcut),连接点,引入
aop编程在框架本身用的很多。
通知(advice):实现共通的类。 一共有5种通知 :Around(拦截目标方法),Before(在目标方法前调用),After,Throws,引入通知(自定义切入点)
代理对象(ProxyFactoryBeans 类):代理接口,完成代理任务。 (织入) 该对象只需配置,不要编写代码。 用到了动态代理技术。
■AOP实现的一个例子1: 事先准备下面的类,实现了MethodBeforeAdvice接口(前置增强):
定义接口
TestServiceInterface{ sayHell();}
TestServiceInterface2{ sayBey();}
在Beans.xml里配置:
1. 被代理的对象
<bean id = "test1Service" class="Test1Service"></bean>
2. 配置前置通知
<bean id="" class="MyMethodBeforeAdvice"> 该class继承MethodBeforeAdvice接口
3. 代理对象
<bean id= "proxyFactoryBean" class="proxyFactoryBean">
-- 代理接口集
<property name="ProxyInterfaces">
<list>
<value>com.hanshunping.aop.TestServiceInterface</value>
<value>com.hanshunping.aop.TestServiceInterface2</value> //支持代理多个接口
</list>
//////////////
当程序运行时,Spring内部肯定会创建一个proxyFactoryBean implement TestServiceInterface,TestServiceInterface2。来实现list里列举的接口。
/////////////
</property>
-- 通知织入到代理对象。可以把通知看成拦截器。structs2核心也有拦截器
<property name="interceptorNames">
<value>MyMethodBeforeAdvice</value>
</property>
--- 配置被代理对象
<property name ="target" ref="test1Service"></property>
<bean> //--- 对应3.里的<bean>
在App代码里
TestServiceInterface ts = (TestServiceInterface) ac.getBean("proxyFactoryBean"); //注意这里要get代理对象。
ts.syaHello();
((TestServiceInterface2)ts).sayBye(); //此时因为调用的是代理对象,所以前置通知会被注入,结果是MyMethodBeforeAdvice里的函数会被自动调用。
例2 首先我们得有一个所谓的切面类(Aspect):Transaction,我们想达到的目的就是在一个某个业务类的(切入点)execute方法调用之前,执行Transaction.beginTx()方法,在调用之后,需要执行Transaction.commitTx()方法。 当然,想描述这些规则, xml依然是不二之选: 注意:现在Transaction这个类和业务类在源代码层次上没有一点关系,完全隔离了。
■AOP实现的一个例子2:@AspectJ配置切面 先用@AspectJ定义一个切面:
package test.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class PreAspect {
@Before("execution(* shout(..))")//意思是返回值任意 参数任意
public void beforeShout()
{
System.out.println("准备叫");
}
}
在applicationContext.xml中设置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" ★
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">★
<!--基于@AspectJ切面的驱动器-->
<aop:aspectj-autoproxy/>
<bean class="test.aop.PreAspect" />
<bean class="test.aop.ChinaDog" id="chinaDog"/>
在AopTest.java中进行测试
public static void main(String[] args)
{
ApplicationContext ac = new FileSystemXmlApplicationContext("web/WEB-INF/applicationContext.xml");
Dog dog = (Dog)ac.getBean("chinaDog"); //注意这里调用的是chinaDog
dog.shout("jim"); //在shout方法调用前会调用PreAspect类的beforeShout方法。
dog.sleep("tom");
}
■AOP实现的一个例子3:使用Spring来定义纯粹的POJO切面 使用spring的aop标签
<!-- POJO -->
<bean class="test.aop.PreAspect" id="preAspect" />
<bean class="test.aop.ChinaDog" id="chinaDog"/>
<aop:config>
<aop:aspect ref="preAspect">
<aop:before method="beforeShout" pointcut="execution(* *.shout(..))"/>
</aop:aspect>
</aop:config>
JAVAコード
public static void main(String[] args)
{
ApplicationContext ac = new FileSystemXmlApplicationContext("web/WEB-INF/applicationContext.xml");
Dog dog = (Dog)ac.getBean("chinaDog");//注意这里调用的是chinaDog
dog.shout("jim");
dog.sleep("tom");
}
SSH (Spring + Struct + Hibernate) 创建一个雇员薪资系统 薪资系统架构: 界面 --<接口 EmployeeServiceInterface>-- 业务操作层 ---- 持久层(hibernate) ---- 数据库
创建手顺: 1,先搞定spring:创建一个新Project 2,引入spring开发包。拷贝到reference lib下。 3,编写 applicationContext.xml (or Beans.xml)文件,并放在 src目录下。 4,测试一下spring是否ok 5,加入Hibernate开发包 6,Hibernate里面的核心要被spring接管 (1) 在 beans.xml里配置数据源(dataSource):driverClassName, url(数据库地址), username(数据库访问名称), password, inintialSize(连接池启动时的初始值), maxActive(连接池得最大值), maxIdle(最大空闲值), minIdle(最小空闲值) (2)配置sessionFactory对象:dataSource,mappingResources(Hiberate里的对象映射。本例里指定下面第8步创建的“Employee.hbm.xml”文件),hibernateProperties。
<hibernate-mapping>
<class name="Employee" table="employee">
<id name="id" type="java.lang.Interger">
<generator class="native" />
</id>
<property name="email" type="java.lang.String">
<column name="email" length="64">
</property>
<property name="hiredate" type="java.util.Date">
<column name="hiredate" >
</property>
<property name="name" type="java.lang.String">
<column name="name" length="64">
</property>
<property name="salary" type="java.lang.Float">
<column name="salary">
</property>
</class>
</hibernate>
9, 测试spring和hibernate是否可以结合使用 10,创建web层和业务层之间的接口(EmployeeServiceInter),声明方法:addEmployee, showEmployee, updateEmployee, delEmployee.
创建EmployeeService来实现上述接口。 而且在addEmployee等函数里都涉及到session操作,这些session操作可以通过AOP事务管理来实现。
11,在beans.xml里配置EmployeeService对象
14, 整合struts (1)引入struts的安装包 (2) 创建jsp页面, actionForm类 (3)创建struts-config.xml ,放在WEB-INF目录下
(4) 让 spring管理structs(action控件) 在struct-config.xml文件理添加下面代码,这样当action发生时(例:login.do -> web服务器),ActionServlet(总司令)会通过spring找对应的action的配置。
<controller>
<set-property property="processorClass" value="org.springframework.web.struts.DelegationRequestProcessor">
</controller>
在beans.xml里配置action路径
SpringMVC
Spring MVC快速入门教程 https://www.tianmaying.com/tutorial/spring-mvc-quickstart
Spring MVC概要
■SpringMVC详细运行流程图
■フォルダ・ファイル構成
■DispatcherServlet Spring Web 模型-视图-控制(MVC)框架是围绕 DispatcherServlet 设计的,DispatcherServlet 用来处理所有的 HTTP 请求和响应。Spring Web MVC DispatcherServlet 的请求处理的工作流程如下图所示:
下面是对应于 DispatcherServlet 传入 HTTP 请求的事件序列:
你需要映射你想让 DispatcherServlet 处理的请求,通过使用在 web.xml 文件中的一个 URL 映射。
■org.springframework.web.servlet.DispatcherServlet について 普通のWEBアプリケーションではServletを作成しますが、Spring Web MVCでは作成せず、Springが用意してくれている org.springframework.web.servlet.DispatcherServletを使用します。
DispatcherServletがクライアントからの要求を受け付けて、コントローラクラス(@Controller)に割り振って、コントローラクラス からの戻りからビュー(jsp)を割り振ってクライアントに戻して・・・などSpring MVCの全体コントロールを行いますが、ソースや 設定ファイル上で登場するのは、このweb.xmlだけです。
■POM.xml 在pom.xml中自定义变量及其使用 背景: 类似于版本号,可能一个组件中的多个jar包都是采用同一版本号,当要升级组件时就需要逐一修改组件中每个jar的版本号,比较繁琐而且容易漏掉,我们可以自定义一个版本号变量,然后组件中的jar包统一调用这个变量即可。
在
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.version>9.3.14.v20161028</jetty.version>
<spring.version>4.1.3.RELEASE</spring.version>
<solr.version>6.3.0</solr.version>
</properties>
变量的调用:
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solr.version}</version>
</dependency>
■Web.xml Sample
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>springMVC</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
最初に org.springframework.web.context.ContextLoaderListener クラスをリスナー登録しています。 これが登録されていることにより、Spring設定ファイル(/WEB-INF/applicationContext.xml)を読みに行きます。 このパスやファイル名称はcontextConfigLocationで変更することが出来ます。
サーブレットの設定は、次の通り。
<servlet>
<servlet-name>[プロジェクト名]</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>[プロジェクト名]</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
如果遇到匹配*.htm的URL,会使用org.springframework.web.servlet.DispatcherServlet来处理。
■/WEB-INF/spring/app.xmlに変更
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Spring設定ファイルはサーブレット毎に設定出来ます。設定する場合は init-param 内の contextConfigLocation で設定します。
■サーブレットに/WEB-INF/spring/mvc-servlet.xmlに適用
<servlet>
<!-- 配置DispatcherServlet -->
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定spring mvc配置文件位置 不指定使用默认情况 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-servlet.xml</param-value>
</init-param>
<!-- 设置启动顺序 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- ServLet 匹配映射 -->
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>*.zxh</url-pattern>
</servlet-mapping>
○需要搞清楚classpath是什么,以及classpath:和classpath有何区别: 首先 classpath是指 WEB-INF文件夹下的classes目录 classpath 和 classpath 区别: classpath:只会到你的class路径中查找找文件; classpath:不仅包含class路径,还包括jar文件中(class路径)进行查找.
■Filter サーブレット・フィルタを使用して、Webアプリケーション・リクエストの前処理やサーバー・レスポンスの後処理を実行できます。
下図は左側が、リクエスト対象のサーブレットに対してフィルタが構成されていない例を示しています。右側の例では、複数のフィルタ(1、2、...、N)が構成されています。
各フィルタは、javax.servlet.FilterインタフェースとdoFilter()メソッドを実装します。
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
フィルタ・チェーンは、javax.servlet.FilterChainインタフェースを実装するクラス(サーブレット・コンテナによって提供されます)のインスタンスです。
フィルタ・チェーンは、フィルタの順序を反映します。サーブレット・コンテナは、web.xmlファイルにおける構成順序に基づいて、マップされるフィルタを持つすべてのサーブレットまたはその他のリソースのフィルタ・チェーンを構成します。フィルタ・チェーンに含まれる各フィルタについては、フィルタに渡されるフィルタ・チェーン・オブジェクトが、順番にコールされる残りのフィルタを表します(これらのフィルタの後にターゲット・サーブレットが起動されます)。
FilterChainインタフェースも、doFilter()メソッドを指定します。
void doFilter(ServletRequest request, ServletResponse response)
<filter>
<filter-name>timer</filter-name>
<filter-class>filter.TimerFilter</filter-class>
<init-param> //初期化パラメータ
<param-name>name</param-name>
<param-value>value</param-value>
<init-param>
</filter>
ApplicationContext.xmlファイルの記述方法 <beanの取得方法> XMLで記述したbeanは、getBean()で簡単に取得できます。
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("c:/test/context.xml");
DataSource ds = (DataSource)context.getBean("dataSource");
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost/sample?useUnicode=true&characterEncoding=utf-8" />
<property name="maxActive" value="10" />
<property name="username" value="XXX" />
<property name="password" value="XXX" />
</bean>
<bean id="memberDao" class="my.MemberDao" >
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
<beanタグ、propertyタグについて> beanタグは属性をいくつか持っています。destroy-method属性は、DIコンテナが終了するときに実行されるメソッドで、記述されたメソッド(上記ではclose())が実行されます。 beanタグは、propertyタグを持つことができます。 俗に言うJavaクラスのsetterに当たるもので、上記は例えば以下のような動作と全く同じになります。
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost/sample?useUnicode=true&characterEncoding=utf-8");
dataSource.setMaxActive(10);
:
!!引数の型が違うことにも注目してください。!! Springの設定ファイルには文字列、数字の違いが表れていません。3つとも""で括られているだけです。 では、どうやって文字列に変換する、数字に変換する、といった判断をしているのでしょうか? それは、Springが指定のクラスのsetterの型を見て、自動で変換しているのです。 ですのでSpringが知らない型があると当然変換できません。自作の変換クラスを作成して設定することもできますが、通常はサンプルのmemberDaoのようにします。 ref という属性が使用されています。 ref はDIコンテナ内に設定された他のbeanを参照するためのものです。(もちろん参照先のdataSourceというbeanはXMLに記述しなければなりません)
<beanタグのidについて> idは、Spring設定ファイル内で一意でなくてはなりません。
■beanの生成パターン(singleton, prototypeなど)
■beanの生成タイミング(lazy-init)
<bean id="member" class="my.Member" lazy-init="true" />
■bean設定の引継ぎ(abstract) 実は、beanのプロパティなどを上書きすることができます。 ですので、同じような設定をする場合、親beanを指定すれば、記述の省略ができます。
<!-- 引継ぎ元(親) -->
<bean id="memAbstarct" class="my.MemberDao" abstract="true" >
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 単純に引き継いだ例。dataSourceが引き継がれています -->
<bean id="memberDao1" parent="memAbstarct" >
<property name="switch" value="1"/>
</bean>
■beanの設定のオーバーライド(上書き) XML内から他のファイルをimportすることができます。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
">
<import resource="classpath:my/spring/base-context.xml"/>
</beans>
importで指定したファイル内に同じidが存在すれば、importしたファイルのbeanが上書きされます。
■コンストラクタの指定(constructor-arg) 1.引数の数と型で指定する方法
<bean class="com.my.MyClass">
<constructor-arg index="0" value="あいう" />
<constructor-arg index="1" value="12" />
</bean>
2.引数の名前で指定する方法 【ApplicationContextファイル】
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateanswer" value="42"/>
</bean>
コード中
@ConstructorProperties({"years", "ultimateAnswer"})
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
ーーーーーーーーーーーーー
tx:annotation-driven と mvc:annotation-driven
其含义就是支持注解,一般根据前缀 tx、mvc 等也能很直白的理解出来分别的作用。
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.
Hibernate
JDBC http://wiki.jikexueyuan.com/project/hibernate/orm-overview.html JDBC 代表 Java Database Connectivity ,它是提供了一组 Java API 来访问关系数据库的 Java 程序。这些 Java APIs 可以使 Java 应用程序执行 SQL 语句,能够与任何符合 SQL 规范的数据库进行交互。 JDBC 提供了一个灵活的框架来编写操作数据库的独立的应用程序,该程序能够运行在不同的平台上且不需修改,能够与不同的 DBMS 进行交互。
ORM ORM 表示 Object-Relational Mapping (ORM),是一个方便在关系数据库和类似于 Java, C# 等面向对象的编程语言中转换数据的技术。
Hibernate Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象。 Hibernate 优势
Hibernate架构 更详细些:
配置对象:配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。
SessionFactory 对象:配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。
Session 对象:一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。
Transaction 对象:一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。
Query 对象:Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。
Criteria 对象:Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。
持久化类 在 Hibernate 中,其对象或实例将会被存储在数据库表单中的 Java 类被称为持久化类。若该类遵循一些简单的规则或者被大家所熟知的 Plain Old Java Object (POJO) 编程模型,Hibernate 将会处于其最佳运行状态。 以下所列就是持久化类的主要规则,然而,在这些规则中,没有一条是硬性要求。
映射文件 一个对象/关系型映射一般定义在 XML 文件中。映射文件指示 Hibernate 如何将已经定义的类或类组与数据库中的表对应起来。 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
</class>
</hibernate-mapping>
需要以格式
映射类型 Java类型和 Table类型之间的 映射关系 http://wiki.jikexueyuan.com/project/hibernate/mapping-types.html
Spring Security允许我们在定义URL访问或方法访问所应有的权限时使用Spring EL表达式,在定义所需的访问权限时如果对应的表达式返回结果为true则表示拥有对应的权限,反之则无。
<security:http use-expressions="true">
<security:form-login/>
<security:logout/>
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>
在上述配置中我们定义了只有拥有ROLE_USER角色的用户才能访问系统。
2.通过表达式控制方法权限
2.1使用@PreAuthorize和@PostAuthorize进行访问控制
@PreAuthorize可以用来控制一个方法是否能够被调用。
` @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')") `
/**
限制只能查询Id小于10的用户 */ @PreAuthorize("#id<10") public User find(int id) { System.out.println("find user by id........." + id); return null; }
/**
限制只能查询自己的信息 */ @PreAuthorize("principal.username.equals(#username)") public User find(String username) { System.out.println("find user by username......" + username); return null; }
/**
}
有时候可能你会想在方法调用完之后进行权限检查,这种情况比较少,但是如果你有的话,Spring Security也为我们提供了支持,通过@PostAuthorize可以达到这一效果。
@PostAuthorize("returnObject.id%2==0") public User find(int id) { User user = new User(); user.setId(id); return user; }
上面这一段代码表示将在方法find()调用完成后进行权限检查,如果返回值的id是偶数则表示校验通过,否则表示校验失败,将抛出AccessDeniedException。 需要注意的是@PostAuthorize是在方法调用完成后进行权限检查,它不能控制方法是否能被调用,只能在方法调用完成后检查权限决定是否要抛出AccessDeniedException。
2.2使用@PreFilter和@PostFilter进行过滤
使用@PreFilter和@PostFilter可以对集合类型的参数或返回值进行过滤。使用@PreFilter和@PostFilter时,Spring Security将移除使对应表达式的结果为false的元素。
@PostFilter("filterObject.id%2==0")
public List
上述代码表示将对返回结果中id不为偶数的user进行移除。filterObject是使用@PreFilter和@PostFilter时的一个内置表达式,表示集合中的当前对象。
当@PreFilter标注的方法拥有多个集合类型的参数时,需要通过@PreFilter的filterTarget属性指定当前@PreFilter是针对哪个参数进行过滤的。如下面代码就通过filterTarget指定了当前@PreFilter是用来过滤参数ids的。
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List
3 使用hasPermission表达式
http://elim.iteye.com/blog/2247073
http://www.codeceo.com/article/spring-transactions.html http://www.cnblogs.com/xiohao/p/4808088.html @Transactional注解管理事务 ■什么是“事务”? 事务是一组操作的原子执行,其中任何一笔操作失败将导致全部操作撤销。 事务遵循ACID原则。 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。
■对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 1,获取连接 Connection con = DriverManager.getConnection() 2,开启事务con.setAutoCommit(true/false); 3,执行CRUD 4,提交事务/回滚事务 con.commit() / con.rollback(); 5,关闭连接 conn.close(); 使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。
■Spring 事务的传播属性 就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。
PROPAGATION_REQUIRED : 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。 PROPAGATION_REQUIRES_NEW :新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作。 などなど
■数据库隔离级别 脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。 不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。 幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。
总结: 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。 大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle 少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB
■Spring中的隔离级别
■Spring 事务管理分为编码式和声明式的两种方式。 编程式事务指的是通过编码方式实现事务; 声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。
■ 使用@Transactional 注解管理事务的实现步骤分为两步。第一步,在 xml 配置文件中添加如清单 1 的事务配置信息。除了用配置文件的方式,@EnableTransactionManagement 注解也可以启用事务管理功能。这里以简单的 DataSourceTransactionManager 为例。
清单 1. 在 xml 配置中的事务配置信息
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
或者
<!-- 事务管理器配置,单数据源事务 -->
<bean id="pkgouTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="pkGouDataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="pkgouTransactionManager" />
第二步,将@Transactional 注解添加到合适的方法上,并设置合适的属性信息。 比如在使用事务的方法或者类上添加 @Transactional(“pkgouTransactionManager”)注解。
Spring的注解 @Service用于标注业务层组件(我们通常定义的service层就用这个) @Controller用于标注控制层组件(如struts中的action) @Repository用于标注数据访问组件,即DAO组件 @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
这几个注解是当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX; 这几个是基于类的,我们可以定义名称,也可以不定义,不定义会默认以类名为bean的名称(类首字母小写)。
下面这4个BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解。
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
如果你想使用@Autowired注解,那么就必须事先在 Spring 容器中声明
AutowiredAnnotationBeanPostProcessor Bean。传统声明方式如下
<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/>
于是spring给我们提供
@Required:应用于 bean 属性的 setter 方法。 @Autowired :apply to bean property setter methods, non-setter methods, constructor and properties。 @Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier 使用;
不使用@Autowired的话:
public class Boss
{
private Car car;
private Office office;
★这里有Car和Officce的setter 代码★
@Override
public String toString()
{
return "car:" + car + "/n" + "office:" + office;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="boss" class="Boss">
<property name="car" ref="car"/> //★需要声明car和office的property★
<property name="office" ref="office" />
</bean>
<bean id="office" class="Office">
<property name="officeNo" value="002"/>
</bean>
<bean id="car" class="Car" scope="singleton">
<property name="brand" value="红旗CA72"/>
<property name="price" value="2000"/>
</bean>
</beans>
使用@Autowired的话可以消除消除set方法:
import org.springframework.beans.factory.annotation.Autowired;
public class Boss
{
@Autowired
private Car car;
@Autowired
private Office office;
}
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<!-- 移除 boss Bean 的属性注入配置的信息 -->
<bean id="boss" class="Boss"/>
<bean id="office" class="Office">
<property name="officeNo" value="001"/>
</bean>
<bean id="car" class="Car" scope="singleton">
<property name="brand" value="红旗 CA72"/>
<property name="price" value="2000"/>
</bean>
</beans>
@Autowired默认是按照byType进行注入的,但是当byType方式找到了多个符合的bean,又是怎么处理的?Autowired默认先按byType,如果发现找到多个bean,则又按照byName方式比对,如果还有多个,则报出异常。
Spring MVC ■参照サイト: http://www.jianshu.com/p/21b143ad235b
■DataSource 在Spring框架中有如下3种获得DataSource对象的方法: 1.从JNDI获得DataSource. 2.从第三方的连接池获得DataSource. 3.使用DriverManagerDataSource获得DataSource. 一、从JNDI获得DataSource
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jcptDataSourceJNDI</value>
</property>
</bean>
ここのjcptDataSourceJNDI是tomcat或者其他应用服务器配置的JNDI.
二,从第三方的连接池获得DataSource 三种数据库连接池的配置,使用这些连接池可以获得一个数据源。 1、spring自带的JDBC连接池; 2、c3p0; 3、dbcp;
1,spring自带的JDBC方式 spring提供了对JDBC的支持,且提供了基于JDBC的数据源的配置,如下配置文件
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
2、c3p0 c3p0是一个开源的数据库连接池,可以很好的管理数据连接,如下配置
<bean id="dataSourceC3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
3、dbcp dbcp同样是一个开源的数据连接池,如下配置,
<bean id="dataSourceDbcp" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
JNDI 図 1. JNDI アーキテクチャー
■Java使用JNDI配置WEB项目数据源
一般对于普通的项目,习惯上使用.properties的文件来配置数据源的一些信息。在.properties文件中配置数据源连接字符串、用户名、密码和驱动的类,然后在代码中读取配置文件的信息再通过DriverManager.getConnection(url, username, password)的方式获取数据源连接对象。
1、获取数据源的连接对象Connection public static Connection getConnection(String jndi) { 。。。。。。。。 //如果数据源的名称不为空的话使用指定的数据源的名称来获取数据库连接对象 if(StringUtils.isNotEmpty(jndi)) { datasource = (DataSource) envContext.lookup(jndi); } else { datasource = (DataSource) envContext.lookup("sqlserver/default"); } connection = datasource.getConnection(); 。。。。 } 2、在Tomcat中的webapp中加入Resource配置
<Resource name="sqlserver/default"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="sa"
password="*"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;databasename=DBNAME"/>
常见配置属性描述: name:JDBC数据源的名称 auth:认证方式,一般设置为Container,还有一种是Application type:当前配置资源的类别 factory:数据源工厂,默认为”org.apache.commons.dbcp.BasicDataSourceFactory” driverClassName:驱动的全路径类名 maxActive:当前数据源支持的最大并发数 maxIdle:连接池中保留最大数目的闲置连接数 maxWait:当连接池中无连接时的最大等待毫秒数,在等当前设置时间过后还无连接则抛出异常 username:访问数据库的用户名 password:访问数据库的密码 url:JDBC驱动的连接字符串 validationQuery:在返回应用之前,用于校验当前连接是否有效的SQL语句,如果指定了,当前查询语句至少要返回一条记录,可以写成select top 1 * from sysobjects
3、在Tomcat的lib目录下面添加数据库的驱动文件 MySQL:mysql-connector-java-5.1.20-bin.jar SQLServer:sqljdbc4.jar Oracle:ojdbc14.jar
4、在Spring项目的web.xml加入如下配置
<resource-ref>
<res-ref-name>sqlserver/default</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
注:属于可选配置,如果在web.xml中加入了上面的配置,则需要在Tomcat中一定要配置对应的Resource,否则会报错。 5、使用方式
Connection conn = getConnection("sqlserver/default");
...
■Bean Validation Spring MVCでは、Bean Validation (JSR-303)をサポートしており、アノテーションベースな入力チェックを、簡単に 実装することができる。例として、エコーアプリケーションで名前の入力チェックを行う。 例1
import javax.validation.constraints.NotNull; ★
import javax.validation.constraints.Size; ★
public class EchoForm implements Serializable {
private static final long serialVersionUID = 2557725707095364446L;
@NotNull // ★@NotNull アノテーションをつけることで、HTTPリクエスト中に name パラメータがあることを確認する。
@Size(min = 1, max = 5) // ★@Size(min = 1, max = 5) をつけることで、name のサイズが、1以上5以下であることを確認する。
private String name;
例2
import javax.validation.Valid;★
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; ★
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("echo")
public class EchoController {
@ModelAttribute
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}
@RequestMapping
public String index(Model model) {
return "echo/index";
}
@RequestMapping("hello")
public String hello(@Valid EchoForm form, BindingResult result, Model model) { // ★
if (result.hasErrors()) { // ★
return "echo/index";
}
model.addAttribute("name", form.getName());
return "echo/hello";
}
}
コントローラー側には、Validation対象の引数に @Valid アノテーションを付加し、 BindingResult オブジェクトを引数に追加する。 Bean Validationによる入力チェックは、自動で行われる。結果は、 BindingResult オブジェクトに渡される。 hasErrors メソッドを実行して、エラーがあるかどうかを確認できる。
■Hibernateのvalidation http://tech.pjin.jp/blog/2016/06/14/springframework9/
http://blog.sina.com.cn/s/blog_6d3c1ec601014h1h.html Spring mvc视图机制 Spring的控制器Controller会返回一个ModelAndView的实例。Spring根据ModelAndView实例中的View和Model把信息反馈给用户。Spring中的视图是以名字为标识的,ViewResolver是通过名字来解析view的。Spring提供了多种视图和视图解析器。
ModelAndView 它代表了Spring Web MVC中呈现画面时所使用的Model与View,由于Java一次只能返回一个物件,所以ModelAndView的作用封装这两个物件,以方便您一次返回Model与View这两个物件。 ModelAndView(String viewName):最简单的ModelAndView是只有View的名称。
ModelAndView(String viewName, Map model) 如果您要返回呈现画面时所需的Model资料,则可以使用Map来收集呈现View时所需的资料,然后在建构ModelAndView作为建构时的参数。
ModelAndView(String viewName, String modelName, Object modelObject) 返回单个model时使用。
-- 学视频教程 https://www.youtube.com/watch?v=8QA5F0fk6aE
Spring MVC 4 + Hibernate 5 integration example https://www.boraji.com/spring-4-mvc-hibernate-5-integration-example