注意:所有文章除特别说明外,转载请注明出处.
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框架最主要的本质是:“高内聚、低耦合”。
