Spring--day02

作者: 键盘瞎 | 来源:发表于2017-03-06 22:31 被阅读82次

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


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

    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());
    

    相关文章

      网友评论

        本文标题:Spring--day02

        本文链接:https://www.haomeiwen.com/subject/kciwwttx.html