注意:所有文章除特别说明外,转载请注明出处.
Spring - FD
Spring提供一种方法管理你的业务对象,主要有两个功能为我们的业务对象管理提供便捷
Spring整合Web项目的底层原理
这一过程表示在加载配置文件和创建对象过程,在服务器启动时完成。
1.在服务器启动的时候,为每个项目创建一个ServletContext对象。
2.在ServletContext对象创建时,使用监听器可以具体到ServletContext对象在什么时候创建。
3.在使用监听器监听ServletContext对象创建时。
4.加载spring配置文件,将配置文件对象创建。
5.将创建出来的对象放到ServletContext域对象里(setAttribute方法)。
6.获取对象的时候,到ServletContext域得到(getAttribute方法)。
- 1.DI 依赖注入
- 2.AOP 面向切面编程
1.Java Bean
每一个实现Bean的规范才可以由Spring来接管,而Bean的规范是:
1.必须是个公有类
2.有无参构造函数
3.用公有方法暴露内部成员属性(setter/getter) 实现了这样的规范的类才叫做JavaBean(一种可重用组件)
2.DI-依赖注入
简单来说,一个系统中可能会有成千上万个对象。如果要手工维护它们之间的关系,这是不可想象的。我们可以在Spring的XML文件描述它们之间的关系,由Spring自动来注入它们——比如A类的实例需要B类的实例作为参数set进去。
3.AOP-面向切面对象
在执行某个操作前后需要输出日志,但是如果是手工加代码会非常吃力,维护也非常艰难,所以这就需要面向切面编程
Spring框架的主要内容
1.Spring框架运行环境
核心容器(IOC):Bean(Bean工厂/创建对象)、Core(一切的基础)、Context(上下文)、SpEL(Spring的表达式语言)
AOP:AOP、Aspects
数据访问的支持:JDBC、ORM、Transaction、JMS(Java邮件服务)
Web的支持:Spring MVC
2.Ioc(Inversion of control)控制反转
这是一种设计思想,在Java开发中,Ioc意味着将你设计好的对象交给容器控制管理,不像传统的在对象内部直接控制。
解释:在传统的Java程序设计中,在对象内部通过new进行创建对象,是程序主动去创建依赖对象,Ioc专门有一个容器来创建这些对象,即由Ioc容器来控制对象的创建。Ioc容器控制了对象,主要控制了外部资源的获取。
3.DI(Dependency Injection)依赖注入
组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
解释:应用程序依赖于Ioc容器。应用程序需要Ioc容器来提供对象需要的外部资源。Ioc容器注入应用程序某个对象,应用程序依赖的对象。注入某个对象所需要的外部资源(对象、资源、常量数据)。
提示:一般项目开发的模块
注意:
DAO层、Service层、Controller层和View层详解
1.DAO层
主要做数据持久层的工作,负责与数据库进行联络的一些任务封装在此。
1)设计DAO层的接口
2)在Spring配置文件中定义此接口的实现类
3)在模块中调用此接口来进行数据业务的处理,不需要关心此接口的具体实现类是哪个类
注意:DAO层的数据源配置以及有关数据库连接的参数都在Spring的配置文件中进行配置
2.Service层
此层主要负责业务模块的逻辑应用设计
1)首先设计接口,再设计其实现类,最后再在配置文件中配置其实现的关联,从而在应用中调用service接口来进行业务处理。
2)service层的业务实现,具体要调用到已定义的DAO层的接口,封装Service层的业务逻辑有利于通用业务逻辑的独立性和重复利用性。
3.Controller层
此层负责具体的业务模块流程的控制,在此层要调用Service层的接口来控制业务流程,控制的配置也同样是在Spring的配置文件里面进行
4.View层
View层与控制层结合比较紧密,View层主要负责网页前台的JSP页面的表示
1.首先给出Ioc(控制反转)思想程序:
1.定义DAO接口UserDao
2.定义DAO接口实现类UserDaoMysqlImpl和UserDaoOracleImpl
3.定义Service层接口UserService,实现具体的业务
4.定义Service接口的实现类UserServiceImpl,Service层的业务实现,具体要调用到已定义的Dao层的接口
注意:控制反转(Ioc)的设计思想,我们不需要应用程序本身来创建对象,而是将创建对象的任务交付给Ioc容器
Spring - SD
Spring的bean管理(xml方式)
对象创建的细节:
1.对象创建的时间
1)scope="prototype"(默认值) 在用到对象时才创建 (多例 action对象)
2)scope="singleton" 在启动(容器初始化之前)就已经创建了对象,整个web应用只有一个单例(dao/service/工具类)
2.是否延迟创建
1)lazy-init="false"(默认值) 不延迟创建,即在启动时就创建
2)lazy-init="true" 延迟初始化,在用到对象的时候才创建
Bean实例化的方式
1.在Spring里面通过配置文件创建对象
2.Bean实例化三种方式实现(创建对象的几种方式)
1)使用类的无参数构造创建(重点)
<bean id="user" class="cn.itcase.ioc.User"></bean>
注意:如果类里面没有无参数构造,会出现异常,所以一般要在类里面有有参构造的前提下重写无参构造方法
2)带参构造创建
<bean id="user2" class="cn.User">
<constructor-arg index="0" type="int" value="100"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="Jack"></constructor-arg>
</bean>
3)使用静态工厂创建
创建静态方法,返回类对象
<!-- # 3.2 工厂类: 静态方法 -->
<!--
class 指定的就是工厂类型
factory-method 一定是工厂里面的“静态方法”
-->
<bean id="user" class="cn.ObjectFactory" factory-method="getStaticInstance"></bean>
4)使用实例工厂创建
创建不是静态的方法,返回类对象
<!-- 3. 工厂类创建对象 -->
<!-- # 3.1 工厂类,实例方法 -->
<!-- 先创建工厂 -->
<bean id="factory" class="cn.ObjectFactory"></bean>
<!-- 在创建user对象,用factory方的实例方法 -->
<bean id="user4" factory-bean="factory" factory-method="getInstance"></bean>
注意:
Spring管理Bean
Spring容器通常理解为BeanFactory或者ApplicationContext
在Spring的Ioc容器能够帮助我们创建对象,对象交给Spring管理之后我们不用手动去new对象
对象依赖关系
Spring常用的几种注入方式:
1.通过构造器
2.通过set方法给属性注入值(最常用)
Servlet监听器
定义:监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为 ServletContext, HttpSession 和 ServletRequest 这三个域对象。
1.监听ServletContext域对象的创建和销毁
ServletContextListener接口用于监听ServletContext对象的创建与销毁事件
创建:服务器启动针对每一个web应用创建servletcontext
销毁:服务器关闭前先关闭代表每一个web应用的servletContext
2.编写Servlet监听器
1.实现一个特定的接口,并且针对相应的动作覆盖接口中相应的方法
2.servlet监听器注册是由web容器负责,我们只需要在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动将监听器注册到事件源中
3.一个web.xml文件中可以配置多个servlet事件监听器,web服务器按照它们的web.xml文件中的注册顺序来加载和注册这些servlet监听器
3.监听HttpSession域对象创建与销毁
HttpSessionListener接口用于监听HttpSession的创建和销毁
创建:调用sessionCreated(HttpSessionEvent se)方法
销毁:sessionDestroyed (HttpSessionEvent se)方法
4.监听HttpRequest域对象创建与销毁
创建:用户的每一次访问都会创建一个request
销毁:当前访问结束,request对象就会销毁
注意:session域对象在每一次访问时被创建,而如果用户的session在30分钟内没有使用,服务器就会销毁session,在web.xml中也可以配置session的失效时间
Spring注解注入详解
1.@Resource注解
这一注解是JSR-250标准注解,推荐使用其代替Spring专有的@Autowired注解,@Resource的作用相当于@Autowired,只不过@Autowired按 byType 自动注入,而@Resource默认按 byName 自动注入罢了。
@Resource有两个比较重要的属性,分别是name与type,Spring注解的name属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType
自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
2.@Component注解
在对应的类上加上一个@Component注解就定义该类是Bean
3.@Scope注解
在使用XML定义bean的时候,有些时候需要通过bean的scope属性来定义一个bean的作用范围
Spring Ioc快速入门
1.下载Spring的开发包
2.了解Spring的目录结构 1)docs:Spring的开发文档 2)libs:Spring的开发包 3)schema:约束文档
3.创建一个项目引入jar包
4.引入Spring的配置文件
5.编写测试类
IOC:控制反转,将Bean创建反转给Spring容器
DI:依赖注入,在Spring创建这个类的过程中,将这个类的依赖的属性注入,设置属性值
提示:两者之间的关系:依赖注入不能单独存在,需要在Ioc的基础上完成操作
1.IOC底层原理
1.创建xml配置文件,配置要创建的对象类
<bean id = "userService" class = "cn.xidian.edu.*"/>
2.创建工厂类,使用dom4j解析配置文件和反射
//返回UserService对象的方法
public static UserService getService(){
// 1.使用dom4j解析xml文件
// 然后根据id值userService得到id值对应的class属性值
String classValue = "class属性值";
// 2.使用反射创建类对象
Class clazz = Class.forName(classValue);
// 创建类对象
UserService userService = clazz.newInstance();
return service;
}
Spring的工厂类
1.ApplicationContext
- ClassPathXmlApplicationContext:解析类路径下的XML
- FileSystemXmlApplicationContext:解析本地磁盘上的XML
注意:BeanFactory和ApplicationContext都是Spring中的工厂,BeanFactory是Spring的老版的工厂类(第一次调用getBean方法的时候实例化类)。ApplicationContext是Spring的新版本的工厂类(在加载核心配置文件的时候,将所有的类实例化)
Spring的Bean管理(基于XML方式)
1.Spring实例化Bean方式
1.1 无参构造方式(最常用)
<!-- 无参数构造方法方式 -->
//引入Spring的配置文件(1.引入约束 2.编写标签)
<bean id="bean1" class="cn.augmentum.spring.demo3.Bean1"></bean>
//编写测试类
public void demo1() {
// 加载核心配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");//getBean()是用来获取applicationContext.xml文件里bean的
System.out.println(bean1);
}
1.2 静态工厂实例化方式
public class Bean2Factory {
public static Bean2 getBean2(){
return new Bean2();
}
}
配置文件:
<!-- 静态工厂实例化方式 -->
<bean id="bean2" class="cn.augmentum.spring.demo3.Bean2Factory" factory-method="getBean2"/>
代码:
public void demo2() {
// 加载核心配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
System.out.println(bean2);
}
实例工厂:
public class Bean3Factory {
public Bean3 getBean3(){
System.out.println("实例工厂执行了...");
return new Bean3();
}
}
配置文件:
<!-- 实例工厂实例化方式 -->
<bean id="bean3Factory" class="cn.itcast.spring.demo3.Bean3Factory"/>
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"/>
代码:
public void demo3() {
// 加载核心配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
System.out.println(bean3);
}
Spring的Bean的常用配置
1.标签的id和name属性
id与name的区别:
id:使用xml约束中id约束,不可以出现特殊字符
name:出现特殊字符,如果使用name没有id,那么name可以作为id使用
2.上生命周期的配置
@Test
/**
* Bean的生命周期的相关配置:
* * init-method
* * destory-method :只能针对单例对象有效.必须在工厂关闭之后才会销毁对象.
*/
public void demo1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeService employeeService = (EmployeeService) applicationContext
.getBean("employeeService");
employeeService.save();
applicationContext.close();
}
3.上的作用范围的配置:
scope属性:
- singleton :单例的(默认)
- prototype :多例的
- request :WEB项目中,创建一个对象,保存到request域中
- session :WEB项目中,创建一个对象,保存到session域中
- globalsession :WEB项目中,特殊环境.分布式开发环境.如果没有分布式环境,相当于session
4.Bean的生命周期
Spring属性注入
属性注入:创建对象的时候,向类里面属性设置值,这一过程就是属性注入
1.有参构造方法的属性注入
<bean id="car" class="cn.augmentum.spring.demo6.Car">//创建类,然后在类中添加属性值
<constructor-arg name="name" value="宝马"/>
<constructor-arg name="price" value="1000000"/>
</bean>
//第一种 有参构造注入属性值(一般情况下的属性赋值方式)
public class User{
private String name;
public User(String name){
this.name=name;
}
}
User user=new User("lucy");
2.set方法的属性注入
<bean id="car2" class="cn.augmentum.spring.demo6.Car2">//1.创建car2对象
<property name="name" value="奇瑞QQ"/>//2.属性注入(对象中属性的值的设定) name属性值:类里面定义的属性名称 value属性:设置具体的值
<property name="price" value="30000"/>
</bean>
//第二种 使用set方法注入属性值(在一般情况下使用的属性赋值方式)
public class User{
private String name;
public void setName(String name){
this.name=name;
}
}
User user=new User();
user.setName("张三");
//第三种 使用接口方式注入
public interface Dao{
public void delete(String name);
}
public class DaoImpl implements Dao{
private String name;
public void delete(String name){
this.name=name;
}
}
注意:在spring框架中只支持前面两种方式
1)set方法注入(重点)
2)有参数构造注入
3.Spring的2.5支持p名称空间注入
p名称空间语法
普通属性:p:name=""
对象类型属性:p:name-ref=""
4.p名称空间的使用
1.引入p名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
2.p名称空间的注入
<bean id="car2" class="cn.augmentum.spring.demo6.Car2" p:name="长安奔奔" p:price="25000"/>
<bean id="employee" class="cn.augmentum.spring.demo6.Employee" p:name="马凤" p:car2-ref="car2"/> ref:表示引用其他bean对象
5.Spring3.0的SpEL的属性注入
SpEL语法:#{SpEL}
1.属性配置
<bean id="carInfo" class="cn.augmentum.spring.demo6.CarInfo">
</bean>
2.属性注入
<!-- SpEL的方式的属性注入 -->
<bean id="car2" class="cn.augmentum.spring.demo6.Car2">
<property name="name" value="#{carInfo.carName}"/>
<property name="price" value="#{carInfo.calculatorPrice()}"/>
</bean>
<bean id="employee" class="cn.augmentum.spring.demo6.Employee">
<property name="name" value="涛哥"/>
<property name="car2" value="#{car2}"/>
</bean>
6.Spring中数组或集合的复杂类型属性注入(在创建好类之后便要创建类的对象,此时创建对象的操作交给Spring容器,然后注入对象的属性值)
1.注入复杂属性值,首先创建类型对象
<bean id="person" class="cn.itcast.property.Person">
//2.然后在创建的对象中注入属性值
<property name="arrs">//加入的属性名称
<list>
<value>老马</value>
<value>马凤</value>
<value>马如花</value>
</list>
</property>
</bean>
<!--List集合的属性的注入:-->
<property name="list">
<list>
<value>马芙蓉</value>
<value>马大帅</value>
<value>马大彪</value>
</list>
</property>
<!--Set集合的属性的注入:-->
<property name="set">
<set>
<value>马云</value>
<value>马化腾</value>
<value>马大哈</value>
</set>
</property>
<!--Map集合的属性的注入:-->
<property name="map">
<map>
<entry key="aaa" value="刘能"/>
<entry key="bbb" value="赵四"/>
<entry key="ccc" value="王五"/>
</map>
</property>
<!--Properties的属性的注入:-->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123</prop>
</props>
</property>
7.Spring中的分配置文件进行开发
1.加载配置文件时候加载多个配置文件
2.总配置文件中引入其他配置文件
2.注入对象类型属性(重点)
1.创建service类和dao类
1)在service得到dao对象
2.具体实现过程
1)在service里面将dao作为类型属性
2)生成dao类型属性的set方法
public class UserService{
//1.定义dao类型属性
private UserDao userDao;
//2.生成set方法
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
}
3)配置文件中注入关系
1.配置service和dao对象
<bean id="userDao" class="cn.itcast.ioc.UserDao"></bean>
<bean id="userService" class="cn.itcast.ioc.UserService"></bean>
2.注入dao对象 name属性值,service类里面属性名称,现在不要写value属性,因为刚写的是字符串,现在是对象,写ref属性,dao配置bean标签中id值
<property name="userDao" ref="userDao"></property>
3.Bean标签常用属性
1)id属性:为后面查找类起的名称,id属性值名称任意命名,id属性值不能包含特殊字符,根据id值得到配置对象
2)class属性:创建对象所在的类的全路径
3)name属性:功能和id属性一样的,id属性值不能包含特殊符号,但是在name属性值里面可以包含特殊字符
4)scope属性:
- singleton :单例的(默认) 创建的实例是一个对象
- prototype :多例的 创建的实例是多个对象
- request :WEB项目中,创建一个对象,保存到request域中
- session :WEB项目中,创建一个对象,保存到session域中
- globalsession :WEB项目中,特殊环境.分布式开发环境.如果没有分布式环境,相当于session
Spring整合Web项目原理
1.加载Spring核心配置文件,根据配置创建对象
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
//1)new对象,虽然这一过程功能可以实现,但是实现效率很低
2.提高这一过程实现效率的思想:将加载配置文件和创建对象的过程在服务器启动的过程完后
3.上述思想实现原理
1)ServletContext对象
2)监听器
3)具体使用
- 在服务器启动的使用,会为每个项目创建一个ServletContext对象
- 在ServletContext对象创建的时候,使用监听器可以具体到ServletContext对象在什么时候被创建
- 使用监听器监听到ServletContext对象创建的时候
--加载Spring配置文件,将配置文件配置对象创建
--将创建出来的对象放到ServletContext域对象里面(setAttribute方法)
- 获取对象的时候,到ServletContext域之中得到(getAttribute方法)
Spring - TD
Spring的Bean管理(注解)
注解(程序里面的图书特殊标记,使用注解可以完成功能 写法:@注解名称(属性名称=属性值)) >>注解可以使用在类上面、方法上面以及属性上面
1.Spring注解开发准备
1.导入jar包
1.导入基本的jar包
2.导入aop的jar包
2.创建类、创建方法
3.创建Spring配置文件,引入约束
1.在刚开始做Ioc基本功能的时候,引入的约束是beans
2.但是在做Spring的Ioc注解开发的时候需要引入新的约束(../spring-context.xsd)
4.开启注解扫描(到包里面扫描类、方法、属性上面是否有注解)
<context:component-scan base-package="cn.itcast"></context:component-scan>
//另外一个开启扫描注解配置程序
<context:annotation-config></context:annotation-config>//这只会扫描属性上面的注解
2.注解创建对象
1.在创建对象的类上面使用注解实现
@ Component(value="user") // <bean id="user" class=""/>
public class User{
//...
}
2.创建对象有四个注解
下面三个的让标注类的用途清晰,在后续Spring版本中对其增强
@ Controller :web层
@ Service :业务层
@ Repository :持久层
@ Component 和上面的三个注解等效
3.创建对象单实例还是多实例
@ Scope(value="prototype")
3.注解注入属性
注入属性注解:
1.@Autowired
2.@Resource
1.@Autowired
创建service类,创建dao类,在service类中得到dao对象
1)使用注解创建dao类与service类的对象
@Service(value="userService")
public class UserService{
//...
}
@Component(value="userService")
public class UserService{
//...
}
2)得到dao对象(在service类里面定义dao类型属性)
- 1.定义dao类型属性,在dao属性上面使用注解完成对象注入
@Autowired(自动装配)
private UserDao userDao;
//使用注解方式的时候不需要使用set方法注入属性值
2.@Resource
name属性值写注解创建dao对象value值
@Resource(name="userDao")
private UserDao userDao;
配置文件和注解混合使用
1.创建对象操作使用配置文件方式实现
<bean id="bookService" class="cn.itcast"></bean>
2.注入属性的操作使用注解方式实现
//得到类的对象,使用注解的方式
@Resource(name="bookDao")
private BookDao bookDao;
@Resource(name="ordersDao")
private OrdersDao ordersDao;
3.多种装配Bean方式的比较
1.基于xml配置(适用于Bean来自第三方、使用其他命名空间)
bean定义:<bean id="" class=""/>
bean名称:通过id或name指定
bean属性注入:<property>或者p命名空间
生命过程/bean作用范围:init-method/destory-method 范围:scope属性
2.基于注解配置(Bean的实现类由用户自己开发)
bean定义:
@Component(@Repository)
@Service
@Controller
bean名称:@Component("person")
bean属性注入:@Autowired 按类型注入
@Qualifier 按名称注入
生命过程:
3.基于Java类配置
bean注入:在方法内部编写注入代码逻辑
扩展
log4j介绍
1.通过log4j可以看到程序运行过程中更详细的信息(加载的配置文件、日志文件)
log4j使用步骤:
1.导入log4j的jar包
2.复制log4j的配置文件,复制到src下面
log4j.propertises(配置文件)
3.设置日志的级别
log4j.rootLogger=info,stdout
1)info:看到基本的信息
2)debug:看到更详细的信息
Spring整合Web项目演示
1.演示问题
1.action调用service,service里面调用dao方式,每次访问action的时候都会加载配置文件
2.解决方案
1)在服务器启动的时候,创建对象加载配置文件
2)底层使用监听器、ServletContext对象
3.在Spring里面不需要我们自己写代码实现,框架已经帮我们封装好了
1)封装了一个监听器,只需要配置好监听器就行了
2)配置监听器之前需要导入Spring整合web项目的jar包
3)指定加载配置文件的位置
指定Spring配置文件的位置
<context-param>
<param-name>..</param-name>
<param-value>...</param-value>
</context-param>
基于aspectj的注解aop
1.使用注解方式实现aop操作
1.首先引入aop编程的相关jar包
2.然后在bean.xml文件中引入aop名称空间
3.其次在bean.xml文件中开启aop扫描<context:component-scan base-package=""></context:component-scan>
4.然后开启aop注解方式,默认是false <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
5.开始写一个切面类
1.@Component:加入IOC容器 @Aspect:指定当前类为切面类
2.在类里面指定切入点表达式,拦截那些方法,即为那些类生成代理对象(@Pointcut("execution(* com.bie.aop.UserDao.*(..))"))
注意:在类里面可以开启前置增强(@Before("pointCut()")) 开启后置增强(@After("pointCut()"))
6.在写好切面类之后写执行目标对象方法(接口/接口实现类)以及最后的测试类
注意:如果目标对象是有实现接口,spring会自动选择”jdk代理(动态代理)”动态代理标识:
class com.sun.proxy.$Proxy10
如果对象没有实现接口,spring会自动调用”cglib代理”
1)创建对象
<bean id="book" class="cn.itcast.aop.Book"></bean>//创建Book对象,被增强类
<bean id="MyBook" class="cn.itcast.aop.MyBook"></bean>//创建增强类MyBook对象
2)在Spring核心配置文件中开启aop操作
<aop:aspectj-autoproxy> </aop:aspectj-autoproxy>
3)在增强类上面使用注解方式来完成增强配置
@Aspect
public class MyBook{
//在方法上面使用注解完成增强配置
@Before(value="execution(* cn.itcast.aop.Book.*(..))")
public void before(){
System.out.println("before.......");
}
}
2.Spring的jdbcTemplate操作
1)Spring框架一站式框架(针对JavaEE的三层,每一层都有解决技术)
2)在DAO层,使用jdbcTemplate
3.Spring对不同的持久化层技术都进行了封装
1)jdbcTemplate对jdbc进行封装
4.jdbcTemplate的使用和dbutils使用和相似,对数据库进行crud操作
添加
1)导入jdbcTemplate使用的jar包(spring-jdbc-4.2.4.RELEASE.jar spring-tx-4.2.4.RELEASE.jar)
2)创建对象,设置数据库信息(注意配置数据库的驱动)
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:myql:///spring_day_03");
dataSource.setUsername("root");
dataSource.setPassword("root");
3)创建jdbcTemplate对象,设置数据源
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
4)调用jdbcTemplate对象里面的方法实现操作
1.创建sql语句
String sql="insert into user values(?,?)";
jdbcTemplate.update(sql,"lucy","123");//调用模板中的update方法
修改
1)设置数据库的信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:myql:///spring_day_03");
dataSource.setUsername("root");
dataSource.setPassword("root");
2)创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
3)调用jdbcTemplate对象里面的update()方法实现操作
String sql="update user set password=? where username=?";//根据用户名修改密码
int rows=jdbcTemplate.update(sql,"1234","lucy");
System.out.println(rows);//输出结果为1,修改成功
删除
1)设置数据库的信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:myql:///spring_day_03");
dataSource.setUsername("root");
dataSource.setPassword("root");
2)创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
3)调用update()方法实现删除
String sql="delete from user where username=?";
int rows=jdbcTemplate.update(sql,"lucy");
System.out.println(rows);
查询
1.使用jdbcTemplate实现查询操作
2.查询的具体操作
1)查询返回某一个值(数据库中有多少条记录)
1.设置数据库信息
2.创建jdbcTemplate对象
3.调用方法得到记录数
String sql="select count(*) from user";
4.调用jdbcTemplate的方法
int count=jdbcTemplate.queryForObject(sql,Integer.class);
第一个参数,sql:返回sql语句
第二个参数,requiredType:返回类型的class
注意:jdbc底层实现程序
public class testJDBC(){
Connection conn=null;
PreparedStatement psmt=null;
ResultSet rs=null;
//1.加载驱动
try{
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接
conn=DriverManager.getConnection("jdbc:mysql:///spring_day03","root","root");
//3.编写sql语句
String sql="select *from user where username=?";
//4.预编译sql
psmt=connt.prepareStatement(sql);
//5.设置参数值
psmt.setString(1,"lucy");
//6.执行sql
rs=psmt.executeQuery();
//7.遍历结果集
while(rs.next()){
//得到返回结果集
String username=rs.getString("username");
String password=rs.getString("password");
//创建一个实体类,将username与password放到实体类中去
//创建实体类的对象
User user=new User();
user.setUsername(username);
user.setPassword(password);
//输出user
System.out.println(user);
}
}catch(ClassNotFoundException e){
e.printStackTrace();
}finally{
try{
rs.close();
psmt.close();
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
2)查询返回对象
1)在方法里面操作,设置数据库信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:myql:///spring_day_03");
dataSource.setUsername("root");
dataSource.setPassword("root");
2)创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
3)写sql语句,根据username查询
String sql="select *from user where username=?";
4)调用jdbcTemplate的方法实现
jdbcTemplate.queryForObject(String sql,RowMapper<T>rowMapper,Object...args)
User user=jdbcTemplate.queryForObject(sql,new MyRowMapper(),"lucy")
第一个参数:sql语句
第二个参数:RowMapper,接口,类似于dbutils里面的接口,需要自己写类实现接口,自己实现数据封装
第三个参数:可变参数
注意:在Java里面可以有多个class,但是只能有一个public
写RowMapper类
class MyRowMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet rs,int num) throws SQLException{
//1.从结果集里面得到数据
String username=rs.getString("username");
String password=rs.getString("password");
//2.将得到的数据封装到对象里面
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
}
5)输出user
System.out.println(user);
3)查询返回list集合
query(String sql,RowMapper<T> rowMapper,Object...args):List<T>
1)sql语句
2)RowMapper接口,自己写类实现数据封装
3)可变参数
1)设置数据库信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:myql:///spring_day_03");
dataSource.setUsername("root");
dataSource.setPassword("root");
2)创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
3)写sql语句
String sql = "select * from user";
4)调用jdbcTemplate的方法实现
List<User> list=jdbcTemplate.query(sql,new MyRowMapper());
System.out.println(list);
//MyRowMapper()实现与上面的一样
注意:增、删、修都是使用update()方法,而查询使用的query()方法
Spring配置连接池和dao使用jdbcTemplate
1.Spring配置连接池(c3p0)
1)导入jar包(c3p0连接池jar包c3p0-0.0.2.1.jar mchange-commons-java-0.2.3.4.jar)
2)创建Spring配置文件,配置连接池
1)将程序在配置文件中进行配置
<!--配置c3p0连接池-->
//创建连接池对象
<bean id="dataSource" class="com.mchange.v2.c3po.ComboPooledDataSource">
<!--注入属性值-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
注意:设置c3p0连接池的信息(原始方式)
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_day03");
dataSource.setUsername("root");
dataSource.setPassword("root");
2.dao使用jdbcTemplate
1)创建Service和dao对象,在service里面注入dao对象
<bean id="userService" class="cn.itcast.c3p0.UserService"></bean>
<!--注入dao对象-->
<property name="userDao" ref="userDao"></property>
2)创建jdbcTemplate对象,将模板对象注入到dao里面
//得到JdbcTemplate对象
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate=jdbcTemplate;
}
<bean id="userDao" class="cn.itcast.c3p0.UserDao">
<!--注入jdbcTemplate对象-->
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
3)在jdbcTemplate对象里面注入dataSource
private DataSource dataSource;
private SQLExceptionTranslator exceptionTranslator;
private boolean lazyInit=true;
public void setDataSource(DataSource dataSource){
this.dataSource=dataSource;
}
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--将dataSource传递到模板对象里面-->
<property name="dataSource" ref="dataSource"></property>
</bean>
案例:Service调用DAO,然后DAO调用jdbcTemplate,最后jdbcTemplate调用dataSource
UserService.java
public class UserServie{
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public void add(){
userDao.add();
}
}
UserDao.java
public class UserDao{
//得到JdbcTemplate对象
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate=jdbcTemplate;
}
//添加操作
public void add(){
//创建jdbcTemplate对象
//JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="insert into user values(?,?)";
jdbcTemplate.update(sql,"李磊","123");
}
}
测试类:
扩展
Spring JDBCTemplate 方法详解
1.JDBCTemplate 主要提供以下五类方法:
1.execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句。
2.update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句。batchUpdate方法用于执行批处理相关语句。
3.query方法及queryForXXX方法:用于执行查询相关语句。
4.call方法:用于执行存储过程、函数相关语句。
2.JDBCTemplate 类支持的回调类
1.预编译语句及存储过程创建回调:用于根据JdbcTemplate提供的连接创建相应的语句
1.PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的PreparedStatement
2.CallableStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的CallableStatement
2.预编译语句设置回调:用于给预编译语句相应参数设值
1.PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由用户来对相应的预编译语句相应参数设值
2.BatchPreparedStatementSetter:;类似于PreparedStatementSetter,但用于批处理,需要指定批处理大小
3.自定义功能回调:提供给用户一个扩展点,用户可以在指定类型的扩展点执行任何数量需要的操作
1.ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,用户可在该Connection执行任何数量的操作
2.StatementCallback:通过回调获取JdbcTemplate提供的Statement,用户可以在该Statement执行任何数量的操作
3.PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,用户可以在该PreparedStatement执行任何数量的操作
4.CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,用户可以在该CallableStatement执行任何数量的操作
4.结果集处理回调:通过回调处理ResultSet或将ResultSet转换为需要的形式
1.RowMapper:用于将结果集每行数据转换为需要的类型,用户需实现方法mapRow(ResultSet rs, int rowNum)来完成将每行数据转换为相应的类型。
2.RowCallbackHandler:用于处理ResultSet的每一行结果,用户需实现方法processRow(ResultSetrs)来完成处理,在该回调方法中无需执行rs.next(),该操作由JdbcTemplate来执行,用户只需按行获取数据然后处理即可。
3.ResultSetExtractor:用于结果集数据提取,用户需实现方法extractData(ResultSet rs)来处理结果集,用户必须处理整个结果集。
3.使用方法
1.预编译语句以及存储过程创建回调、自定义功能回调使用
首先使用PreparedStatementCreator
创建一个预编译语句,其次由JdbcTemplate
通过PreparedStatementCallback
回调传回,由用户决定如何执行该PreparedStatement
。此处我们使用的是execute
方法。
2.预编译语句设值回调使用
通过JdbcTemplate
的int update(String sql, PreparedStatementSetterpss)
执行预编译sql
,其中sql
参数为insert into test(name) values (?)
,该sql
有一个占位符需要在执行前设值。PreparedStatementSetter
实现就是为了设值,使用 setValues(PreparedStatementpstmt)
回调方法设值相应的占位符位置的值。 JdbcTemplate
也提供一种更简单的方式update(String sql, Object... args)
来实现设值,所以只要当使用该种方式不满足需求时才应使用PreparedStatementSetter
。
结果集处理回调
RowMapper
接口提供mapRow(ResultSet rs, int rowNum)
方法将结果集的每一行转换为一个Map
,当然可以转换为其他类,如表的对象画形式。
RowCallbackHandler
接口也提供方法processRow(ResultSet rs)
,能将结果集的行转换为需要的形式。
ResultSetExtractor
使用回调方法extractData(ResultSet rs)
提供给用户整个结果集,让用户决定如何处理该结果集。
注意:我们可以使用JdbcTemplate提供更简单的queryForXXX方法,来简化开发。
//1.查询一行数据并返回int型结果
jdbcTemplate.queryForInt("select count(*) from test");
//2. 查询一行数据并将该行数据转换为Map返回
jdbcTemplate.queryForMap("select * from test where name='name5'");
//3.查询一行任何类型的数据,最后一个参数指定返回结果类型
jdbcTemplate.queryForObject("select count(*) from test", Integer.class);
//4.查询一批数据,默认将每行数据转换为Map
jdbcTemplate.queryForList("select * from test");
//5.只查询一列数据列表,列类型是String类型,列名字是name
jdbcTemplate.queryForList("select name from test where name=?", new Object[]{"name5"}, String.class);
//6.查询一批数据,返回为SqlRowSet,类似于ResultSet,但不再绑定到连接上
SqlRowSet rs = jdbcTemplate.queryForRowSet("select * from test");
总结:JDBCTemplate 提供很多方法,这其中的规律便是:第一种提供回调接口让用户决定做什么。第二种是比较简单方法(如:queryForXxx),用于比较简单的操作。
4.JDBCTemplate 的基本使用步骤
1.JDBC模板依赖连接池来获取数据的连接,所以需要先构建连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("123456");
2.创建JDBC模板
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//或者使用构造方法
jdbcTemplate.setDataSource(dataSource);
注意:1.配置JDBCTemplate的三种方式:1.在自定义的DAO实现类注入一个DataSource引用来完成JdbcTemplate的实例化,即从外部注入DataSource到DAO中,然后实例化jdbctemplate,然后将DataSource设置到jdbcTemplate对象中。2…….
3.sql语句
//查询的sql语句
String sql = "select count(*) from user";
Long num = (long) jdbcTemplate.queryForObject(sql, Long.class);
System.out.println(num);
注意:Spring学习中,在new对象的时候我们应该想到IOC,在使用set方法时应该想到DI,在要切面时应该想到AOP,所以有一引用链:
1. 我们需要有DataSource,DataSource的属性可以通过注入数据库的一些配置属性添加
2. 我要有JdbcTemplate,而Template依赖与DataSource,我要以ref的方式为我的JdbcTemplate注入引用
3. 有了JdbcTemplate之后,我要有Dao,此时我应该在Dao添加一个JdbcTemplate的成员,然后以ref的方式将JdbcTemplate引入到Dao中
4. 我在Action或者是Servlet中都会调用的是Serivce,所以,我在Serivce中要添加一个Dao作为成员,然后由ref在注入Dao到Service中
DataSource --> JdbcTemplate --> Dao --> Service --> Action/Servlet
"-->"表示将左边的对象注入到右边的对象当中
5.JDBCTemplate 的CRUD方法
//插入程序用的是update方法,查询用的是query方法。
//首先定义一个sql语句
String sql = "insert into user (username,password) values(?,?)";
//然后使用jdbctemplate方法插入数据
jdbcTemplate.update(sql, user.getUsername(), user.getPassword());
注意:
jdbcTemplate.update
适用于insert/update/delete
操作。
其中:第一个参数为执行的sql。 第二个参数为参数数据 第三个参数为参数类型。
//删除
String sql = "delete from user where username= ?";
jdbcTemplate.update(sql, "小王");
//修改
String sql = "update user set username=? where username= ?";
jdbcTemplate.update(sql, user.getUsername() + "_new", user.getUsername());
//查询
//在最开始使用比较基础的持久化工具(DBUtils)时,会针对查询结果给我们提供一些封装的接口和类,但是JdbcTemplate只给我们提供接口,并没有可用的类,所以需要我们自己实现类来进行封装。
//1.查询表的记录数
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
String sql = "select count(*) from user";
Long row = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println("查询出来的记录数为:" + row);
//2.查询返回对象
//获得jdbcTemplate对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
String sql = "select username, password from user where username = ?";
// 设定参数
Object[] object = {"mary_new"};
// 进行查询
User user = jdbcTemplate.queryForObject(sql, object, new UserMapper());
System.out.println(user);
//注意:除此之外还需要实现结构RowMapper来新建一个映射类,且此java类应该与具体的sql语句对应。
...
public class UserMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet resultSet, int rows) throws SQLException {
User user = new User();
user.setUsername(resultSet.getString(1));
user.setPassword(resultSet.getString(2));
return user;
}
....
//3.查询并返回list集合
...
// 获得jdbcTemplate对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
// sql语句
String sql = "select * from user";
List<User> users = jdbcTemplate.query(sql, new UserMapper());
for(User u: users) {
System.out.println(u);
}
...
6.JdbcTemplate.queryForList()方法中不同的参数:
1.String sql;//查询用的sql语句
2.Object[] args;//sql语句中的参数
3.int[] argTypes;//sql语句中参数的数据类型
4.Class elementType;//list装载结果的元数据类型
扩展:
1.常用注解:
1.@Transactional 事务注解,标注当前类时表示类中所有方法都进行事务处理。
@Transactional public class TestServiceBean implements TestService {}
注意:1.@Transactional 只能被应用到public方法上,对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
2.POJO类与VO类
vo:1.表示viewObject 只负责封装页面传递过来的数据 2.valueObject 页面与页面之间的传递时保存值的对象。
区别1:1.POJO是持久层所使用的,是用来封装原始数据的,而VO则主要用来在视图层活动,两个JavaBean所使用的范围不同。假如我们从数据库取出来的原始数据,我们可以通过业务层将数据进行封装,再通过VO发到页面上去。
过程:我们获得的时候,数据是原始数据,然后通过业务层进行判断,将其所对应的参数放到VO里。即POJO里的属性主要是用来给数据库用的,而VO里的属性是纯用户显示的。
区别2:1.POJO类,是不继承任何类(继承Object类),不实现任何接口的,只有属性和set/get方法。
2.VO类,实际返回给用户的视图对象,将某个指定页面<组件>的所有数据封装起来。
如:用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。
3.PO类,每个数据基本上都对象数据库中的某个字段,一般需要实现序列化接口,也有些时候继承一些类
SSH框架整合(Struts2 hibernate spring4.x)
回顾SSH框架知识点
Hibernate框架
1.Hibernate核心配置文件
- 如果单纯使用Hibernate框架,核心配置文件名称hibernate.cfg.xml和位置在src下面这是固定的
- Hibernate和Spring进行整合的时候,hibernate核心配置文件的名称和位置是没有固定要求的
1)ORM思想(对象关系映射 实体类与数据表之间的映射关系)
Struts2框架
1.Action操作
1)action创建的三种方式
继承类 ActionSupport
2)配置action访问路径
- 创建struts2.xml配置文件,这个配置文件名和位置固定在src下面
3)配置访问action的多个方法
- 使用通配符方式配置
4)在action获取表单提交数据
- 获取request对象
-- 使用ServletActionContext类获取
- 属性封装
- 模型驱动(重点)
- 表达式封装
5)在action操作域对象
- 使用ServletActionContext获取域对象
6)配置struts2的过滤器
2.值栈
1)向值栈放数据
- set方法
- push方法
- 定义变量,生成get方法
2)从值栈获取数据
- 在JSP中使用struts2标签+ognl获取
- <s:property>
- <s:iterator>
3.拦截器
1)aop和责任链模式
2)自定义拦截器
- 继承MethodFilterInterceptor
- 重写类里面的方法
- 配置拦截器和action关联
Spring框架
1.spring核心配置文件
1)名称和位置没有固定要求
2)在spring核心配置文件中引入schema约束
2.创建对象
1)xml配置方式 <bean id="" class="" scope=""/>
2)注解方式,四个注解
3.注入属性
1)xml配置方式
2)注解方式,两个注解
4.使用ServletContext对象和监听器实现
1)在服务器启动时候,加载spring配置文件,创建连接
2)配置spring的监听器
3)指定spring配置文件位置
SSH整合的思想
Web层:struts2框架 调用service层
Service层:Spring框架 调用DAO层
Dao层:Hibernate框架 对数据库进行crud操作
注意:框架的之间的整合往往是两个框架之间的整合
1.struts2框架与Spring框架的整合
- 将struts2的action对象创建交给Spring来进行管理
<bean id="" class="" acope="protype">
2.Spring框架与Hibernate框架之间的整合
- 将hibernate核心配置文件里面的数据库配置,直接写在Spring配置文件中
- 在第一次访问的时候会很慢,是因为在第一次访问的时候要创建sessionFactory对象
-- 解决方案:将sessionFactory对象创建交给Spring来管理
- 在服务器启动的时候创建sessionFactory对象
整合Struts2与Spring框架
将Struts2的action交给Spring管理
实现过程
1.导入Struts2的jar包
SSH框架搭建和整合(struts2/spring4/hibernate5)
集成SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层(实体层),以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。
总结:
在SSH框架中使用Struts2框架作为系统的整体基础架构,负责MVC的分离。
在Struts框架的模型(model)部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做支持,支持struts和hibernate。
具体做法是:用面向对象的分析方法根据需求提出一些模型,将这些模型实现为基本的Java对象,然后编写基本的DAO(Data Access Objects)接口,并给出Hibernate的DAO实现,采用Hibernate架构实现的DAO类来实现Java类与数据库之间的转换和访问,最后由Spring做支持,支持struts和hibernate。
其实ssh框架最主要的本质是:“高内聚、低耦合”。