Spring--day02

非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿


感谢传智博客及黑马程序猿

Spring整合web项目

引入:在做开发中,使用mvc+dao模式,提交表单到Servlet中,Servlet调用Service里面的方法,在Service里面调用dao里面的方法

第一步:导入Spring整合web项目的jar包

spring的web项目jar包

第二步:创建Servlet、Service、dao

package cn.itcast.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class UserServlet extends HttpServlet {
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("servlet执行了...............");    
       //得到service对象
        WebApplicationContext context = 
                     WebApplicationContextUtils.getWebApplicationContext
                              (this.getServletContext());       
        UserService service = (UserService) context.getBean("userService");
        service.testservice();
    }

    /**
     * 
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
package cn.itcast.web;

public class UserService {
    
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }


    public void testservice() {
        System.out.println("service........");
        userDao.testdao();
    }
}
package cn.itcast.web;

public class UserDao {

    public void testdao() {
        System.out.println("dao.............");
    }
}

第三步:配置applicationContext.xml

<?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.xsd">
    <!-- 创建dao和service对象 -->
    <bean id="userDao" class="cn.itcast.web.UserDao"></bean>
    <bean id="userService" class="cn.itcast.web.UserService">
        <!-- 注入dao对象 -->
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

第四步:配置web.xml监听器配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
   <!-- 使用全局初始化参数配置文件位置 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
  <!-- 配置监听器 ContextLoaderListener -->
  <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>cn.itcast.web.UserServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/userServlet</url-pattern>
  </servlet-mapping>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

问题:

在Servlet中获取Service时候因为

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

每次访问Servlet的时候,都会创建一次对象,造成资源浪费,只需要创建一次就可以了

日志信息

解决方法:

在web项目中只有一个对象是ServletContext对象。这个对象范围是整个web项目。

做法:可以在服务器启动时候,把applicationContext对象放到servletcontext里面去。之前学过监听器。监听到servletcontext对象创建和销毁

创建类,实现接口ServletContextListener,监听到servletcontext对象创建,只要创建把applicationContext对象放到里面去。

第一步:配置监听器ContextLoaderListener

public class ContextLoaderListener extends ContextLoaderListener implements ServletContextListener{
  
}

第二步:指定配置文件位置

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

第三步:使用WebApplicationContextUtils得到context对象

WebApplicationContext context = WebApplicationContextUtil.getWebApplicationContext(this.getServlet());

AOP

AOP相关概念

什么是AOP:

面向方面编程。在一个基本功能之上,添加一个额外的功能,但是没有额外的功能,基本功能也可以正常运行。

AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

比如有用户管理系统,有添加用户的功能,如果添加完成用户之后,可以记录添加的日志(东方不败在2016-11-11添加了用户),但是如果没有记录日志,添加用户的功能也可以运行。

AOP

Aop底层使用动态代理,增强一个类中的方法,有两种:

第一种:JDK动态代理,使用在有接口情况下,生成接口实现类的代理对象

第二种:cglib动态代理,使用在没有接口情况下,生成类的子类代理对象

JDK的动态代理

例:

public DaiLi implements InvocationHandler{
    private Bird bird;
    public DaiLi(Bird bird) {
        this.bird = bird;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throw Throwable{
        bird.fly();
        Sysotem.out.println("增强输出");
        return null;
    }
}

Class[] interfaces = {Bird.class};
Bird bird = (Bird) Prxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new DaiLi(new Ying));
bird.fly();

针对有接口情况,生成接口实现类的代理对象

CGLIB动态代理

针对没有接口情况,生成类子类代理对象

public ProductService createProductService() {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(productSercice.getClass());
    enhancer.setCallBack(this);
  
    ProductService procutService = (ProductService) enhancer.create();
    return productService;
}
public Object intercept(Object o, Method method, Object[] obj, MethodProxy methodProxy) throws Throwable {
    Object object = methodProxy.invokeSuper(o, obj);
    System.out.println("CGLIB增强的方法。。。");
    return object;
}
public static void main(String[] args) {
    MyCGLIB cglib = new MYCGLIB(new ProductService());
    ProductService productService = cglib.createProductService();
    productService.buy();
}

AOP术语

Joinpoint(连接点):在一个类中有哪些方法可以增强,这些方法称为连接点

Pointcut(切入点):在一个类中的所有可以被增强的方法中,哪些方法具体做增强

Advice(增强/通知):写具体的增强逻辑。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的通知)

Target(目标对象):代理的目标对象(要增强的类)

Weaving(织入):是把增强应用到目标的过程。把advice应用到target

Proxy(代理):一个类被AOP织入增强后,就产生了一个结果代理类

Aspect(切面):是切入点和增强的结合。把具体的逻辑增强到具体的方法上

Introduction(引介):引介是一种特殊的通知在不修饰类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或属性

Spring的传统方式Aop

第一步:导入两个jar包

jar包

第二步:配置文件,加入新的约束

约束

Spring的AOP切面类型:

​ Advisor:不带切入点切面,对目标类所有方法进行拦截

​ PointcutAdvisor:有切点的切面,可以指定拦截目标类那些方法

不带切入点的切面

不带切入点的切面,对目标类所有方法进行拦截

第一步:生成实现类和增强类对象

<!-- 创建接口实现类的对象 -->
<bean id="userDao" class="cn.xxx.userDaoImpl"></bean>
<!-- 创建通知类的对象 -->
<bean id="myBefore" class="cn.xx.MyBefore"></bean>

第二步:配置增强类和实现了的关系

<!-- 配置切面 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 指定哪个通知在哪些方法上 -->
    <!-- 指定是生成哪个接口类的实现对象 -->
    <property id="proxyFaces" value="cn.xxx.UserDao"></property>
    <!-- 配置使用的哪一个通知 -->
    <property id="interceptorNames" value="myBefore"></property>
    <!-- 配置目标类 -->
    <property name="target" ref="userDao"></property>
</bean>

第三步:测试

@Resource(name="proxyFactoryBean")
private UserDao userDao;

@Test
public void test() {
    userDao.run();
}

带切入点切面

第一步:创建类的对象

<!-- 配置带切入点切面 -->
<bean id="personDao" class="cn.xx.PersonDao"></bean>
<bean id="myAround" class="cn.xx.MyAround"></bean>

第二步:配置切入点(配置类里面哪些方法进行增强)

配置切入点

第三步:配置切面

配置切面

Spring基于aspectj的AOP操作(重点)

AspectJ是一个面向切面的框架,它扩展了Java语言。

AspectJ是一个基于Java语言的AOP框架

Spring2.0以后新增了对AspectJ切点表达式支持

@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面

新版本Spring框架,建议使用AspectJ方式来开发AOP

基于aspectj的注解方式

第一步:导入相关的jar包

jar包

第二步:在配置文件中引入约束

约束

第三步:开启aspectj的注解

aspectj的注解

使用注解实现不同的通知

  1. @Before 前置通知,相当于BeforeAdvice
  2. @AfterReturning 后置通知,相当于AfterReturningAdvice
  3. @Around 环绕通知,相当于MethodInterceptor
  4. @AfterThrowing抛出通知,相当于ThrowAdvice
  5. @After 最终final通知,不管是否异常,该通知都会执行

通过execution函数,可以定义切点的方法切入

• 语法:

– execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

• 例如

– 匹配所有类public方法 execution(public * *(..))

– 匹配指定包下所有类方法 execution(cn.itcast.dao.(..)) 不包含子包

– execution(* cn.itcast.dao..(..)) ..表示包、子孙包下所有类

– 匹配指定类所有方法 execution(cn.itcast.service.UserService.(..))

– 匹配实现特定接口所有类方法 execution(cn.itcast.dao.GenericDAO+.(..))

– 匹配所有save开头的方法 execution(* save*(..))

常用的写法:

​ 匹配所有类的所有的方法 execution(* .(..))

​ 匹配某个类的里面所有的方法 execution(* cn.itcast.UserDao.*(..))

    匹配某个类里面的某一个方法execution(*cn.itcast.UserDao.update(..))

基于切入点的注解

有多个类型通知,都需要对一个类里面某一个方法进行增强

使用注解@Pointcut,写在一个方法上面

例子

使用时候,在增强的方法上面使用类名.方法名称调用

例子

基于aspectj的xml方式

第一步:导入jar包(包含基本jar包,包含aop的jar包,包含aspectj的jar包)

第二步:在配置文件中引入约束(beans、aop约束)

第三步:创建类,创建增强类

第四步:配置两个类的对象

配置

第五步:使用aspectj的方法xml进行配置

  1. 配置切面
  2. 配置切入点
  3. 使用哪个增强用在哪个方法上面
配置

Spring的jdbcTemplate模板

spring的jdbcTemplate,可以实现对数据库的crud的操作。底层就是jdbc操作,对jdbc进行了封装。

//构造连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//设置数据库相关信息
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUserName("root");
dataSource.setPassword("root");

//创建jdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "create table user (id int, username varchar(100))";
//执行sql语句
template.execute(sql);

使用jdbc实现增删改操作

添加方法

JdbcTemplate template = new JdbcTemplate(dateSource);
String sql = "insert into user (?, ?)";
int rows = template.update(sql ,1, "Lucy");

修改方法

JdbcTemlate template = new JdbcTemplate(dateSource);
String sql = "update user set username = ? where id = ?";
template.update(sql, "东方不败", 1);

删除方法

JdbcTemlate template = new JdbcTemplate(dateSource);
String sql = "delete from user where id = ?";
template.update(sql, 1);

Spring的jdbc模板

第一步:导入相关的jar包

jar包

第二步:配置数据库信息

调用模板里面的方法实现,如果实现增加、修改、删除调用里面的update方法

update()方法

第一个参数是sql语句,第二个参数是参数值的可变参数

Jdbc模板的连接池配置

有c3p0、dbcp...等开源连接池

第一个:配置dbcp连接池

1、导入dbcp连接池的jar包

dbcp jar包

2、配置连接池

连接池配置

3、注入dbcp模板

dbcp模板
dbcp 模板

第二个:配置c3p0连接池

1、导入c3p0的jar包

c3p0 jar包

2、配置连接池

配置连接池
<!-- 配置数据库连接池(c3p0) -->
    <bean id="dataSouce" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 基本信息 -->
        <!-- 必须加jdbc.xxx -->
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="driverClass" value="${jdbc.driverClassName}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>

        <!-- 其他配置 -->
        <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
        <property name="initialPoolSize" value="3"></property>
        <!--连接池中保留的最小连接数。Default: 3 -->
        <property name="minPoolSize" value="3"></property>
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize" value="5"></property>
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="acquireIncrement" value="3"></property>
        <!-- 控制数据源内加载的PreparedStatements数量。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
        <property name="maxStatements" value="8"></property>
        <!-- maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
        <property name="maxStatementsPerConnection" value="5"></property>
        <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime" value="1800"></property>
    </bean>

Jdbc模板简化开发

第一步:在dao中继承类,不需要手动注入jdbcTemplate了

public class PersonDao extends JdbcDaoSupport{
  
}

第二步:在配置文件中,直接在dao里面注入dataSource

<bean id="personDao" class="cn.xx.PersonDao">
    <property name="dataSource" ref="dataSource"></property>
</bean>

第三步:在dao方法里面得到jdbcTemplate的对象

this.getJdbcTemplate().update("insert into user values(?, ?)", 3, "Tom");

使用jdbc模板实现查询操作

在jdbcTemplate里面有接口,而没有提供实现的类,需要自己封装数据

第一个操作:查询单值操作

方法
int count = this.getJdbcTemplate().queryForInt("select count(*) from user");

第二个操作:查询某一个对象

方法

方法里面有三个参数:第一个参数是sql语句,第二个参数RowMapper是接口,数据返回结果集,需要手动封装返回结果,第三个参数是参数值

RowMapper接口
String sql = "select * from user where id = ?";
Orders orders = this.getJdbcTemplate().queryForObject(sql, new MyRowMapper(), 1);

MyRowMapper类

public class MyRowMapper implements RowMapper<Orders> {
    //封装数据
    public Orders mapRow(ResultSet rs, int mun) throws SQLException{
        //把结果集rs里面的数据,手动封装到orders里面
        //把结果集里面的数据取出来
        int id = rs.getInt("id");
        String username = rs.getString("username");
        String password = rs.getString("password");
        //封装到Orders里面
        Orders o = new Orders();
        o.setId(id);
        o.setUsername(username);
        o.setPassword(password);
        return 0;
    }
}

第三个操作:查询所有数据

方法
String sql = "select * from user";
/**
实现过程:
首先得到每条记录的结果集
把每条记录封装到一个对象里面
这个过程做循环操作
最终把封装的多条记录,放到List集合里面
*/
List<Orders> list = this.getJdbcTemplate().query(sql, new MyRowMapper());
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容