07_项目一Ⅰ

Day1 Spring IOC入门

1.1IOC思想推导

  • IOC Inversion of Control(控制反转)由传统的主动实例化对象(new 对象),变为从容器(map)集合中获取

  • 对象创建的两种方式:

    • 通过手动反射创建对象

    • map集合(容器)中获取

      1. 创建xml配置文件

        <beans>
        	<bean id="" class=""></bean>
        </beans>
        
      2. 单例工厂

      3. 获取配置文件的输入流

      4. 创建SAXReader对象

      5. 获取Document对象

      6. 获取跟节点

      7. 获取所有的bean节点

      8. 解析bean节点,获取id和class属性

      9. 用反射创建对象

      10. 将id和对应的对象存入map集合

      11. 根据id获取map中的对象并返回

1.2Spring概述和IOC

Spring介绍

  • spring是于2003 年兴起的一个full-stack轻量级的Java 开源框架
  • Spring以IOC Inversion of Control(控制反转)和AOP(面向切面编程)为核心
  • Spring提供了展现层Spring MVC、持久层Spring JDBC、业务层事务管理等众多的企业级应用技术
  • Spring还能整合开源世界众多的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架

IOC(控制反转)

  • 一种设计思想,目的是指导我们设计出更加松耦合的程序。
  • 指将对象的控制权由原来的 程序员在类中主动控制 反转到 由Spring容器来控制。
  • 对象的创建交由Spring容器管理,需要对象从容器中获取即可
  • 主要功能是解耦,底层原理是反射

1.3SpringIOC的入门

  • 创建工程导入依赖

    <dependencies>
            <!--spring的坐标-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.6.RELEASE</version>
            </dependency>
        </dependencies>
    
  • 创建Dao接口和实现类

  • 创建Spring配置文件

    • spring配置文件约定俗称: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">
    
        <bean id="唯一标识" class="全限定类名"></bean>
    
    </beans>
    
  • spring的API介绍

    • Spring的API体系异常庞大,我们现在只关注两个:
    • BeanFactory
      • BeanFactory是 Spring 的"心脏",是 IOC 容器的核心接口,它定义了IOC的基本功能。
      • 用来配置文档,管理bean的加载,实例化并维护bean之间的依赖关系,负责bean的声明周期
    • ApplicationContext
      • 由BeanFactory派生而来,可以比喻为Spring的躯体,添加了很多功能。
        • 支持了aop功能和web应用
        • MessageSource, 提供国际化的消息访问
        • 通过配置来实现BeanFactory中很多编码才能实现的功能
      • 常用实现类
        • ClassPathXmlApplicationContext: 从classpath目录读取配置文件
        • FileSystemXmlApplicationContext: 从文件系统或者url中读取配置文件
        • AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring容器。它用来读取注解。
    • 区别:
      • beanFactory主要是面向Spring框架的基础设施,供spring自身内部调用
      • Applicationcontext 主要面向Spring的使用者。
      • BeanFactroy在第一次使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,而ApplicationContext是在容器启动时,一次性创建并加载了所有的Bean

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ozEziRuR-1605668946277)(assets\11.png)]

1.4对象的作用域和生命周期

 <bean id="唯一标识" class="全类名"  scope="..." init-method="方法名1" destroy-method="方法名2"></bean>
<!--
	scope :作用
		singleton :单例对象
			容器创建,自动的反射创建UserDaoImpl对象存入容器
			自动的执行init-method中配置的对象方法
			容器关闭时,对象销毁之前自动的执行destroy-method配置的对象方法
	    prototype:多例对象
	        当调用一次getBean方法,创建一次对象
			当对象创建,调用init-method中配置的对象方法
			多例对象(没有存在容器中),自动的进行垃圾回收
	init-method : 
		对象实例化之后,自动执行的对象方法
	destroy-method: 
		容器关闭,对象被销毁之前,自动执行的对象方法
-->

1.5依赖注入

  • 依赖注入:Dependency Injection (DI)。是 spring 框架核心 ioc 的具体实现
  • 本质是用于对象中的私有属性赋值
    • 构造方法注入
    • set方法注入

构造方法注入

  1. 向对象添加有参构造方法

    public class UserDaoImpl implements UserDao {
    
    	private String username;
        
        private Integer age;
        
        public UserDaoImpl(String username,Integer age){
            this.username = username;
            this.age = age;
        }
    
    }
    
  2. 在spring的配置文件中,通过bean标签配置对象创建

    <bean id="userDao" class="cn.....UserDaoImpl">
    	<constructor-arg name="username" value="参数1"></constructor-arg>
        <constructor-arg name="age" value="参数2"></constructor-arg>
        
        <!--
    		index	指定参数的索引 从0开始;
    		type	通过参数类型定位
    		name	通过参数名称定位
    			以上三个用于定位构造参数,三选一
    		-----------------------------------
    		value	对基本数据类型的数据赋值(8个基本+String)
    		ref		对Java实体类对象赋值
    			以上两个用于对参数赋值
    	-->
    </bean>
    

set方法注入

  1. 提供属性的set方法

    public class UserDaoImpl implements UserDao {
    	private String username;
        private Integer age;
        
        private List<String> list;
        private Set<String> set;
        private String[] array;
        
        private Map<String,String> map;
        private Properties properties;
    	此处应有7个Set方法
    }
    
  2. 在spring配置文件中,通过bean结合property配置set方法调用

    <bean id="userDao" class="cn.....UserDaoImpl">
    	<propertey name="username" value="参数1"></propertey>
        <propertey name="age" value="参数2"></propertey>
        <!--
    		property:
    			name	定位执行的set方法
    			value	对基本数据类型赋值
    			ref		对Java实体类对象赋值
    	-->
        <property name="list">
            <list>
                <value>参数1</value>
           		<value>参数2</value>
            </list>
        </property>
        
    	<property name="set">
            <set>
                <value>参数1</value>
           		<value>参数2</value>
            </set>
        </property>
        
        <property name="array">
            <array>
                <value>参数1</value>
           		<value>参数2</value>
            </array>
        </property>
    ---------------------------------------------------------------
        <property name="map">
            <map>
                <entry key="k1" value="v1"></entry>
                <entry key="k2" value="v2"></entry>
            </map>
        </property>
        
        <property name="properties">
            <props>
                <entry key="k1" value="v1"></entry>
                <entry key="k2" value="v2"></entry>
            </props>
        </property>
    </bean>
    

注入对象

  • 推荐set方法注入

配置文件的模块化

  • 并列的多个配置文件

    • 直接编写多个配置文件,beans1.xml…
    • 创建ApplicationContext的时候,直接传入多个配置文件。
     ApplicationContext act = new ClassPathXmlApplicationContext("beans1.xml","beans2.xml","...");
    
  • 主从配置文件

    • 先配置一个主配置文件
    • 然后在里面导入其它的配置文件。
     <import resource="beans1.xml" />
     <import resource="beans2.xml" />
    
  • 注意事项:

    • 同一个xml文件中不能出现相同名称的bean,如果出现会报错
    • 多个xml文件如果出现相同名称的bean,不会报错,但是后加载的会覆盖前加载的bean,所以企业开发中尽量保证bean的名称是唯一的。

Day02DbUtils&xml、注解、单元测试

2.1DbUtils

DbUtils是Apache的一款用于简化Dao代码的工具类,它底层封装了JDBC技术。

核心类:

  • QueryRunner 用于执行增删改查的SQL语句
  • ResultSetHandler 这是一个接口,主要作用是将数据库返回的记录封装进实体对象,查询数据封装,结果集处理器

核心方法:

  • update() 用来执行增、删、改语句 executeUpate
  • query() 用来执行查询语句 executeQuery

DbUtils基本使用:

  1. 创建工程导入依赖

    • mysql,druid,commons-dbutils,junit
  2. 创建实体类

    public class Accout {
        private Integer id;
        private String name;//账户名称
        private Float money;//账户金额
    	set...
        toString...
    }
    
  3. CRUD

    @Test
    public void testInsert() throws Exception {
        //1、创建DataSource
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///heima31");
        //2、创建QueryRunner对象 (通过构造参数,传入datasource)
        QueryRunner queryRunner = new QueryRunner(dataSource);
        //3、保存账户数据
        queryRunner.update("insert into account(name,money) values (?,?)", "小张",2);
        //4.查询单个账户
        Account account = queryRunner.query("select * from account where name=?", new BeanHandler<Account>(Account.class), "小张");
    }
    	//5.查询多个个账户
    	List<Account> list = queryRunner.query("select * from account", new BeanListHandler<Account>(Account.class));
    
    

2.2基于XML配置数据库操作

  1. 创建工程导入坐标

    • mysql,druid,commons-dbutils,junit,spring-context,spring-test
  2. 创建实体类

    public class Account {
        private Integer id;
        private String name;
        private Float money;
        get...
        set...
    }
    
  3. 创建dao接口

    public interface AccountDao {
        //1、保存账户
        public void saveAccount(Account account);
    }
    
  4. 创建dao接口实现类

    public class AccountDaoImpl implements AccountDao {
    
        //依赖属性
        private QueryRunner queryRunner;
    
        public void setQueryRunner(QueryRunner queryRunner) {
            this.queryRunner = queryRunner;
        }
    
        //保存
        public void saveAccount(Account account) {
            queryRunner.update("insert into account(name,money) values(?,?)", account.getName(),account.getMoney());
            
        }
    }
    
  5. 创建service接口

public interface AccountService {
    //1、保存账户
    public void saveAccount(Account account);
}
  1. 创建service接口实现类

    public class AccountServiceImpl implements AccountService {
    
        //依赖属性(依赖注入)
        private AccountDao accountDao;
    
        //用于property的set注入
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        //保存
        public void saveAccount(Account account) {
            accountDao.saveAccount(account);
        }
    }
    
  2. Spring配置

    • applicationContext.xml
    <!-- 创建AccountService对象,交给Spring管理-->
    <bean id="accountService" class="cn...AccountServiceImpl">
    	<!--ref:被spring容器管理的对象 id-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>
                                                   
    <bean id="accountDao" class="cn...accountDao">
    	<property name="queryRunner" ref="queryRunner"></property>
    </bean>
    	<!---->
    <bean id="queryRunner" class="cn...QueryRunnerImpl">
        <!--构造方法注入-->
    	<constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>
                                                   
    <bean id="dataSource" class="cn...DataSourceImpl">
    	<property name="username" value="root"></property>
        ....
    </bean>
    
  3. 测试

    public static void main(String[] args) {
            //1、创建spring容器
            ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
            // 2、从容器中获取对象
            AccountService accountService = (AccountService)ac.getBean("accountService");
    
            accountService.saveAccount(new Acount(...));
    
        }
    

2.3Spring中的常见注解

  1. xml中加入包扫描&托管properties文件

    <!--包扫描:扫描指定包及子包下的所有java类,扫描类中的Spring注解,帮助我们自动的创建对象存入容器-->
    <context:component-scan base-package="cn.itcast"></context:component-scan>
    
    <!--将properties文件,交给spring管理-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    
  2. 对象创建的注解

创建对象交给spring容器管理,语义话的形式代码分层
  <bean id="userDao" class="cn...UserDaoImpl"></bean>
  @Component (组件):
  @Controller :在web层使用
  @Service    :在service层
  @Repository :在dao层使用
      * 当spring容器启动时,根据包扫描配置自动的扫描到@Component注解,反射创建注解标注的对象,存入容器
      * 默认存入容器的id(唯一标识) = 当前类名首字母小写(userDaoImpl)
      * value属性 :自定义容器中对象的唯一标识
  1. 生命周期的注解

    对象的生命周期的注解
      @Scope : 配置到类上,生命对象的生命周期
          singleton:单例(默认)
          prototype:多例
      @PostConstruct: 相当于xml中的init-method
          对象初始化方法:配置到对象的方法上
      @PreDestory:相当于xml中的destory-method
          对象的销毁方法:配置到对象的方法上
    
  2. @Autowired

     @Autowired
         1、配置到依赖关系的属性上(通过Autowired依赖注入,不需要配置set方法)
         2、默认按照对象类型(接口类型)从容器中查找对象并注入赋值
         3、如果按照类型查询出多个对象,按照属性名作为id从容器中查找对象并注入赋值
     对于 @Autowired注解,大部分情况只需要此注解配置到属性上,即可完成依赖注入
     但是对于容器中存在多个同类型对象时
         1、修改属性名称(不常用)
         2、@Autowired结合@Qualifier共同使用,配置到属性上
             * 在@Qualifier中可以指定容器中对象的id
    
  3. @Reource

    @Resource:    
    	* 是jdk提供的依赖注入的注解,此注解在jdk9及以上版本已经移除    
    	* 配置到依赖对象的属性上,可以通过name属性,根据id从容器中查找对象,并注入
    
  4. @value

    @Value:配置到属性上
        1、注入基本数据类型的常量
        2、被Spring容器管理的properties文件中的内容
            i、配置文件交给Spring容器管理
            ii、通过@Value,从容器中得到配置项,并注入 :
            	语法规则:@Value(value="${properties文件中的key}")
    
  5. 注解总结

    • 使用注解编程之前,必须执行包扫描!!!
xml配置注解配置说明
< bean id="" class="" >@Component @Controller @Service @Repositorybean的实例化,向Spring容器中放入对象
< property name="" ref="">@Autowired @Qualifier @Resourcebean的对象属性注入,从Spring容器中获取对象
< property name="" value="">@Valuebean的简单属性注入
< bean scope="">@Scope控制bean的作用范围
< bean init-method=“init” destroy method=“destory” />@PostConstruct @PreDestroybean创建之后和销毁之前分别调用的方法

2.4注解结合XML

注解结合XML:

  • 自定义的java对象通过注解配置(service,dao)
    • service,repository,autowired
  • 第三方对象通过XML配置(QueryRunner,DataSource)

2.5纯注解

  1. 新建配置类

    # 通过SpringConfig替换之前的xml配置项
    	1、声明配置类,在类上配置一个注解
     		@Configuration
    	2、开启包扫描
    	 	@ComponentScan(basePackages = "cn.itcast")
         		basePackages: 指定需要扫描的包
    	3、将第三方jar包对象,创建并交给容器管理
    		 @Bean
    # 步骤
    	1、@Bean注解需要配置到方法上
        2、方法需要返回值
        3、在Spring容器启动的时候,自动的扫描所有配置了@Bean的方法
        4、自动执行被@Bean扫描的方法,将返回值存入Spring容器
        5、如果方法需要参数,Spring会从容器中根据类型获取对象,再调用在@Bean标注的方法中,可以配置依赖的属性参数
        6.spring会从容器中获取到依赖的对象,自动调用方法
    
    # 加载外部配置文件
    	1、声明配置类,在类上配置一个注解
      		@Configuration
     	2、开启包扫描
      		@ComponentScan(basePackages = "cn.itcast")
          		basePackages: 指定需要扫描的包
     	3、将第三方jar包对象,创建并交给容器管理
       		@Bean
     	4、将properties配置文件,交给spring容器管理
       		@PropertySource("jdbc.properties")
          		value : properties路径
        5、从从容器中获取值
        	@Value("${jdbc.username}")
    #  模块化
    	1、在主配置类中,通过Import引入其他的配置类
    		@Import(value=JdbcConfig.class)
    
  2. 测试

    public static void main(String[] args){
        //创建spring容器,根据注解配置类创建容器
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
    	...  
    }
    

2.6Spring整合单元测试

  • Junit在单元测试底层工作的是一个运行器,默认是ParentRunner

  • Spring提供了一个可以获取对象的运行器

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations ="classpath:applicationContext.xml")
    public class AccountJunitTest {
        //@Autowired注入待测试的对象,通过@Test发起测试
        @Autowired
        private AccountService accountService;
        //测试保存
        @Test
        public void testInsert() {
            //调用方法保存
            Account account = new Account();
            account.setMoney(100f);
            account.setName("小李1");
            accountService.saveAccount(account);
        }
    }
    

Day03SpringAOP壹

3.1转账事务问题

  • 原因
    • 每执行完一条sql语句后, jdbc会自动提交事务
  • 解决
    • 关闭事务的自动提交, 选择手动提交事务
    • 保证执行多条sql语句的是同一个connection
  • 方法
    1. Service创建connection向后传递
    2. Threadlocal方法

3.2Threadlocal

  • 原理

    • 将数据绑定到当前线程上,同一个线程中,从Threadlocal获取的数据是同一个对象
  • 使用

    //T是要存储的数据类型
    ThreadLocal<T> sThreadLocal = new ThreadLocal<T>();
    sThreadLocal.set() //将数据绑定到当前线程
    sThreadLocal.get() //从当前线程中获取数据
    

3.3事务管理器

  • 普通方式
    • 步骤
      • 编写事务管理器,提供获取connection及其他事务方法
      • 各代码层,引入事务管理器,从Threadlocal获取connection及事务方法
    • 问题
      • 事务代码和业务代码严重耦合在一起
    • 解决
      • 动态代理,在不改变源代码的前提下,对功能进行增强
      • java代码中只需要重点关注业务逻辑即可
      • 增强部分内容,通过动态代理添加
  • 动态代理方式
    • jdk动态代理
    • cglib动态代理
    • 两中代理方式的选择
      • 在创建代理实现类时, jdk的速度要高于cglib
      • 当被代理类有接口的时候,使用jdk动态代理, 因为它的效率高
      • 当被代理类没有接口的时候,使用cglib动态代理, 因为没办法

3.4cglib动态代理

  • 原理

    • 基于子类的动态代理
  • 使用cglib的方式创建代理对象

//编写代理逻辑
InvocationHandler invocationHandler = new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {	
        //增强方法
};

		// 使用cglib的方式创建代理对象
        // 1 创建增强器
        Enhancer enhancer = new Enhancer();

        // 2 设置父类
        enhancer.setSuperclass(AccountServiceImpl.class);

        // 3 设置代理逻辑
        enhancer.setCallback(invocationHandler);

        // 4 产生代理对象
        AccountServiceImpl instance = (AccountServiceImpl) enhancer.create();

        //5 使用代理对象运行方法
        instance.save(参数);

3.5AOP

  • 概念
    • AOP( 面向切面编程 )是一种思想, 它的目的就是在不修改源代码的基础上,对原有功能进行增强.
    • Spring AOP是对AOP思想的一种实现,Spring底层同时支持jdk和cglib动态代理.
    • Spring会根据被代理的类是否有接口自动选择代理方式:
      • 如果有接口,就采用jdk动态代理(当然,也可以强制使用cglib)
      • 没有接口就采用cglib的方式
  • 优点
    • 逻辑清晰,开发核心业务的时候,不必关注增强业务的代码码复用性高:增强代码不用重复书写
  • 总结
    • 核心业务增强业务同时出现时,我们可以在开发时对他们分别开发,运行时再组装在一起(使用动态代理的方式)
  • 工作原理
    • 开发阶段分别开发 运行阶段组装运行
    • 开发阶段
      • 开发共性功能,制作成增强
      • 开发非共性功能,制作成切点
      • 在配置文件中,声明切点与增强间的关系,即切面
    • 容器启动阶段
      • Spring读取配置文件中的切面信息,根据切面中的描述,
      • 将增强功能增加在 目标对象 的 切点方法 上,动态创建代理对象
      • 最后将经过代理之后对象放入容器中 (存入容器的是动态代理对象

3.6术语

  • 目标对象
    • target :被代理对象
  • 连接点
    • jointPoint:被代理对象中的所有方法
  • 切入点
    • pointCut: 被增强的方法
  • 增强(通知)
    • advice:一个具体的增强功能
    • 前置通知,后置通知,异常通知,最终通知,环绕通知
  • 代理对象
    • proxy :生成的动态代理对象
  • 切面
    • aspect:切面是一种描述,描述了一个什么样的功能添加到了哪个切入点的什么位置上
    • 切面 = 切点 + 增强

3.7SpringAOP的入门案例

  1. 创建工程,引入坐标

    • spring-context,aspectjweaver,junit
  2. 创建AccountDao的接口和实现类

  3. 开发增强功能

    • 在SpringAOP中,需要增强的功能需要配置到类中方法上
  4. 基于XML配置切面

    • 切面类需要交给Spring容器管理
    • 通过<aop:config> 开启AOP配置
      • 配置切入点(被增强的类和方法)
      • 配置切面
    <!--创建AccoutDao-->
    	...
    <!--配置AOP-->
    
    <!--切面类交给容器管理-->
    <bean id="logger" class="cn...Logger"></bean>
    
    <!--通过aop:config开启配置aop-->
    <aop:config>
    	<!--
    		配切入点:
    			id:唯一标志
    			expression(方法类型 返回值 全类名.方法(参数):切入点表达式
    				方法类型:可以省略
    				* :表示任意字符串
    			   .. : 表示任意个
    	-->
        <aop:pointcut id="pt" expression="execution(public void cn...AccountDaoImpl.save())"/>
        <!--
    		配置切面
    			ref:配置切面类(具有增强功能类)
    	-->
        <aop:aspect ref="logger">
        	<!--
    			四大通知之一:
    				method:切面类中的方法
    				pointcut-ref:切入点
    		-->
            <aop:before method="before" pointcut-ref="pt"></aop:before>
        </aop:aspect>
    </aop:config>
    
  5. 测试

3.8SpringAOP配置详解

  • 四大通知

    • 分类
      1. 前置通知(before) : 在切点运行之前执行
      2. 后置通知(after-returning): 在切点正常运行结束之后执行
      3. 异常通知(after-throwing): 在切点发生异常的时候执行
      4. 最终通知(after): 在切点的最终执行
    • 缺点
      • 四大通知的配置顺序不同,执行效果会不同
  • 环绕通知

    • 一种特殊的通知,他允许你以编码的形式实现四大通知

    • 和手动定义动态代理类似

    • 方法

      /**
      环绕通知
      	和自定义动态代理类似
      		1.具有返回:Object
      		2.参数:ProceedingJoinPoint:被代理对象执行的方法
      	目的
      		程序员自己编写去实现代码增强
      			1.增强代码块
      			2.被代理对象的方法
      */
      public Object around(ProceedingJoinPoint pjp) throw Throwable{
          Object obj = null;
          try{
              sout("前置通知");
              obj = pjp.proceed();
              sout("后置通知")
          }catch(Exception e){
              sout("异常通知")
          }
          return obj;
      }
      
    • 配置

      <aop:pointcut id="pt" expression="execution(* cn.itcast.dao.impl.*.*(..))"/>
      
      <aop:aspect ref=logger>
      	<aop:around method="around" pointcut-ref="pt"></aop:around>
      </aop:aspect>
      

Day04SpringAOP贰

4.1基于XML结合注解的配置

  • 开启注解支持

    • IOC的包扫描
    • AOP的自动代理
    • 自定义的对象,通过IOC注解进行对象创建和依赖注入
    • 第三方的对象,通过XML配置对象创建和依赖注入
    	<!--包扫描-->
        <context:component-scan base-package="cn.itcast"></context:component-scan>
    
        <!--开启AOP注解的支持,开启自动代理-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
    
  • 修改dao,通过注解创建对象,交给容器管理

  • 修改Logger切面类

    • 交给Spring容器管理
    • 在类上声明切面类 : @Aspect
    • 在类中的通知方法上:通过@Before,@After,@AfterReturning,@AfterThrowing,@Around配置通知类型
    @Component
    @Aspect
    public class Logger {
        //抽取公共参数
    	@pointcut(value="execution(* cn.itcast.dao.impl.*.*(..))")
        public void pt(){}
        
        //前置通知
        @Before(value="execution(* cn.itcast.dao.impl.*.*(..))")
        public void before() {
            System.out.println("执行前置通知:before方法");
        }
    	
        //环绕通知
        @Around (value="pt()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
    
            Object obj = null;
    
            try {
                System.out.println("执行前置通知");
                obj = pjp.proceed(); //执行被代理对象的方法
                System.out.println("执行后置通知");
            }catch (Exception e) {
                System.out.println("执行异常通知");
            }finally {
                System.out.println("执行最终通知");
            }
    
            return obj;
        }
    }
    
    

4.2基于纯注解的配置

  • 编写配置类

    • 删除applicationContext.xml配置文件
    • 编写配置类:SpringConfig.java
    • 在配置类中替换xml中的配置内容
      • 声明配置类
      • 开其IOC包扫描
      • 开启AOP的自动代理
    @Configuration//声明配置类
    @ComponentScan(basePackages = "cn.itcast")//IOC支持
    @EnableAspectJAutoProxy//AOP支持
    public class SpringConfig{
        
    }
    
    • 对象创建,AOP的切面配置

4.3基于XML的AOP事务配置

  • 修改AccoutServiceImpl

    • 只保留业务逻辑即可,将通知的内容。编写到对应的切面类中
  • 修改AccoutDaoImpl

    • 准备set注入
  • 配置切面类

  • 配置AOP

    • 基于xml的配置方式
    • IOC配置 : 对象的创建和依赖注入
    • AOP配置
      • 切面类交给容器管理
      • 通过<aop:config>开启配置
  	<!--对象创建IOC-->
    <bean id="accountService" class="cn.itcast.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <bean id="accountDao" class="cn.itcast.dao.impl.AccountDaoImpl">
        <property name="queryRunner" ref="queryRunner"></property>
        <property name="txManager" ref="txManager"></property>
    </bean>

    <bean id="txManager" class="cn.itcast.utils.TxManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>


    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///heima31"></property>
    </bean>


    <!--AOP配置-->
    <aop:config>
        <!--切入点表达式 : 查找需要增强的方法-->
        <aop:pointcut id="pt" expression="execution(* cn.itcast.service.impl.*.*(..))"/>
        <!--配置切面-->
        <aop:aspect ref="txManager">
            <!--前置通知-->
            <aop:before method="begin" pointcut-ref="pt"></aop:before>
        </aop:aspect>
    </aop:config>
</beans>

4.4基于XML结合注解的AOP事务配置

  • 开启对注解的支持(ioc包扫描,aop的自动代理)
  • 通过IOC注解创建对象和依赖注入
    • 注解:替换自动的对象创建
    • XML:第三方jar包对象
  • 通过AOP注解完成切面配置
    • 声明切面类
    • 通过AOP注解配置通知类型

4.5JdbcTemplate

  • 介绍
    • JdbcTemplate是Spring提供的持久层技术,用于操作数据库,它底层封装了JDBC技术。使用方式和DbUtils基本类似.
  • 核心类:
    • JdbcTemplate 用于执行增删改查的SQL语句 (QueryRunner)
      • 创建过程和QueryRunner一模一样,构造方法传入DataSource
      • 调用JdbcTemplate 中的方法完成数据库操作
    • RowMapper 这是一个接口,主要作用是将数据库返回的记录封装进实体对象(BeanHandler)
  • 核心方法:
    • update() 用来执行增、删、改语句,和QueryRunner相同
    • query() 用来执行查询语句,查询数据列表
    • queryForObject(),查询单一对象
 //创建一个JdbcTemplate对象,用来执行增删改查, 需要给一个数据源   
JdbcTemplate  jdbcTemplate = new JdbcTemplate(dataSource); 

//update方法,用于执行增删改语句     
jdbcTemplate.update("insert into account value(null,?,?)",1,2);

//query或者queryForObject方法,用于执行查询语句 
//query 用于查询多条记录,返回一个集合  queryForObject用于查询一条记录,返回一个实体
jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); jdbcTemplate.queryForObject("select * from account where  aid = ?", new  BeanPropertyRowMapper<Account>(Account.class), 1); 

4.6Spring中的事务管理

  • 根据SpringAOP拓展出来的事务控制功能
  • 事务管理方式
    • 编程式事务
      • 将业务代码和事务代码放在一起书写
      • 耦合性太高,开发中不使用
    • 声明式事务
      • 通过一段配置让程序组装运行,最后达到事务控制的目的.
      • 通过AOP原理实现
  • PlatformTransactionManager这是Spring进行事务管理的一个根接口,我们要使用它的实现类做事务管理器(增强的事务处理的功能)
    • DataSourceTransactionManager :对mybatis和jdbcTemplate操作做事务控制
    • JpaTransactionManager:对JPA操作数据库进行数据库
  • TransactionDefinition
    • 用来做事务定义
    • 面向配置(事务隔离级别,传播行为,是否只读事务,超时时间)
    • 隔离级别
    • mysql支持四种,默认可重复度
    • Oracle支持两种(读已提交和串行化),默认读已提交
    • 传播行为
      • 在多方法嵌套调用时,被调用方法对事务的支持情况
      • Required 加入事务或创建事务
      • supports 加入事务或以非事务形态运行
    • 是否只读事务
      • Read Only : true | false
      • 只读事务只能用于查询方法
    • 超时时长
      • 事务超时时间, 此属性需要底层数据库的支持
      • 使用默认值-1,代表不限制

4.7声明式事务xml版

  • 基于XML的方式完成声明式事务配置:
    • 配置事务管理器交给Spring容器管理(切面类)
    • 配置事务通知
    • 配置事务的AOP
<!--配置Spring的声明式事务-->

    <!--1、事务管理器交给容器管理 transactionManager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入DataSource对象-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--2、配置事务通知 : 配置方法对事务的配置-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--不同方法,对事务的要求配置
                    name : 方法名(可以接受 * 作为通配符)
                    propagation:传播行为
                    read-only: 是否只读事务
                    timeout:超时时间
                    isolation:事务隔离级别
            -->
            <tx:method name="*" propagation="REQUIRED" read-only="false" ></tx:method>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--3、配置事务的AOP : 定位到所有需要添加事务的方法-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pt" expression="execution(* cn.itcast.service.impl.*.*(..))"/>
        <!--事务配置:事务通知-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
    </aop:config>
</beans>

4.8声明式事务注解结合XML版

注解:

  • IOC注解:自定义对象通过注解创建对象和依赖注入
  • 声明式事务注解:替换xml中的事务通知和事务AOP配置
    • 需要开启事务注解的支持 : 事务注解驱动
    • 在需要事务的类或者方法上,使用@Transactional注解配置事务

步骤:

  • 删除xml中的tx:advice和aop:config

  • 添加一个事务注解驱动

    <!--开启事务注解支持: 事务注解驱动-->
    <tx:annotation-driven></tx:annotation-driven>
    
  • 在方法生添加声明式事务的注解

    /**
     * 通过注解配置事务
     * @Transactional:
     *  1、可以配置到类上,表明此类中的所有方法都需要此事务配置
     *  2、也可以配置到方法上,表明此方法需要类似配置
     *  3、即配置到类上也配置到了方法上:就近原则(使用方法的配置为依据)
     */
    @Service
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public class AccountServiceImpl implements AccountService {
    
        //查询全部
        @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
        public List<Account> findAll() {
            return accountDao.findAll();
        }
    
        @Autowired
        private AccountDao accountDao;
    
        //保存
        public void save(Account account) {
            accountDao.save(account);
        }
    }
    

4.9声明式事务纯注解版

  • 通过配置类,替换原有的XML配置文件
  • 包扫描
  • 事务注解驱动
    • @EnableTransactionManagement
  • 第三方的相关对象,创建并交给容器管理
    • @Bean

Day05SpringMVC 壹

5.1介绍

  • mvc 是一种用于设计创建web应用表现层的模式。使用它可以将业务逻辑,数据,页面显示代码分离出来

    • Model(模式):数据模型(封装对象)
    • View(试图):用于展示数据(html,jsp)
    • Controller(控制器):用于程序业务逻辑处理
  • SpringMVC是Spring产品对MVC模式的一种具体实现, 它可以通过一套注解,让一个简单的Java类成为控制器,而无须实现任何接口。

    • 在SpringMVC中,前端控制器通过Servlet实现
    • 在Struts2框架中,前端控制器通过Filter实现

5.2SpringMVC原理

  1. 用户通过浏览器发送请求至DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping
  3. HandlerMapping找到具体的处理器链返回给DispatcherServlet
  4. DispatcherServlet会根据返回的处理器链调用HandlerAdapter
  5. HandlerAdapter经过适配调用具体的Handler(controller)
  6. Controller执行完成返回一个执行结果
  7. HandlerAdapter将Handler的结果ModelAndView对象返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView对象传给ViewReslover
  9. ViewReslover解析后得到具体View,并返回给DispatcherServlet
  10. DispatcherServlet根据View进行视图渲染(即将模型数据填充至视图中)
  11. DispatcherServlet会将渲染后的视图响应给浏览器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dz4DpZj2-1605668946279)(assets\12.png)]

5.3SpringMVC的三大组件

  • 前端控制器
    • SpringMVC的核心组件(DispathcherServlet),协调所有组件的运行
  • 处理器映射器
    • 根据URL请求去寻找对应的处理方法( Controller中的方法)
  • 处理器适配器
    • 真正的去调用处理方法(执行Controller中的方法)
  • 视图解析器
    • 将逻辑视图翻译成物理视图
    • 物理视图:jsp页面的完整路径

5.4RequestMapping

  • RequestMapping用于建立请求URL和处理方法之间的对应关系, 也可以通过它的属性对请求做出各种限制.
  • 可以标注在方法上,也可以标注在类上,标注在类上代表类中的所有方法都可以共用一段URL
    • value(path): 用于限制请求URL(和path作用一样)
    • method:用于限制请求类型(post,get,delete,put)
    • params:用于限制请求参数的条件(如果没有指定参数,抛出异常)

5.5接收请求参数

  • 简单类型

    • 8 基本类型 + 8 基本类型的包装类型 + 字符串
    • 只需要保证前端传递的参数名称跟方法的形参名称一致就好
  • 对象类型

    • 保证前端传递的参数名称跟pojo的属性名称(set方法)一致
  • 数组类型

    • 用于接受多个同名参数传递
    • 需要保证前端传递的参数名称跟方法中的数组形参名称一致
  • 集合类型

    • 将前端传入的数据自动的封装成集合,需要将集合包装到一个对象中
    • 获取集合参数时,要将集合参数包装到一个实体中
  • 日期类型

    • 一些常见的类型, SpringMVC是内置了类型转换器,但是对于一些格式比较灵活的参数(日期 时间),SpringMVC无法完成类型转换.
    • SpringMVC对日期: yyyy/MM/dd。
    • 此时需要自定义类型转换器
      • 自定义一个类型转换器,实现类型转换的方法
      • 将自定义的类型转换注册到SpringMvc的转换服务中,然后再将服务注册到SpringMVC的注解驱动
  • 中文乱码

    • SpringMVC在使用post提交请求时,对于中文参数有乱码问题
    • Spring提供了一个中文乱码过滤器,我们需要进行配置.
    • web.xml配置SpringMVC中中文乱码过滤器
    
    /**
     * 日期类型转化器:
     *  将输入的String字符串,按照自定义的规则转化为date对象
     *  1、实现Converter接口,并提供泛型
     *  2、实现convert方法,进行类型转化
     */
    public class StringToDateConverter implements Converter<String, Date> {
    
        @Override
        public Date convert(String s) {
            Date date = null;
    
            try {
                date = new SimpleDateFormat("yyyy-MM-dd").parse(s);
            }catch (Exception e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    
  • 文件类型

    • 页面:文件上传的三要素
      • form表单的method = post
      • form表单的enctype=“multipart/form-data”
      • from表单中的input的type = file
    • 加入文件上传的包
    • 在SpringMVC的配置文件中添加文件解析器
  • @RequestParam

    • @RequestParam标注在方法参数之前,用于对传入的参数做一些限制, 支持三个属性
      • value:默认属性,用于指定前端传入的参数名称
      • required:用于指定此参数是否必传
      • defaultValue:当参数为非必传参数且前端没有传入参数时,指定一个默认值
  • 接收请求头信息

    • @RequestHeader配置到方法参数上 : 前端控制器自动获取头信息
      • @RequestHeader Map map : 获取所有的请求头
      • @RequestHeader(“cookie”) String cookie : 根据key从所有头信息中获取指定头信息
    • @CookieValue(“key”):
      • 从cookie中根据key获取指定value数据

5.6SpringMVC入门案例

  1. 创建一个Project

  2. 创建一个新的Model 加入坐标

    <!--springmvc-->
    	spring-webmvc
    <!--servlet-->
    	javax.servlet-api
    <!--jsp-->
    	jsp-api
    <!--文件上传的包-->
    	commons-fileupload
    <!-- 添加tomcat7插件 -->
    	tomcat7-maven-plugin
    
  3. 补全目录结构

    • JBLJavaToWeb: 将普通的maven工程,转化为web工程
  4. 加入SpringMVC的配置文件

    • 在resource下创建springmvc.xml作为程序的配置文件

      	<!--1、包扫描-->
          <context:component-scan base-package="cn.itcast"></context:component-scan>
      
          <!--2、配置视图解析器-->
          <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
      
          <!--3、配置SpringMVC的注解驱动-->
          <mvc:annotation-driven></mvc:annotation-driven>
      
  5. 加入web的配置文件

    • web.xml文件

      	<!--1、包扫描-->
          <context:component-scan base-package="cn.itcast"></context:component-scan>
      
          <!--
              2、配置视图解析器
                    将逻辑视图转化为物理视图
                    主要功能,自动的对返回的逻辑试图添加前缀和后缀
                    前缀 + 逻辑视图  + 后缀
          -->
          <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!--配置返回路径的前缀-->
              <property name="prefix" value="/WEB-INF/jsp/"></property>
              <!--后缀-->
              <property name="suffix" value=".jsp"></property>
          </bean>
      
          <!--配置类型转化器 : 将自定义的类型转化器加入到SpringMVC的类型转化器集合中-->
          <bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
              <property name="converters">
                  <set>
                      <bean class="cn.itcast.converter.StringToDateConverter"></bean>
                  </set>
              </property>
          </bean>
      
      
          <!--3、配置SpringMVC的注解驱动
                  相当于配置了增强版的处理器映射器和处理器适配器
          -->
          <mvc:annotation-driven conversion-service="conversionService2"></mvc:annotation-driven>
      
      
          <!--
              文件解析器
                  id:固定值(multipartResolver)
                  其中指定上传文件的大小规则
          -->
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!--文件的大小规则  5M = 1024 * 1024 * 5 -->
              <property name="maxUploadSize" value="5242880"></property>
          </bean>
      
  6. 开启请求页面

    
        <%--
                对于集合中元素赋值
                    集合属性[索引|key]
                对集合中的数据赋值
        --%>
        <form action="${pageContext.request.contextPath}/hello/demo7" method="post">
            第一个User的name:   <input type="text" name="users[0].name"/>
            第一个User的age:     <input type="text" name="users[0].age">
            第二个User的name:   <input type="text" name="users[1].name"/>
            第二个User的age:     <input type="text" name="users[1].age">
    
            <hr>
            map的第1个元素       <input type="text" name="map['1001']"/>
            map的第2个元素       <input type="text" name="map['1002']"/>
            map的第2个元素       <input type="text" name="map['1003']"/>
    
            <input type="submit" value="测试集合类型请求参数">
        </form>
    
    
        <a href="${pageContext.request.contextPath}/hello/demo8?birthday=2020-09-09">测试日期类型请求参数</a>
        <br><br>
    
    
  7. 开发控制器

    /**
     * 入门案例
     *  1、在控制器类上,添加@Controller注解
     *  2、在控制器类中,添加处理请求的方法
     */
    @Controller
    @RequestMapping(value="/hello")
    public class HelloController {
    
    
        /**
         * 入门案例:
         *      此方法,接收请求,数据响应和指定页面的跳转
         *      返回值String
         * @RequestMapping : 指定进入此控制器方法的请求路径
         *      可以配置到类上,配置到方法上,如果配置到类上,相当于配置此类中所有方法的共同一级连接
         *      value(path):
         *          指定当前的请求连接
         *      method:
         *          此方法可以接受的发送请求的方式  get,post
         *
         */
        @RequestMapping(value="/demo")   //hello/demo
        public String demo1() {
            System.out.println("第一个案例,终于执行了,真厉害");
            return "success"; //经过处理器,请求需要转发的页面路径
        }
    
    
        //当前请求路径只能,通过post发送
        @RequestMapping(value="/demo2",method = {RequestMethod.POST})   //hello/demo
        public String demo2() {
            System.out.println("第一个案例,终于执行了,真厉害");
            return "success"; //经过处理器,请求需要转发的页面路径
        }
    
    
      
        /**
         * 请求参数:集合类型参数
         *  1、集合需要封装到对象中:vo
         *  2、方法的参数:对象vo
         */
        @RequestMapping(value="/demo7")   //hello/demo
        public String demo6(Vo vo) {
            System.out.println(vo);
            return "success";
        }
    
    
        /**
         * 请求参数:日期参数
         *  日期:Date对象
         *  请求连接:/hello/demo8?birthday=1990-09-09
         */
        @RequestMapping(value="/demo8")   //hello/demo
        public String demo8(Date birthday) {
            System.out.println(birthday);
            return "success";
        }
    
        /**
         * 请求参数:文件上传
         *  文件上传:字节流
         *      SpringMVC提供对象MultipartFile,通过这个对象描述上传文件
         *          1、配置到方法参数上
         *          2、参数的名称和传递的文件input框中的name一致
         */
        @RequestMapping(value="/demo10")
        public String demo10(MultipartFile uploadFile) throws IOException {
    
            System.out.println(uploadFile.getOriginalFilename()); //文件名称
    
            System.out.println(uploadFile.getSize()); //文件大小
    
            File file = new File(new File("d:/upload"),uploadFile.getOriginalFilename());
    
            //将上传文件中的数据,写入到本地文件中
            uploadFile.transferTo(file);
    
            return "success";
        }
    
    
        /**
         * 在控制器中获取,当前请求的请求头
         *      1、@RequestHeader配置到方法参数上 : 前端控制器自动获取头信息
         *          @RequestHeader Map map : 获取所有的请求头
         *          @RequestHeader("cookie") String cookie : 根据key从所有头信息中获取指定头信息
         *      2、@CookieValue("key"):
         *          从cookie中根据key获取指定value数据
         *
         */
        @RequestMapping(value="/demo12")
        public String demo12(@RequestHeader Map map,
                             @RequestHeader("cookie") String cookie,
                             @CookieValue("JSESSIONID") String sessionId) {
            System.out.println(map);
            System.out.println(cookie);
            System.out.println(sessionId);
            return "success";
        }
    
  8. 开发响应页面

Day06 SpringMVC 贰

6.1请求转发

  • 方式一:简单方式(推荐)
    • 直接返回逻辑视图地址
    • Springmvc通过视图解析器获取完整物理视图进行跳转
  • 方式二:使用forward转发(其次)
    • Springmvc提供的页面转发方式
    • return :“forward:物理视图地址”
  • 方式三:使用servlet原生api(了解)
    • 获取Servlet原生API
      • 将需要的对象通过参数的形式配置到方法上
      • 将需要的对象,通过@Autowired注入到控制器中
    • request.getRequestDispatcher("/路径").forward(request,response);

6.2转发时携带数据

  • 方式一:绑定到request域(推荐)

    • request.setAttribute(“name”,“jack”);
    • ${name}
  • 方式二:绑定到Model对象(了解)

    • 将数据绑定到Model对象上(Model底层通过Request实现)

    • 将Model以参数的形式配置到方法上

    • 调用model的addAttribute方法,将数据存入request

          public String demo3(Model model) throws Exception {
              //request.setAttribute("name", "jack");
              //将数据存入request
              model.addAttribute("name", "rose");
              return "success";
          }
      
  • 方式三:通过ModelAndView返回(官方推荐)

    • ModelAndView : 模型视图对象,通过此对象可以指定返回的视图地址和数据绑定

    • 语法规则:

      • 方法的返回值:ModelAndView

      • 在方法中通过ModelAndView的setViewName指定跳转的页面

      • 在方法中通过ModelAndView的addObject指定需要存入request域中的数据

            public ModelAndView demo4() throws Exception {
                ModelAndView mv  = new ModelAndView();
                mv.setViewName("success"); //参数的写法遵循控制器返回值的写法(逻辑视图地址,forward:物理视图地址)
                mv.addObject("name", "王者荣耀");
                return mv;
            }
        

6.3重定向

发送两次请求(第一次用户行为,第二次是浏览器的自动行为)。响应数据会丢失

  • 方式一:通过redirect关键字配置

    • 返回值:String

    • redirect:/重定向的路径

      public String demo5() throws Exception {
              return "redirect:/hello/demo1";
          }
      
  • 方式二:通过servlet原生API配置

    • 返回值void

      public void demo6(HttpServletResponse response) throws Exception {
              response.sendRedirect(request.getContextPath()+"/success.jsp");
          }
      

6.4释放静态资源

  • SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是 /(缺省),代表除了jsp请求不拦截, 其他的所有请求都会拦截

  • 因此当有静态资源需要加载时,一些静态文件(js html css jpg等等)被拦截后找不到对应的处理器方法来处理, 就会报错

  • 因此需要释放静态资源(不交给SpringMVC处理)

  • 方式一:在Springmvc的配置文件中添加释放静态资源

    
        <!--
            释放静态资源的方式一
                mapping : 请求路径的URL的映射规则
                location: 静态资源的物理目录
                当静态资源请求到SpringMVC的前端控制器时,根据释放资源的配置
                    1、不在查找具体的controller处理
                    2、从location路径中查找匹配的资源
        -->
        <mvc:resources mapping="/js/*" location="/js/"></mvc:resources>
        <mvc:resources mapping="/image/*" location="/image/"></mvc:resources>
        <mvc:resources mapping="/css/*" location="/css/"></mvc:resources>
    
  • 方式二:在Springmvc的配置文件中添加释放静态资源

        <!--
            统一释放所有的静态资源文件
                当SpringMVC处理静态资源时,委托给默认的Servlet处理
                默认Servlet:tomcat中的默认Servlet
        -->
        <mvc:default-servlet-handler></mvc:default-servlet-handler>
    
  • 方式三:修改前端控制器的URL映射规则

    • 修改web.xml中前端控制器的URL映射规则,以特殊字符串结尾的请求会交给前端控制器处理。

    • 需要进入SpringMVC的所有请求,都需要已.do结尾

    • 控制器方法中@RequestMapping不需要做额外的配置,和之前一模一样

      	<!--
      		配置前端控制器
      			DispatcherServlet
      	-->
      	<servlet>
      		<servlet-name>mvc</servlet-name>
      		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      		<!--自动加载Springmvc的配置文件-->
      		<init-param>
      			<param-name>contextConfigLocation</param-name>
      			<param-value>classpath:springmvc.xml</param-value>
      		</init-param>
      	</servlet>
      
      
      	<servlet-mapping>
      		<servlet-name>mvc</servlet-name>
      		<url-pattern>*.do</url-pattern>
      	</servlet-mapping>
      

6.5Ajax+json实现异步交互

在SpringMVC中进行ajax的数据交互,需要通过两个注解简化开发

Springmvc默认用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入jackson的包

  • @RequestBody : 自动的将请求的json字符串,转化为指定java对象(处理请求)

  • @ResponseBody:自动的将java对象,转化为json字符串并相应(处理相应)

        //@ResponseBody
        public @ResponseBody User demo7(@RequestBody User user) throws Exception {
            System.out.println(user);
    
            //调用service完成业务逻辑,模拟出返回对象
            User temp = new User();
            temp.setName("lisi");
            temp.setAge(18);
            return temp;
    

6.6Restful风格

REST是一种软件架构风格, 其强调HTTP请求的URL应当以资源为中心 ( 以后的URL中尽量不要出现动词 )

REST规范了HTTP请求动作(请求方式:post,put),使用四个词语分别表示对资源的CRUD操作:

GET(获取)、POST(新建)、PUT(更新)、DELETE(删除)

Restful :

  • 针对同一个URL,根据不同的请求方式做不一样的业务处理
  • 地址参数 /user/{id}
  • 请求方式:GET(获取),POST(新建),PUT(更新),DELETE(删除)
/**
 * 测试Restful编程风格
 *  1、对同一个URL,根据不同的请求方式,完成不同的业务处理
 *  2、请求URL上存在,地址参数 /user/{id}
 *
 *  /user
 *      保存      :post
 *      查询所有  :get
 *  /user/{id}
 *      根据id查询用户
 *      删除用户
 *      根据id更新用户
 */
@Controller
public class UserController {


    //保存
    @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String saveUser() {
        System.out.println("保存用户");
        return "success";
    }


    //查询所有
    @RequestMapping(value = "/user",method = RequestMethod.GET)
    public String findAll() {
        System.out.println("查询所有用户");
        return "success";
    }


    /**
     * 根据id查询用户
     *  传入地址参数:
     *      请求URL  /user/1
     *      地址参数: {自定义参数名}
     *      在java方法中如何获取地址参数中的数据
     *          @PathVariable : 配置到方法参数上
     *              自动的从地址参数中,根据名称获取参数值
     *              @PathVariable("自定义的参数名")
     *
     */
    //@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    @GetMapping(value="/user/{id}")
    public String findById(
            @PathVariable(value="id") Integer userId) {
        System.out.println("根据id查询用户userId="+userId);
        return "success";
    }

    //根据id更新 :put
   //@RequestMapping(value = "/user/{id}",method = RequestMethod.PUT)
    @PutMapping(value = "/user/{id}")
    public String update(
            @PathVariable(value="id") Integer userId) {
        System.out.println("根据id更新用户userId="+userId);
        return "success";
    }

    //根据id删除 :delete
    @RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
    public String delete(
            @PathVariable(value="id") Integer userId) {
        System.out.println("根据id删除用户userId="+userId);
        return "success";
    }
}

6.7异常处理机制

对于异常的处理一般有两种方式:

一种是当前方法处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合。

一种是当前方法不处理, 出现异常后直接抛给调用者处理。

使用Spring框架后,我们的代码最终是由框架来调用的。异常最终会抛到框架中, 然后由框架指定异常处理器来统一处理异常。

  • 方式一:自定义异常处理器

    • 自定义一个类实现HandlerExceptionResolver接口,将异常处理器交给spring容器管理即可

      @Component
      public class HandlerExcepton  implements HandlerExceptionResolver {
      
          /**
           *  当程序抛出异常时,SpringMVC框架会自动的调用此方法。完成后续异常处理工作
           *      1、跳转到一个错误页面
           *      2、错误信息
           *   返回值:ModelAndView
           *      模型与视图对象
           */
          public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                               HttpServletResponse httpServletResponse, Object o, Exception e) {
              e.printStackTrace();
              ModelAndView mv = new ModelAndView();
              mv.addObject("errorMsg", "对不起,我错了");
              mv.setViewName("forward:/error.jsp"); //和success
              return mv;
          }
      }
      
  • 方式二: @ControllerAdvice

    • 配置java类

    • 定义一个异常处理方法

      • 返回值String (视图)
      • 参数:Model
      @ControllerAdvice //全局异常处理器
      public class HandlerException2 {
      
          /**
           * @ExceptionHandler :
           *  配置此方法可以处理的异常类型
           */
          @ExceptionHandler(value = Exception.class)  //空指针
          public String resolveException(Model model) {
              model.addAttribute("errorMsg", "对不起,我又错了。");
              return "forward:/error.jsp";
          }
      
      

Day07 SpringMVC 叁

7.1拦截器

  • 拦截器是SpringMVC提供的一种技术, 它的功能似于过滤器Filter,它会在进入controller之前,离开controller之后以及页面渲染完毕之后进行拦截

  • 可以单独使用,也可以同时使用多个拦截器形成一条拦截器链,注册的时候注册多个,注册的顺序就代表拦截器执行的顺序。

  • 自定义拦截器

    • 实现HnadlerInterceptor接口
    • 实现其中的三个方法(三个拦截点)
      • preHandle:返回值true(拦截)/false(过滤)
      • postHandle
      • afterCompletion
  • 配置拦截器

    • 在SpringMVC的配置文件中,添加拦截器配置

          <!--配置SpringMVC的拦截器-->
          <mvc:interceptors>
              <!--配置具体的拦截器和拦截器的拦截规则-->
              <mvc:interceptor>
                  <mvc:mapping path="/**"/>
                  <mvc:exclude-mapping path="/hello/demo2"/>
                  <bean class="cn.itcast.interceptors.MyInterceptor01"></bean>
              </mvc:interceptor>
      
              <!--配置具体的拦截器和拦截器的拦截规则-->
              <mvc:interceptor>
                  <mvc:mapping path="/**"/>
                  <mvc:exclude-mapping path="/hello/demo2"/>
                  <bean class="cn.itcast.interceptors.MyInterceptor02"></bean>
              </mvc:interceptor>
          </mvc:interceptors>
      
  • 拦截器和过滤器的区别

    • 过滤器是Servlet 规范中的一部分,任何java web工程都可以使用。
    • 拦截器是SpringMVC框架的,只有使用了SpringMVC框架的工程才能用。
    • 过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。
    • 拦截器只会拦截访问的控制器方法,如果访问的是jsp,js,html,css,image等,它是不拦截的。

7.2SSM整合

  • 借助Spring框架,完成对象的创建和依赖注入。通过Spring的声明式事务完成Service层的事务控制

  • 整合的步骤(初学者):

    • 搭建mybatis的运行环境(保证mybatis可以独立运行)

      • 建立数据库
      • 创建工程
      • 创建实体类
      • 创建Dao接口
      • 创建Dao的映射文件
      • 创建Mybatis的核心配置文件
    • 搭建Spring的运行环境(IOC)

      • 创建service接口
      • 创建Service接口实现类
      • 开启注解支持(包扫描)
      • 自定义的java对象 (注解)
      • 第三方jar包中的java对象(XML)
    • 整合Spring和mybatis

      • Spring管理mybatis的配置对象(datasource,sqlsessionfactory,mapperscannerconfigurer)
      • Spring的事务管理(xml,xml + 注解)
      • service中注入dao的依赖
    • 搭建Springmvc的运行环境

      • springmvc的配置文件(包扫描,视图解析器,mvc的注解驱动,释放静态资源)
      • web.xml的配置文件(前端控制器,字符集编码的过滤器)
      • 编写控制器Controller
      • 准备页面
    • 整合Spring和SpringMVC

      • 父子容器的关系(两种配置方式)
  • 监听器配置Spring容器(父),通过dispatcherServlet配置mvc的容器(子)

    • 通过dispatcherServlet配置所有对象
<servlet>
	<servlet-name>mvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:springmvc.xml,classpath:applicationContext.xml</param-value>
	</init-param>
</servlet>
```

Day08maven高级

8.1依赖

  • 依赖传递
    • 当工程中依赖于A,而A依赖于B,那么工程也依赖于B。
  • 依赖冲突
    • 由于依赖的传递特性,导致依赖jar包的导入混乱,可能导致项目出现问题。
  • 依赖冲突解决方法:
    • 约定俗成
      • 第一声明优先原则
      • 路径近者优先原则
    • 排除依赖
      • 排除依赖配置中某个传递依赖的jar包
    • 锁定版本
      1. 定义公共版本号
      2. 锁定版本
      3. 导入依赖

8.2聚合工程

  • 分模块构建工程,将一个大型项目,按照功能模块拆分。
  • 拆分标准:
    • domain层,dao层,service层,web层
  • maven分模块开发的架构:
    • 父工程
    • 多个子模块
  • 继承
    • 子模块可以继承父工程中定义的所有依赖
  • 聚合
    • 父工程统一管理所有的子模块

8.3聚合工程SSM搭建环境

  • 定义父工程和子模块
    • 创建export_parent父工程
    • 创建export_commons子模块
    • 创建export_domain子模块
    • 创建export_dao子模块
    • 创建export_system_service子模块
    • 创建export_manager_web子模块
  • 在父工程pom文件中定义公共依赖
  • 在子模块中配置模块间的依赖关系
    • 找到export_manager_web的pom文件,配置对service依赖
    • 找到export_system_service的pom文件,配置对dao依赖
    • 找到export_dao的pom文件,配置对domain依赖

8.4整合SSM

  • 实体类:export_domain模块
  • 搭建Mybatis的运行环境
    • 代码需要编写到export_dao模块下
    • dao接口,dao映射文件,mybatis核心配置文件,spring中关于dao的配置文件
  • 搭建SpringIOC的运行环境
    • 代码需要编写export_system_service
    • service接口和实现类,spring对service的配置文件(事务)
  • 整合Spring和Mybatis
    • 整合mybatis的对象交给容器管理
    • service的事务处理
  • 搭建SpringMVC的运行环境
    • 代码书写到export_manager_web
    • web.xml,springmvc.xml,controller,页面
  • 整合Spring和SpringMVC

8.5搭建Mybatis运行环境

  • 创建实体类
    • 属性&getter & setter & toString
  • 创建dao接口
    • findAll
  • 创建映射文件CompanyDao.xml
  • 创建核心配置文件SqlMapConfig.xml(整合后删除)
    • Spring整合mybatis: 将dao层中mybatis的相关对象,交给spring容器管理
      • datasource
      • sqlSessionfactoryBean
      • mapperscannerconfigurer

8.6搭建Spring运行环境

  • service接口
    • findAll
  • service接口实现类
    • findAll
  • spring配置文件
    • Spring配置service的对象管理
    • 事务配置: xml的方式
      • 创建事务管理器
      • 配置事务的通知
      • 配置事务的AOP

8.7整合Spring和mybaits

  • spring的配置方式:

    • xml结合注解
  • 将dao层中mybatis的相关对象,交给spring容器管理

    • export_dao工程的resources目下创建spring/applicationContext-dao.xml
  • 配置Service的事务管理

    • Spring配置service的对象管理
    • 事务配置: xml的方式
      • 创建事务管理器
      • 配置事务的通知
      • 配置事务的AOP

8.8搭建SpringMVC运行环境

  • springmvc的配置文件

    • controller包扫描
    • 视图解析器
    • mvc的注解驱动
  • web.xml配置文件

    • 前端控制器dispatcherServlet
    • 中文乱码的过滤器 CharacterEncodingFilter
  • controller

8.9maven私服

  • 私服的安装和启动和卸载
    • nexus.bat install
    • nexus.bat start
    • nexus.bat uninstall
  • 进入私服的管理后台
    • 浏览器访问 localhost:8081/nexus
    • 用户名/密码:admin/admin123
  • 私服中仓库的种类
    • virtual: 虚拟仓库(失效了,兼容maven1)
    • hosted:宿主仓库(公司内部的所有jar包)
    • proxy:代理仓库(代理从中央仓库下载jar包)
    • group:仓库组(合并以上三种中所有仓库)
  • 将本地的工程打包存入私服
    • 找到maven的setting.xml配置文件,设置私服访问密码
    • 找到带上传工程pom.xml配置文件,设置需要上传到的服务路径
    • 执行maven命令上传:deploy
  • 从私服上下载jar包
    • 在maven安装目录的conf文件中的settings配置文件中配置profile
    • 在maven安装目录的conf文件中的settings配置文件中激活profile

Day09 Git

9.1git概述

svn : 是一个集中式的版本控制工具(管理代码)

git :是分布式的版本控制工具

  • svn:集中式版本控制工具

    • 优点:简单
    • 缺点:单点故障(svn服务器出现故障)
  • git:分布式版本控制工具

  • 每个客户端记录所有代码操作

  • git工作流程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c0yTWofS-1605668946280)(assets\13.png)]

9.2git的本地操作

  • 初始化仓库
  • 添加新文件(暂存区)
  • 提交到本地版本库(本地库)
  • 查看操作记录
  • 还原文件
  • 设置忽略

9.3在线git远程服务器

  • github&gitee(中国码云)
    • 码云的访问地址:https://gitee.com/
  • 项目推送
    • 搭建项目环境
    • 初始化本地版本库
    • 项目代码添加到本地版本库的暂存区
    • 将暂存区内容提交到本地版本库
    • 创建本地版本库和远程版本库的联系
    • 将本地版本库推送到远程版本库中
  • 项目克隆
  • ssh协议(配置)
    • 秘钥生成
    • ssh密钥配置

9.4通过IDEA插件完成git操作

  • 配置git的插件
  • 初始化本地版本库
  • 配置忽略
    • 将.gitignore,添加到工程的根路径下
  • 添加与提交
  • 推送到远程仓库
  • 克隆工程
  • push修改的内容
  • pull拉取最新修改的文件
  • 冲突解决Merge

9.5git的分支

  • 创建分支
  • 切换分支
  • 合并分支代码
  • 将分支中最新修改的内容合并到master上
  • 切换到master操作

9.6搭建私人git服务器

  • 需要搭建到linux系统中
  1. 安装git服务环境准备

    yum -y install curl curl-devel zlib-devel openssl-devel perl cpio expat-devel gettext-devel gcc cc
    yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
    
  2. 下载git-2.5.0.tar.gz

    1. 解压缩 用tar -xzf解压
    2. cd git-2.5.0进入目录中
    3. autoconf 自动配置
    4. ./configure 配置脚本
    5. make 编译
    6. make install 安装
  3. 添加用户

    adduser -r -s /bin/sh -c 'git version control' -d /home/git git
    
  4. 输入两次密码

    passwd git
    
  5. 设置/home/git文件夹操作权限

    mkdir /home/git
    chown git:git /home/git
    
  6. 切换到git用户

    su git
    
  7. 创建git仓库

    cd /home/git
    git --bare init first 
    
    如果不使用“--bare”参数,初始化仓库后,提交master分支时报错。这是由于git默认拒绝了push操作,需要.git/config添加如下代码:
    
    [receive]
    
       denyCurrentBranch = ignore
    
    推荐使用:git --bare init初始化仓库。
    
  8. 连接服务器

    • 私有git服务器搭建完成后就可以向连接github一样连接使用了,但是我们的git服务器并没有配置密钥登录,所以每次连接时需要输入密码。

    • 仓库的url:

      ssh://git@192.168.66.137/home/git/first
      

库下载jar包)

  • group:仓库组(合并以上三种中所有仓库)
  • 将本地的工程打包存入私服
    • 找到maven的setting.xml配置文件,设置私服访问密码
    • 找到带上传工程pom.xml配置文件,设置需要上传到的服务路径
    • 执行maven命令上传:deploy
  • 从私服上下载jar包
    • 在maven安装目录的conf文件中的settings配置文件中配置profile
    • 在maven安装目录的conf文件中的settings配置文件中激活profile

Day09 Git

9.1git概述

svn : 是一个集中式的版本控制工具(管理代码)

git :是分布式的版本控制工具

  • svn:集中式版本控制工具

    • 优点:简单
    • 缺点:单点故障(svn服务器出现故障)
  • git:分布式版本控制工具

  • 每个客户端记录所有代码操作

  • git工作流程

    [外链图片转存中…(img-c0yTWofS-1605668946280)]

9.2git的本地操作

  • 初始化仓库
  • 添加新文件(暂存区)
  • 提交到本地版本库(本地库)
  • 查看操作记录
  • 还原文件
  • 设置忽略

9.3在线git远程服务器

  • github&gitee(中国码云)
    • 码云的访问地址:https://gitee.com/
  • 项目推送
    • 搭建项目环境
    • 初始化本地版本库
    • 项目代码添加到本地版本库的暂存区
    • 将暂存区内容提交到本地版本库
    • 创建本地版本库和远程版本库的联系
    • 将本地版本库推送到远程版本库中
  • 项目克隆
  • ssh协议(配置)
    • 秘钥生成
    • ssh密钥配置

9.4通过IDEA插件完成git操作

  • 配置git的插件
  • 初始化本地版本库
  • 配置忽略
    • 将.gitignore,添加到工程的根路径下
  • 添加与提交
  • 推送到远程仓库
  • 克隆工程
  • push修改的内容
  • pull拉取最新修改的文件
  • 冲突解决Merge

9.5git的分支

  • 创建分支
  • 切换分支
  • 合并分支代码
  • 将分支中最新修改的内容合并到master上
  • 切换到master操作

9.6搭建私人git服务器

  • 需要搭建到linux系统中
  1. 安装git服务环境准备

    yum -y install curl curl-devel zlib-devel openssl-devel perl cpio expat-devel gettext-devel gcc cc
    yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
    
  2. 下载git-2.5.0.tar.gz

    1. 解压缩 用tar -xzf解压
    2. cd git-2.5.0进入目录中
    3. autoconf 自动配置
    4. ./configure 配置脚本
    5. make 编译
    6. make install 安装
  3. 添加用户

    adduser -r -s /bin/sh -c 'git version control' -d /home/git git
    
  4. 输入两次密码

    passwd git
    
  5. 设置/home/git文件夹操作权限

    mkdir /home/git
    chown git:git /home/git
    
  6. 切换到git用户

    su git
    
  7. 创建git仓库

    cd /home/git
    git --bare init first 
    
    如果不使用“--bare”参数,初始化仓库后,提交master分支时报错。这是由于git默认拒绝了push操作,需要.git/config添加如下代码:
    
    [receive]
    
       denyCurrentBranch = ignore
    
    推荐使用:git --bare init初始化仓库。
    
  8. 连接服务器

    • 私有git服务器搭建完成后就可以向连接github一样连接使用了,但是我们的git服务器并没有配置密钥登录,所以每次连接时需要输入密码。

    • 仓库的url:

      ssh://git@192.168.66.137/home/git/first
      
    • 使用TortoiseGit同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值