Week12手写笔记

本周内容

1.mybatis分页查询快速使用

1)导入分页查询的jar包  pageheleper-->5.1.10
2)在mabatis核心配置文件的配置中(位于环境配置的上面),需要引入pagaHelper插件(实现了interceptor的自实现类的全限定名称)--
<plugins interceptor = "com.githelp.pageheleper.PageInterceptor"></plugins>
3)配置分页条件pageHelper.startPage()
	参数一:当前页码
	参数二:每页显示条数
4)调用方法查询数据(获取mapper接口的对象)
5)封装pageInfode的参数
	PageInfo pageinfo = new PageInfo(list);

2.引入Spring–定义用户业务接口以及业务实现–获取

传统MVC情况下,控制器需要不断的去new服务层的对象,耦合性不断增加,会造成oom(内存溢出)的情况,解决此现象的三种方式

2.1 方式一:创建工厂类–通过读取资源文件和反射获取service的实体对象

1)通过配置properties文件,包含服务层的实现类的全限定名称
2)创建一个工厂类
	2.1)读取resource类路径下的资源文件
	2.2)创建属性集合列表
	2.3)将资源文件所在的输入流加载属性集合列表中
	2.4)通过key获取value
	2.5)反射,获取服务层的自实现类的对象
3)测试类中,通过工厂类获取服务层的对象,执行方法

public class BeanFactory {
    //方式一:使用工厂类读取配置文件,加载资源文件
    //构造方法私有化
    private BeanFactory(){};
    public static Object getBean(String Beanname) throws Exception{
        //加载资源文件,获取资源输入流
        InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("Bean.properties");

        //创建属性集合列表
        Properties properties = new Properties();
        //封装属性集合列表
        properties.load(inputStream);
        //通过key值获取value
        String userServiceImpl = properties.getProperty(Beanname);
        Class clazz = Class.forName(userServiceImpl);
        Object obj = clazz.newInstance();

        return obj;

    }

2.2 创建一个工具(工厂)类–>通过解析xml文件和反射的方式获取service的实体对象

1) 导入dom4j这个jar包解析xml文件,版本1.6.1
2)-使用dom4j里面包含的xpath表达式快速定位到某个标签,导包jaxen,版本1.1-beta-6
3)自定义xml文件,beans标签中的子标签bean,
	id属性:是子标签的唯一标识,解析器通过id属性获取到标签对象 
	class属性:业务接口的实现类的全限定名称
4)读取xml文件获取根标签对象,创建解析器对象
	 SAXReader saxReader = new SAXReader();
5)读取路径下的配置文件bean.xml(反射的方法)
	InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.xml");
    Document document = saxReader.read(inputStream) ;
6)获取到元素对象:bean标签对象
利用dom4j里面有xpath表达式:可以快速定位到某个标签-->xpath-->"//不分层级关系选择标签",格式://标签对象[@id='"+id名称+"']
	
	Element beanElement = (Element) document.selectSingleNode("//bean[@id='"+id+"']"); //id就是等会传递userService
7)通过标签对象获取class属性值的内容
	String userServiceImplClass = beanElement.attributeValue("class");
8)反射,通过全限定名称获取字节码文件进而获取实体类对象
9)通过工厂类获取实体类对象,然后调用方法
	

 public static Object getObj(String id) throws Exception {
        //第一步;导包-->log4J->版本1.2.17
        //第二步:导入xpath表达式的jar包-->快速定位到xml文件中某个标签的位置
        //第三步 自定义xml文件.确定访问路径
        //第四步: 创建解析器对象
        SAXReader saxReader = new SAXReader();
        //第五步:读取xml文件,获取资源输入流
        InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.xml");
        Document document = saxReader.read(inputStream);
        //第六步:获取元素对象,"//不分层级关系选择标签"
        Element element = (Element) document.selectSingleNode("//bean[@id='" + id + "']");
        //再通过元素对象获取classs属性值
        String userServiceImplClass = element.attributeValue("class");
        //获取服务层的字节码文件
        Class clazz = Class.forName(userServiceImplClass);
        Object obj = clazz.newInstance();
        return obj;
    }

2.3 通过Spring使用spring来管理bean对象,里面底层还是工厂模式

1)导包 spring-context-版本5.3.12

2)准备Spring的xml文件
	2.1) 添加Spring的表头限制文件,使用本地连接,去掉https中的s
	2.2)添加Spring的容器标签bean
3)创建Spring容器对象applicationContext
	 ClassPathXmlApplicationContext  applicationContext =
                new ClassPathXmlApplicationContext("spring-config.xml") ;
4)获取业务接口类对象
	UserService userService = (UserService) applicationContext.getBean("userService");//id值

 public void testSpring(){

        //创建spring容器对象
        //并解析spring配置文件
        ClassPathXmlApplicationContext  applicationContext =
                new ClassPathXmlApplicationContext("spring-config.xml") ;

        //获取业务接口代理对象
        UserService userService = (UserService) applicationContext.getBean("userService");
        String message = userService.getMessage();
        System.out.println(message);
    }

3.SpringIOC管理Bean对象:spring 的控制反转(依赖注入(DI))

定义:SpringIOC称为控制反转或者反转控制,管理各个层的对象的创建工作,降低程序之间的耦合性;底层是一种工厂模式,解析配置文件,通过spring 容器解析配置文件,还可以DI依赖注入,一个类依赖另一个引用类型,可以通过注入的方式注解注入,(set注入,构造器注入)

1)导包 ->spring-context 5.3.9
2)配置spring的xml文件
	<bean>标签:Spring中的标签
		id属性:是子标签的唯一标识,解析器通过id属性获取到标签对象 
		class属性:业务接口的实现类的全限定名称

3.1 set注入

<set/ property="属性名称" value="赋值">
value是直接给属性名称赋值
ref是关联的意思,关联其他id,也就是实体类中含有其他自定义的类

<bean id="user1" class="com.qf.pojo.User">
        <property name="userId" value="1"></property>
        <property name="userName" value="王桑"></property>
        <property name="userBirthday" value="1996-10-01"></property>
        <property name="userAddress" value="西安市"></property>
    </bean>

3.2 构造器注入

前提条件:实体类必须提供有参构造方法
<constructor name="属性名称" value="赋值"/>
value是直接给属性名称赋值
ref是关联的意思,关联其他id,也就是实体类中含有其他自定义的类

 <bean id="user2" class="com.qf.pojo.User">
        <constructor-arg name="userId" value="1"></constructor-arg>
        <constructor-arg name="userName" value="付桑"></constructor-arg>
        <constructor-arg name="userBirthday" value="1996-01-01"></constructor-arg>
        <constructor-arg name="userAddress" value="西安市"></constructor-arg>

    </bean>

3.3 p标签注入(实际开发中使用较少)

 前提条件:
 1)在当前xml文件的文档声明前面,需要声明一个p的名称空间约束
                  xmlns:p="http://www.springframework.org/schema/p"
 2)必须有set方法/get方法,否则不行!	
<bean>
                    p:属性名称="属性值"
</bean>

 <bean id="user3" class="com.qf.pojo.User"
          p:userId="1" p:userName="田桑" p:userBirthday="1996" p:userAddress="西安市">

    </bean>
    </beans>

3.4 注入复杂数据类型

<property>中分别添加类型标签,属性name表示实体类中的属性名称
1)数组类型	添加<array>标签-->再添加value标签.进行赋值
	  <property name="hobbys">
            <array>
                <value>足球</value>
                <value>健身</value>
                <value>玩游戏</value>
            </array>
        </property>

2)set集合--->添加<set>标签
		<property name="phones">
            <set>
                <value>13335390494</value>
                <value>13689257999</value>
                <value>13888886666</value>
            </set>
        </property>
3)list集合-->添加<list>集合
		 <property name="names">
            <list>
                <value>刘桑</value>
                <value>符桑</value>
                <value>魏桑</value>
            </list>
      </property>
4)map集合-->添加<map>标签--><entry>标签-->key属性和value属性
	 <property name="peple">
            <!--键值对元素-->
            <map>
                <entry key="id" value="001"></entry>
                <entry key="name" value="文章"></entry>
                <entry key="age" value="35"></entry>
                <entry key="address" value="西安市"></entry>
            </map>
        </property>
5)properties属性集合列表--><props>标签--><prop>标签-->属性key
	 	<property name="files">
            <props>
                <prop key="prduct_id">1</prop>
                <prop key="product_name">华为仓颉</prop>
                <prop key="product_desc">为中国人使用中文编程而生</prop>
            </props>
        </property>

4.SpringIOC管理Bean对象的生命周期

1)默认是一个单例,scope不写的话,默认就是(singleton:单例),前提是在一个容器中
2)如果scope的值是property,则表示Spring是多例的,表示在一个spring容器中,可以创建多个对象
3)init-method:初始化方法
4)destroy-method:销毁方法
(1)Spring的生命周期:被Spring容器管理,.
			如果模式是单例模式,获取的实例对象是一致的(前提是在同一个Spring容器中)	
             实例化和初始化就一次,加载当前类的时候就会创建对象;
             当将容器关闭掉,当前类对象被Spring容器销毁
(2)多例 prototype:在一个spring容器,获取的实例对象不一致的(通过id标识符)
           生命周期:对象的创建以及初始化是多次,每一次都需要通过无参构造方法创建对象,获取的实例对象不一致
           实例化和初始化非一次,类加载一次就创建一个实例和初始化
           对象的销毁,并非Spring容器,通过Jvm的垃圾回收器 回收没有更多引用的对象!

5.Servlet-mybatis_Spring整合(xml配置方式)

mybatis和Spring整合的时候,就不需要mybatis的核心xml了
操作步骤:
1)导包
	spring和mybatis的整合包-->mybatis提供的-->mybatis-spring,版本2.0.6
	spring提供的连接池jdbc的jar包,spring-jdbc.jar 版本5.2.5.RELEASE
2)在spring的xml中,进行整个,管理业务层,注入业务层信息--->服务层中不需要new对象,加入自定义持久层类型属性,提供set/get方法
3)在spring.xml文件中对服务层进行bean管理,set注入服务层属性
4)失去了持久层的核心配置文件,现在需要交给Spring代理,需要让Spring识别sqlSessionFactory,sqlsessionFactory需要加载映射文件,并且扫描持久层的接口
5)注入sqlsessionFactory需要加载映射文件
	//mybatis和spring整合.管理sqlsessionFactory,提供了一个类:
 						//org.mybatis.spring.SqlSessionFactoryBea
 	这个类的属性有关联数据源,实名包扫描,加载映射文件
6)连接数据源
	连接spring自带的数据池
	

<?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">
	//-进行spring和mybatis的整合,管理业务层以及持久层-->
	//   set注入进行bean管理-->
<bean id="shopService" class="com.qf.service.impl.ShopServiceImpl">
    <property name="shopMapper" ref="shopMapper"></property>
</bean>
    //  需要让spring识别sqlsessionFactory  -->
    // private String sqlSessionFactoryBeanName:内置属性 指定的SqlSessionFactory,这个id必须叫mapperScannerConfigurer-->
   <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        //   private String sqlSessionFactoryBeanName:内置属性 指定的SqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
       // 告知spring扫描持久层的mapper接口的内置属性
        		// private String basePackage;相当于扫描持久层-->
        <property name="basePackage" value="com.qf.mapper"></property>
    </bean>

		// mybatis和spring整合.管理sqlsessionFactory,提供了一个类:
 				//org.mybatis.spring.SqlSessionFactoryBean
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
			//   关联数据源-->
        <property name="dataSource" ref="dataSource"></property>
				//    实体类的别名包扫描-->
			//	     内置属性:private String typeAliasesPackage set方法注入进去-->
        <property name="typeAliasesPackage" value="com.qf.pojo"></property>
						//	    配置映射文件的路径加载  扫描映射文件-->
						//       内置属性:private Resource[] mapperLocations;
           //     set方法注入,路径必须是类路径下	value="classpath:/*Mapper.xml-->

        <property name="mapperLocations" value="classpath:com/qf/mapper/*Mapper.xml"></property>
    </bean>
    <!--连接spring自带的数据池-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!--        加载数据源信息-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306//myee_2113"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
        </beans>	

6.Spring常用的几个注解

6.1 创建对象的注解

spring提供了很多的注解
(1)一般创建对象的三个注解
1)关于对象创建的注解	@component:这个注解一般作用在类上,标记在谁上,就创建谁的对象,表示将类的创建交给spring容器管理,代替<bean id="xx" class="xxx">,如果不给类名,默认给当前类的类型(class文件)创建对象
使用:在 xml中添加扫描注解的头部文件和本地地址----通用
2)@Service--在业务层类上使用
3)@controller--在控制器层
4)@Repository---在数据访问层

6.2 注入的注解

(1)@Autowired:自动按照类型注入,前提是当前类型是唯一的,如果持久层有多个实现类,则不能使用
(2)@Qualifier:要结合autowired使用,通过唯一的标识注入,也就是当autowired不能使用时,在创建对象注解给上标识,在自动注入时,增加Qualifier("持久层的标识")
(3)@Resource(name="唯一的标识id"):单独使用,就是类似于bean标签中的唯一标签id

6.3 生命周期的注解

(1)@PostConstruct:代替了之前<bean init-method = "初始化方法名">
(2)@preDestroy:代替了之前的<bean detroy-method="销毁的方法名">
(3)@Scope(单例(默认)还是多例):

7.将Spring-mybatis-servlet整合xml优化,加入相关注解

注意:因为使用了注解方式,在servlet中,获取服务层的对象时,传递参数需要变为类名.class
	shopService = (ShopService) classPathXmlApplicationContext.getBean(ShopServiceImpl.class);
在使用注解时,需要在spring的xml文件的表头文件中,加入 xmlns:context="http://www.springframework.org/schema/context"限定和本地地址
  http://www.springframework.org/schema/context
  http=://www.springframework.org/schema/context/spring-context.xsd
  
  在xml文件中开启注解即可
  		<!--开启spring的包扫描,扫描com.qf下面的包下单有关的注解-->
  		 <context:component-scan base-package="com.qf"/>


		<!--    set注入进行bean管理-->
    <context:component-scan base-package="com.qf"></context:component-scan>
    //代替了bean标签的定位
<!--<bean id="shopService" class="com.qf.service.impl.ShopServiceImpl">-->
<!--    <property name="shopMapper" ref="shopMapper"></property>-->
<!--</bean>-->

7,1 ,使用德鲁伊连接池代替spring连接池

(1)导入外部资源文件-->jdbc.properties
	<context:property-placeholder location="classpath:jdbc.properties"/>
(2)连接数据源
	 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

8.SpringAOP–横向切面技术

8.1 SpringAOP的定义

Aspect Oriented Programmar是一种面向切面编程,基于OOP完成(封装,继承,多态),他融合了jdk动态代理有一集cglib动态代理:不仅基于接口,也可以基于类来实现代理,但是默认使用jdk动态代理;

8.2 Aop的主要作用

(1)对逻辑叶落方法和非业务方法,进行分离(RUD--对各个方法进行增强)
(2)开闭原则:对修改关闭,对扩展开发!不修改先用代码,只需要改动Spring相关的配置文件即可
(3)降低了程序之间的耦合,后期维护更为方便

8.2 AOP开发术语

(1)连接点(joinpoint):当前业务的方法(增删查改
(2)切点(pointcurt):通过SpringAOP的配置切入到连接点(横向切面)
	切点表达式--找到我们对应的业务层中的所有方法,都可以进行增强
(3)通知(advice):需要告知Spring执行什么通知进行切入
	前置通知 BeforeHandleAdvice--->实现MethodBeforeAdvice接口
	后置通知 AfterReturningAdvice-->实现AfterReturningAdvice接口
	异常通知(thorwAdvice)出现问题了的通知类型-->实现了ThrowsAdvice接口
	最终通知(afterAdvice)方法
	环绕通知(methodInterceptor):将上面的通知融合到一块去--->实现MethodInterceptor接口
(4)织入:通过通知的类型,切入到连接点,创建代理对象的过程
(5)代理(proxy):织入之后,产生的结果(代理对象)
(6)切面(Aspect):切入到指定的连接点(自定义一个方法),将所有的通知放在一起,可以用多个切点形成一个切面

8.3 cg_lib动态代理

定义:属于动态代理的一种,基于子实现类实现(基于类实现,不需要接口)
(1)导包-->导入ch_lib的jar包,版本3.3.0
(2)创建增强类-->Enhance,底层要实现一个接口net.sf.cglib.proxy.InvocationHandler
(3)给增强类对象进行赋值,参数为真是角色的字节码文件
(4)设置回调对象:代表当前类对象的地址值引用
(5)创建当前角色对象
		

public class CglibHandler implements InvocationHandler {

    //成员位置声明真实角色的变量 Object target
    private Object target ;
    //定义一个方法,直接在这个方法中产地代理角色
    public Object bindObject(Object target){
        //固定的写法
        this.target = target ;
        //cglib使用步骤
        //1)创建增强类(核心类)
        Enhancer enhancer = new Enhancer() ;
        //2)给Enhancer增强类对象,进行赋值
        //public void setSuperclass(Class superclass):参数:真实角色的字节码文件对象
        enhancer.setSuperclass(target.getClass());
        //3)设置回调对象:代表当前类对象的地址值引用 this
        enhancer.setCallback(this) ;
        //4)创建当前角色对象---
        Object obj = enhancer.create();
        return  obj ;
    }

    //底层方法调用:
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        //method:自己的业务方法---需要通过反射的方式调用 add/getName()
        System.out.println("执行业务方法之前,校验权限");
        Object obj = method.invoke(target, objects);//真实角色对象以及实际参数
        System.out.println("执行业务方法之后,产生日志文件");
        return obj;  //和jdk动态代理一致的
    }
}

测试类
public void test3(){
        CglibHandler cglibHandler = new CglibHandler();
        //创建子实现类对象
        UserServiceImpl userServiceimpl = new UserServiceImpl();
        //创建基于代理类的增强类对象

        //调用增加的方法,返回子实现类对象
        UserServiceImpl userService = (UserServiceImpl) cglibHandler.bindObject(userServiceimpl);
        //调用方法
        userService.add();
    }

8.5 SpringAOP的操作步骤(xml配置)

(1)导入Spring的aspect的jar包,版本5.2.5.RELEASE
(2)添加aop的头部约束文件和本地库
	xmlns:aop="http://www.springframework.org/schema/aop"
	http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
(3)自定义一个类,实现一个处理器-->springAOP提供的,可以作为前置通知,在执行业务之前,先进行前置通知的执行,继承自AOP中的接口MethodBeforeAdvice
(4)在xml中配置前置通知
	<bean id="beforeHandler" class="com.qf.spring_aop_proxy.BeforeHandler"></bean>
(5)前置通知通过切点表达式切入到连接点中,进行业务方法增强
	<aop:advisor advice-ref="beforeHandler" pointcut="execution(* *.*.service.impl.*.*(..))"></aop:advisor>
	<aop:advisor>---通知切入标签
		属性 advice-ref:关联通知类型
			pointcut:切点
        	 execution:切点表达式
	 pointcut="execution(* *.*.service.impl.*.*(..))" 切入到业务层方法中了
                    第一个* 是默认的
                    第二个* 就是com
                    第三个* 就是qf
                    第四个*:一般不写*,直接进入到业务层包名  service
                    第五个*:一把不写*,impl 包名
                    第六个*: 代表当前impl包下的类名 (类名不用给出来) 直接写*
                    第七个*:代表这个类下面的方法名,如果业务方法很多,直接写*
                    (..):不明确方法的参数

8.5.1 环绕通知的配置

配置方式是一样的
	<bean id="myAround" class="com.qf.spring_aop_proxy.MyAround"></bean>//配置通知管理
	<aop:advisor advice-ref="myAround"
                     pointcut="execution(* *.*.service.impl.*.*(..))"></aop:advisor>//配置切点

//通知类
public class MyAround implements MethodInterceptor {
    //声明object变量
    Object obj =null;
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        try{
            //前置通知的方法
            System.out.println("在添加用户之前,需要进行权限校验");
            //调用业务数据,返回的是真实角色对象
           obj = invocation.proceed();
           //后置通知的方法
            System.out.println("在添加用户之后,需要加载日志");
            return obj;
        }catch (Exception e){
            //异常通知
            System.out.println("出异常了");
        }finally {
        //最终通知
            System.out.println("最后的通知...");
        }

        return null;
    }
}

8.6 配置切面(由切点和通知组成)(xml配置方式)

(1)自定义一个切面类,将所有的增强类通过方法的形式定义出来
(2)在xml中配置切面
<aop:config>
	<aop:aspect ref="切面类">
		子标签:配置切点<aop:pointcut>--->expression("execution(切点表达式)")
			  配置通知<aop:before>,<aop:after-returning><aop:after-throwing><aop:around>
	</aop:aspect>
					属性:method="通知方法名" 
						 pointcut-ref="切点的id标识"
	</aop:config>


//切面类
package com.qf.spring_aspect;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
    //将各类通知定义为方法即可
   /* public void before(){
        System.out.println("执行方法前");
    }
    public void after(){
        System.out.println("执行方法后");
    }
    public void throwing(){
        System.out.println("这是异常通知");
    }*/
   //参数:ProceedingJoinPoint:执行连接点的接口:执行的是业务层方法...
    public Object myRound(ProceedingJoinPoint joinPoint){
        Object target = null ;//产生的代理角色
        try{
            //要将其他通知关联进来
            //before(); //前置通知
            System.out.println("权限校验...");
            //执行业务方法
            target = joinPoint.proceed() ;//执行业务方法
            // afterReturning(); //后置通知
            System.out.println("产生日志");
            return target ;
        } catch (Throwable throwable) {
            throwable.printStackTrace();//打印了
            // afterThrwoing(); //异常通知
            System.out.println("异常打印...");
        } finally {
            System.out.println("after最终.. 通知,");
        }
        return  null ;
    }

}

//xml配置
	<bean id="myAspect" class="com.qf.spring_aspect.MyAspect"></bean>
<!--配置切面-->
<aop:config>
<!--    组装切面,关联到切面的通知类-->
    <aop:aspect  ref="myAspect">
<!--      将切点抽取出来  -->
        <aop:pointcut id="mycut" expression="execution(* *.*.service.impl.*.*(..))"/>
<!--        配置通知-->
<!--        <aop:before method="before" pointcut-ref="mycut"></aop:before>-->
<!--        <aop:after-returning method="after" pointcut-ref="mycut"></aop:after-returning>-->
<!--        <aop:after-throwing method="throwing" pointcut-ref="mycut"></aop:after-throwing>-->
        	<aop:around method="myRound" pointcut-ref="mycut"></aop:around>
    </aop:aspect>
</aop:config>

8.7 springAOP的注解配置方式(还是aop的jar包)

(1)导包
	spring-aspects,版本5.2.5.RELEASE
(2)添加头文件约束和本地库
	xmlns:aop="http://www.springframework.org/schema/aop"
	http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
(3)@Aspect:标记切面的自定义类,标记为切面类
	就相当于刚才在xml文件配置的 <aop:config><aop:aspect>  </aop:aspect></aop-config>
(4)定义创建对象的注解,通知spring管理切面@component
		因为自动注入是,相当于定位到切面类创建对象
(5)再切面类中再创建一个方法,定义注解@pointcut(切面表达式),这个方法就是切点表达式
		相当于<aop:pointcut id="mycut" expression="execution(* *.*.service.impl.*.*(..))"/>
(6)在各个通知上配置注解-
		-@Before("pt1()")
		@AfterReturning("pt1()")
		@AfterThrowing("pt1()")
		 @Around("pt1()")

(7)在xml中,开启包扫描
			<context:component-scan base-package="com.qf.spring_aspect"/>
(8)开启SpringAOP的注解.开启切面模式自动代理
	 <aop:aspectj-autoproxy/>
	


	/注解的方式:标记当前这个MyAspect这个类是一个切面类
@Aspect //就相当于刚才在xml文件配置的 <aop:config><aop:aspect>  </aop:aspect></aop-config>
	//要spring将切面进行管理
@Component
public class MyAspect {
    // 自定义一个方法:
    @Pointcut("execution("* *.*.service.impl.*.*(..)"))
    public void pt1(){} //pt1就是切点表达式
     //参数:ProceedingJoinPoint:执行的连接点的接口:执行的是业务层方法...
    @Around("pt1()")
    public Object myRound(ProceedingJoinPoint joinPoint){
        Object target = null ;//产生的代理角色
        try{
            //要将其他通知关联进来
            //before(); //前置通知
            System.out.println("权限校验...");
            //执行业务方法
            target = joinPoint.proceed() ;//执行业务方法
           // afterReturning(); //后置通知
            System.out.println("产生日志");
            return target ;
        } catch (Throwable throwable) {
            throwable.printStackTrace();//打印了
           // afterThrwoing(); //异常通知
            System.out.println("异常打印...");
        } finally {
            System.out.println("after最终.. 通知,");
        }
        return  null ;
    }
}

xml文件注解配置
//开启注解包扫描
	<context:component-scan base-package="com.qf.spring_aspect"/>
	//spring管理服务层
	<bean id="userService" class="com.qf.service.impl.UserServiceImpl"></bean>
	//开启aop自动代理,开启aop注解
	 <aop:aspectj-autoproxy/>

8.8 Spring和Junit整合

(1)导包-->spring-junit ,版本5.3.9
(2)junit注解:现在启动器使用的是Spring-test里面的启动器,
在测试类加入注解@RunWith(SpringRunner.class)
	//加载类路径下的spring的核心配置文件
@contextconfiguration(classpath:spring_config.xml)//读取文件,加载spring所有注解

9.Spring管理事务–>提供Spring-tx.jar(事务管理器)

spring控制事务
(1)导包 spring-tx,jar ,版本5.2.5 release存在事务管理器
(2)xml配置--添加头部约束和地址
(3)引入事务管理器,在spring-jdbc的事务管理器中连接数据源	
(4)管理数据源
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--        连接数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
(5)事务控制-->配置事务通知
	//id:给事务起的名字 transaction-manager:连接事务的数据源
	<tx:advice id="tx-update" transaction-manager="tx">
		配置事务的属性
		<tx:attribute>
		<tx:method name="控制事务的方法名" propagetion="事务的传播行为,REQUIED:默认的,针对增删改必须使用事务控制""SUPPORTS:针对查询语句" read-only="true":代表只读 rollback-for="Exception":如果出现异常,直接回滚>
		</tx:attribute>
	</tx:advice>
(6)让springAOP控制事务管理
<aop:config>
	<aop:advisor advice-ref="事务id" pointcut="切点表达式
</aop:config>

9.1 事务管理器的注解形式

(1)导包 spring-tx,jar ,版本5.2.5 release存在事务管理器
(2)xml配置--添加头部约束和地址
(3)引入事务管理器
(4)管理数据源
(5)在需要加入事务管理的类上或者方法上加上@trasactional(propagation=Propagation.REQUIED)
(6)在xml中开启事务注解,并且关联事务管理器
 <tx:annotation-driven transaction-manager="tx"></tx:annotation-driven>

10.SpringMVC介绍以及它的执行流程

定义:是spring框架提供的一个产品,可以快速构建web应用程序,针对mvc架构可以融合

11.SpringMVC的使用

(1)导包-->引入spring-webmvc.jar,版本5.3.9
		并且大war包,<packaging>war</packaging>
(2) 编写控制器(DispatcherServlet:前端控制器(中央处理器)):springmvc本质就是一个servlet
	
(3)需要在web.xml文件去配置springmvc--前端控制器-->spring的监听器,spring-webmvc提供的, 项目一启动,通过ContextLoaderListener加载类路径下的springmvc.xml
		前提:添加头部约束文件
	3.1)配置全局参数
		<context-param>
        <param-name>contextConfigLocation</param-name>
        <!--加载springmvc.xml-->
        <param-value>classpath:springmvc.xml</param-value>-->监听的类路径下springmvc.xml
    </context-param>
	3.2)serlvet基本配置
	<servlet>
        <servlet-name>dispatcherServlet</servlet-name>--名字自己起
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>-->不需要变动
            <param-value/>
        </init-param>
        //配置加载时机,当项目已启动,就直接创建我们的前端控制器 DispatcherServlet
        <load-on-startup>1</load-on-startup>
    </servlet>
    3.3)servlet的映射配置
    	<servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>-->映射到springmvc.xml中
        	// 前端控制器 处理所有的请求
        <url-pattern>/</url-pattern> /代表全部
    </servlet-mapping>
(4)配置springmvc.xml.加入aop和mvc的头文件约束和地址
	(4.1) 扫描spring相关的注解
		 <context:component-scan base-package="com.qf.controller"/>
	(4.2)启动springmvc的注解,自动加载控制器里面处理器映射器 /处理器适配器
		 <mvc:annotation-driven/>
	(4.3)配置springmvc视图解析器,set方法注入两个属性,private String prefix = ""; 前缀
												private String suffix = "";  后缀
	<mvc:view-resolvers>
		 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
			<property name="prefix" value="/WEB-INF/jsp/"></property>
             <property name="suffix" value=".jsp"></property>
          </bean>
     </mvc:view-resolvers>
(5)编写控制器,@controller标记为表现层--称为表现层-->需要调用service层-->需要调用mapper/dao持久层
(6)在方法上加上注解@RequestMapping("/别名")--相当于自定义servlet中的方法


web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--    开始配置前端控制器-->
<!--    配置spring的监听器,只要项目一启动,通过ContextLoaderListener加载类路径下的springmvc.xml-->

<!--    引入监听器contextConfigLocation-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
<!--开始配置全局参数,spring的监听器-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
<!--        初始化springioc容器,扫描spring的xml文件,地址是类路径下的spring.xml-->
        <param-value>classpath:springmvc.xml</param-value>
    </context-param>

<!--    配置servlet,就是前端控制器DispatcherServlet,名称必须和映射名称一致-->
    <servlet>
        <servlet-name>DispacteryServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--   初始化参数-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value/>
        </init-param>
<!--        还要web容器已启动,就创建前端控制器的对象-->
        <load-on-startup>1</load-on-startup>
    </servlet>
<!--    配置servlet的一个映射路径-->
    <servlet-mapping>
        <servlet-name>DispacteryServlet</servlet-name>
<!--        跟servlet配置一样,映射路径需要指定到spring管理的具体路径中,/代表所有-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>


springmvc.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--    springMVC是spring的后续产品.会额外提供其他注解-->
<!--    开启spring的注解包扫描,创建对象-->
    <context:component-scan base-package="com.qf.controller"/>
<!--    开启springmvc的注解,自动加载前端控制器里边的映射器,适配器-->
    <mvc:annotation-driven/>
<!--    配置试图解析器-->
    <mvc:view-resolvers>
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--            注入配置前缀和后缀-->
            <property name="prefix" value="/WEB-INF/jsp/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </mvc:view-resolvers>

</beans>

11.1 SpringMVC 的三大组件

前端控制器(中央处理器):dispactcherServlet

处理器映射器:RequestMappingHandlerMapping

处理器适配器:RequestMappingHandler

11.2 SpringMVC怎么传参

方式一:路径携带参数请求(当前方法的形参的参数名称需要和地址栏上携带的参数名称一致)
	解析日期格式的注解@DateTimeFormat(pattern="yyyy-mm-dd")
	通过定义一个方法,带上形式参数,默认获取参数
方式二:路径携带参数请求
	方法形参是HttpServletRequest对象,利用ServletAPI解决
方式三:前端路径携带参数,但是后端方法中的形参和携带的方法名不一致的情况
	解决:使用springmvc提供的注解@RequestParam(参数绑定)
	在每一个新参前面进行参数绑定
	@RequestParam("路径参数名称") 形式参数
方式四:定义实体类pojo,封装实体类
	在方法中直接将实体类做为形式参数,但是实体类的属性名称必须和路径携带参数名称一致
方式五:路径直接"传递参数"--?url
在方法的注解上RequestMappings追加数据("/{值1}/{值2}/{值3}/.....")
	使用springmvc注解@pathVariable Integet id-->类似参数绑定
	地址栏带参:http://localhost:8080/springmvc_param_war/requestparam/third/1/%E5%88%98%E5%AE%9D%E5%AF%BF/123456
方法六:如果实体是一个集合(属于路径携带参数)(tomcat的版本不能太高,否则400错误)
http://localhost:8080/SpringMVC_02_war/requestData/sevenReq?userList[0].id=1&userList[0].username=xx &userList[0].address=xxx&userList[0].time=xx
	400错误解决:修改tomcat的server.xml配置文件配置文件
		给port="8080" 后面配置三个属性,
			urlEcnoding="utf-8"
			relaxedPathChars="|{}[],%"
  			relaxedQueryChars="|{}[],%"
								
	
方式7:前端提交方式是一个表单
	方法的形式参数为数组的形式参数,并且数组的变量名必须和表单的选项的name属性一致
方式8:当前台提交的数据是json形式,后台需要将他封装到实体类中
	(1)导包,springmvc可以解析json数据
		jackjson的三个包
	(2)必须在当前形式参数上加入注解@RequestBody
	(3)当前提交方式必须是POST
	(4)发送的json数据的属性名称必须和实体类保持一致

11.3 SpringMVC响应数据的方式

第一种方式:传统方式,通过servlet-api(HttpRequest)完成
	request.setAttriibute("名称","内容")
第二种方式:返回还是string,方法形参是Model model-->类似于域对象
	model.addAtrribute("名称",Object);在model中存贮数据
第三种方式:返回值是字符串,方法形参是Session
	session.setAtrribute();
第四种方式:返回值是modelandview:试图模型
	(1)创建试图模型对象
	ModelAndView modelAndView = new ModelAndView() ;
	(2)设置模型数据// addObject(String attributeName,  Object attributeValue)
		modelAndView.addObject("money",13999) ;
	(3)设置返回视图---->交给前端控制器DispatcherServlet ---借助于它来请求转发
    	//public void setViewName( String viewName) :参数为视图的路径
    	modelAndView.setViewName("success")
    return ModelAndView;
第五种方式:返回数据是json数据,需要导入三个jar包,实现json的前后端交互
		jackson-annotations-2.4.0.jar、jackson-core-2.4.2.jar、jackson-databind-2.4.2.jar		
	(1)jackson提供的springmvc注解@ResponseBody:将现在的实体类对象转换成json,在方法名上添加@ResponseBody,即可返回值是一个json格式
	(2)如果前台发送的数据也是json格式,则在形式参数前面加入注解@ResponseBody

11.3.1 过滤器的使用

(1)在web.xml文件中配置过滤器,解决全局中文乱码
	   <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--初始化参数-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
   (2)在springmvc中开启过滤器,释放html,css等静态资源,解决全局中文乱码
   		<mvc:default-servlet-handler/>

11.4 SpringMVC提供拦截器(Interceptor)

过滤器的配置:注解,在springmvc中开启过滤器注解<mvc:default-servlet-handler/>:释放html,css等静态资源
	
拦截器的使用步骤:
	(1)自定义一个类实现HandlerInterceptor,重写Prehandler,posthandler,aftercompletion方法
	(2)定义拦截业务-->preHandler
        	定义拦截的业务方法,return-->true则表示放行,false则表示拦截
	(3)定义posthandler,表示控制器执行相关的方法之后执行的
    (4)定义aftercompletion,表示在执行完posthandler之后执行的,进行渲染试视图
	
注解形式:在springmvc中加入注解
  <!--告知springmvc拦截器信息-->
    <mvc:interceptors>
        <!--可以 配置多个拦截器-->
        <mvc:interceptor  >
            <!--拦截路径-->
            <!--拦截所有-->
           <!-- <mvc:mapping path="/**"/>-->
            <!--拦截指定的路径-->
            <mvc:mapping path="/student/findAll"/>
            <!--放行执行的路径-->
            <mvc:exclude-mapping path="/admin/login"></mvc:exclude-mapping>

            <!--管理自定义的拦截器-->
            <bean class="com.qf.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>    
    </mvc:interceptors>

11.5 SpringMVC图片上传(本地上传,云端上传(七牛云存储))

1)准备前端的上传组件 input type="file"--->上传文件的表单标签,表单必须是post提交,并且必须带上表单中的重点属性enctype="multipart/form-data",这样路径就可以携带文件的名称
	<form action="/SpringMVC_03_war/QiNiuYunpload/img" method="post" enctype="multipart/form-data">
    上传图片:<input type="file" name="file"/><br/>  <%--会携带file参数到后台地址上--%>
    <input  type="submit" value="上传" />
</form>	
2)导入jar包:commons-io.jar和upload-file.jar,创建一个controlle,实现本地上传的业务
3)在springmvc.xml中配置图片的上传组件
	 <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

        <property name="maxUploadSize" value="10485760"></property>--->最大上传内存大小,按毫秒值计算
    </bean>
	
	


 public String uploadImg(@RequestParam("file") MultipartFile multipartFile, HttpSession session) throws IOException {//这个里面multipartFile 绑定参数需要和前台提交的图片的name属性一致
        //springmvc--提供接口 里面的方法:
        //InputStream getInputStream() throws IOException;
        //获取图片源文件  (文件包括后缀)
        String originalFilename = multipartFile.getOriginalFilename();
        System.out.println(originalFilename); //高圆圆.jpg

        //图片是不同的,但是图片名称一致的,下一次再次去上传,会上第一次图片覆盖
        //使用UUID工具类产生唯一的图片的名称
        String fileName = UUID.randomUUID().toString();

        //通过原生文件获取它的后置.jpg 的jpg
        //FilenameUtils工具类 --commons-io,获取原始文件名称的后缀名称
        //参数:原始文件
        String ext = FilenameUtils.getExtension(originalFilename);


        //组装一个新的文件
        String newFileName = fileName+"."+ext ;

        //将上传的文件存储到当前项目下的upload_file中

        //四个域对象:前三个都可以获取全局对象ServletContext,也就是当前项目的绝对路径
        String realPath = session.getServletContext().getRealPath("/upload_file");
        System.out.println(realPath);

        //上传操作
        //MultipartFile有个上传的方法transferTo:将文件上传到指定路径中
        multipartFile.transferTo(new File(realPath+"\\"+newFileName));//上传的路径

        return "upload_ok" ;

    }

11.5.1 七牛云上传

(1)自定义一个工具类,将本地磁盘上的图片存储七牛云(服务器),返回值是使用生成的域名+唯一的图片的名称
(2)将七牛云文件上传-->通过数据流上传-->工具类复制下来,并且修改自己的秘钥
(3)自定义一个controller,调用工具类,实现从本地仓库的图片上传到七牛云



public class UploadUtils {

    private UploadUtils(){}

    /*
    * 上传 方法 将本地磁盘上的图片存储七牛云(服务器)
    *
    * 返回:使用生成的域名+唯一的图片的名称
    * */
    public static String uploadFile(MultipartFile multipartFile){ //使用数据流 ---将图片上传

        //使用七牛云---sdk完成 上传 ---查看七牛云开发文档

        //数据流的上传的代码--(七牛云的)

        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0()); //huadong() //华东区域 (云存储的区域地址(服务器))
//...其他参数参考类注释
        //上传管理器,将Configuration进行解析
        UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传

        //访问到七牛云的密钥(个人中心自己的)
        String accessKey = "yGotxUejuad1rVeY4Cc7kkgZ5HTQwSU1Yqdc90II"; //访问密钥
        String secretKey = "kofIM0oF8UtBkN398ZUEmOymJh9up3-9bi-EtO6F";//安全密钥

        //等会需要将本地图片上传到七牛云指定个存储空间,七牛云的存储空间名称
        String bucket = "javaee-2113-upload";
//默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = null;
        try {


            //身份认证:将上面的配置好的访问密钥,和安全密钥封装到Auth
            Auth auth = Auth.create(accessKey, secretKey);
            //生成upToke="令牌字符串" 里面有空间名称以及accessKey, secretKey都在里面
            String upToken = auth.uploadToken(bucket); //使用认证将指定的图片存储空间名称上


                //使用uploadManager上传管理器上传
                // public Response put(InputStream stream, String key, String token, StringMap params, String mime)
                //参数1:上传文件的字节流--->使用自己文件的字节流
                //参数2:哈希字符串
                //参数3:upToken 密钥+空间名称 字符串
                //参数4:其他参数
                //参数5:文件类型
            Response response = null;

                response = uploadManager.put(multipartFile.getInputStream(),key,upToken,null, null);


            //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);//文件名

            //返回字符串
            //http://r9c3yzgt4.hd-bkt.clouddn.com/ 外链 +文件名
            return "http://r9c3yzgt4.hd-bkt.clouddn.com/"+putRet.hash ;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null ;

    }
}

@Controller
@RequestMapping("/QiNiuYunpload")
public class QiNiuYunUploadController {

    @RequestMapping("/img")
    public String uloadFile(@RequestParam("file") MultipartFile multipartFile, Model model){


        //使用自定义工具类,用到了七牛云的sdk,获取到七牛云的存储地址-->全限定名称
        String uploadFile = UploadUtils.uploadFile(multipartFile);

        //存储Model中
        model.addAttribute("imgUrl",uploadFile) ;

        return "upload_ok" ;
    }
}

11.6 SpringMVC的resultFul风格(加入新的注解(@RestController))

前后端分离时,前端传过来和相应给前端的都是json格式,springmvc提供了很多的注解

@RestController //包含两个注解:@Controller@ResponseBody :标记这个控制器中每一个方法都返回json格式 @PostMapping("/login")等价于@RequestMapping(value="/login",method=RequestMethod.post)

12 验证码–githup提供–>本质还是一个servlet

(1)导包
	<dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
            <!--里面包含了servlet.jar包
                加载这个包的时候,过滤里面servlet.jar包
            -->
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

(2)配置web.xml

	 <servlet>
        <servlet-name>cap</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
        <init-param>
            <param-name>kaptcha.border</param-name>
            <param-value>no</param-value>
        </init-param>
        <init-param>
            <param-name>kaptcha.textproducer.char.length</param-name>
            <param-value>4</param-value>
        </init-param>
        <init-param>
            <param-name>kaptcha.textproducer.char.string</param-name>
            <param-value>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</param-value>
        </init-param>
        <init-param>
            <param-name>kaptcha.background.clear.to</param-name>
            <param-value>211,229,237</param-value>
        </init-param>
        <init-param>
            <!-- session.setAttribute("captcha","验证码") -->
            <param-name>kaptcha.session.key</param-name>
            <param-value>captcha</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>cap</servlet-name>
        <url-pattern>/captcha</url-pattern>
    </servlet-mapping>
    
    (3)在jsp中设置验证码即可
    	
    验证码:<input type="text" name="captcha" />
    <img src="${pageContext.request.contextPath}/captcha" id="img" width="80px" height="20px"/><br/>
    </div>
    设置点击事件,刷新图片
     $(this).attr("src",path) ;*/
        this.src="${pageContext.request.contextPath}/captcha?time="+new Date().getTime() ;

13.spring和springmvc的整合

在springmvc.xml文件中导入spring.xml即可
	<import resource="classpath:spring-config.xml"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值