Spring+Mybatis增删改查

测试数据准备

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
  `age` int(11) NOT NULL DEFAULT '0',
  `gender` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Mybatis的安装配置

1.安装(Maven直接引用)

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

https://github.com/mybatis/mybatis-3/releases

2.配置

resource/mybatis/jdbc.properties

username=root
password=root
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/study

resource/mybatis/mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!-- 引用 JDBC 配置文件 -->
    <properties resource="mybatis/jdbc.properties"/>

    <!-- 配置数据库连接 -->
    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 配置 Mappers -->
    <mappers>
        <!--  Mapper 的路径,从 resources 下一级目录开始写 -->
        <mapper resource="mybatis/mapper/StudentMapper.xml"/>
    </mappers>
</configuration>

3.实现

Student.java

package com.study.mybatis.pojo;

public class Student {
    private String name;
    private int    age;
    private String gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
               "name='" + name + '\'' +
               ", age=" + age +
               ", gender='" + gender + '\'' +
               '}';
    }
}

StudentMapper.java

package com.study.mybatis.dao;

import com.study.mybatis.pojo.Student;

import java.util.List;

public interface StudentMapper {
    List<Student> getStudents();

    void addStudent(Student student);

    void delStudent(Student student);

    void updateStudent(Student student);
}

resource/mybatis/mapper/StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="com.study.mybatis.dao.StudentMapper">
    <resultMap id="resultMap" type="com.study.mybatis.pojo.Student">
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>
    </resultMap>
    <select id="getStudents" resultMap="resultMap">
        select * from student;
    </select>
    <update id="updateStudent">
        update student set age = #{age} where name = #{name};
    </update>
    <delete id="delStudent">
        delete from student where name = #{name};
    </delete>
    <insert id="addStudent">
        insert into student (name,age,gender) values (#{name},#{age},#{gender});
    </insert>
</mapper>

4.测试

package com.study.mybatis.test;

import com.study.mybatis.dao.StudentMapper;
import com.study.mybatis.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.testng.annotations.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestStudent {
    @Test
    public void testStudent() {
        String      resource    = "mybatis/mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "default");
        SqlSession        sqlSession        = sqlSessionFactory.openSession(true);
        StudentMapper     studentMapper     = sqlSession.getMapper(StudentMapper.class);

        //初始化
        Student student = new Student();
        student.setName("张三");
        studentMapper.delStudent(student);
        student.setName("李四");
        studentMapper.delStudent(student);
        student.setName("王五");
        studentMapper.delStudent(student);
        student.setName("张三");
        student.setAge(18);
        student.setGender("男");
        studentMapper.addStudent(student);
        student.setName("李四");
        student.setAge(19);
        student.setGender("女");
        studentMapper.addStudent(student);

        //查询
        List<Student> students = studentMapper.getStudents();
        System.out.println("开始查询:\n" + students);

        //新增
        student.setName("王五");
        student.setAge(25);
        student.setGender("男");
        studentMapper.addStudent(student);
        //新增后查询
        students = studentMapper.getStudents();
        System.out.println("新增王五后:\n" + students);

        //删除
        student.setName("李四");
        studentMapper.delStudent(student);
        //删除后查询
        students = studentMapper.getStudents();
        System.out.println("删除李四后:\n" + students);

        //更新王五的年龄为20
        student.setName("王五");
        student.setAge(20);
        studentMapper.updateStudent(student);
        students = studentMapper.getStudents();
        System.out.println("更新王五的年龄后:\n" + students);

    }
}

目录结构

参考

http://www.mybatis.org/mybatis-3/zh/index.html

Spring配置AOP

1.使用注解方式配置AOP

applicationContext-aop.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"
       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">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.study.spring2.aop.impl"/>

    <!-- 使 Aspect 注解起作用:自动为匹配的类生成代理对象 -->
    <aop:aspectj-autoproxy/>

</beans>

Calculator.java

package com.study.spring2.aop.impl;

public interface Calculator {
    int add(int i, int j);

    int sub(int i, int j);

    int mul(int i, int j);

    int div(int i, int j);
}

CalculatorImpl.java

package com.study.spring2.aop.impl;

import org.springframework.stereotype.Component;

@Component(value = "calculator")
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        return i + j;
    }

    @Override
    public int sub(int i, int j) {
        return i - j;
    }

    @Override
    public int mul(int i, int j) {
        return i * j;
    }

    @Override
    public int div(int i, int j) {
        return i / j;
    }
}

LoggingAspect.java

package com.study.spring2.aop.impl;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 把这个类声明为一个切面: 需要把该类放入 IOC 容器中,再声明为一个切面
 * 可以使用@Order 指定切面的优先级,值越小,优先级越高
 */
@Order(2)
@Aspect
@Component
public class LoggingAspect {
    /**
     * 定义一个方法,用于声明切入点表达式,该方法中不需要填入其他的代码
     * 使用 @Pointcut 来声明切入点表达式
     * 后面其他通知直接使用方法名来引用切入点表达式
     */
    @Pointcut("execution(public int com.study.spring2.aop.impl.Calculator.*(int,int))")
    public void declareJoinPointExpresson() {
    }

    /**
     * 声明该方法是一个前置通知,在目标方法开始前执行
     */
    @Before("declareJoinPointExpresson()")
    public void beforeMethod(JoinPoint joinPoint) {
        String       methodName = joinPoint.getSignature().getName();
        List<Object> args       = Arrays.asList(joinPoint.getArgs());
        System.out.println("The Method " + methodName + " begins with " + args);
    }

    /**
     * 后置通知:在目标方法执行后(无论是否发生异常)执行的通知
     * 在后置通知中还不能访问目标方法执行的结果
     */
    @After("declareJoinPointExpresson()")
    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " ends");
    }

    /**
     * 返回通知:在方法正常返回后执行的代码
     * 返回通知是可以访问到方法的返回值的
     */
    @AfterReturning(value = "declareJoinPointExpresson()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " ends with " + result);
    }

    /**
     * 异常通知:在目标方法出现异常时会执行的代码
     * 可以访问异常对象 ,且指定在出现特定异常时执行代码
     */
    @AfterThrowing(value = "declareJoinPointExpresson()", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " occurs with excetion: " + ex);
    }

    /**
     * 环绕通知:需要携带 ProceedingJoinPoint 类型参数。
     * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint 决定是否执行目标方法
     * 且环绕通知必须有返回值,返回值即目标方法的返回值
     */
    @Around(value = "declareJoinPointExpresson()")
    public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) {
        Object result     = null;
        String methodName = proceedingJoinPoint.getSignature().getName();
        try {
            //前置通知
            System.out.println("The Method " + methodName + " begins with " + Arrays.asList(proceedingJoinPoint.getArgs()));
            //执行目标方法
            result = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("The Method " + methodName + " ends with " + result);
        } catch (Throwable e) {
            //异常通知
            System.out.println("The Method " + methodName + " occurs with excetion: " + e);
            throw new RuntimeException(e);
        }
        //后置通知
        System.out.println("The Method " + methodName + " ends");
        return result;
    }
}

VildationAspect.java

package com.study.spring2.aop.impl;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Order(1)
@Aspect
@Component
public class VildationAspect {
    @Before("LoggingAspect.declareJoinPointExpresson()")
    public void validateArgs(JoinPoint joinPoint) {
        System.out.println("Validate:" + Arrays.asList(joinPoint.getArgs()));
    }
}

Main.java

package com.study.spring2.aop.impl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        //1. 创建 Spring 的 IOC 容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
        //2. 从 IOC 容器中获取 bean 的实例
        Calculator calculator = (Calculator) ctx.getBean("calculator");
        //3. 使用 bean
        int result = calculator.add(3, 6);
        System.out.println(result );

        result = calculator.div(12, 3);
        System.out.println(result );
    }
}

2.使用XML方式配置AOP

applicationContext-aop-xml.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: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/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置 bean -->
    <bean id="calculator" class="com.study.spring2.aop.xml.CalculatorImpl"/>

    <!-- 配置切面的 bean -->
    <bean id="loggingAspect" class="com.study.spring2.aop.xml.LoggingAspect"/>
    <bean id="vildationAspect" class="com.study.spring2.aop.xml.VildationAspect"/>

    <!-- 配置 AOP -->
    <aop:config>
        <!-- 配置切入点表达式 -->
        <aop:pointcut id="pointcut" expression="execution(* com.study.spring2.aop.xml.Calculator.*(..))"/>
        <!-- 配置切面及通知 -->
        <aop:aspect ref="loggingAspect" order="2">
            <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
            <aop:after method="afterMethod" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
            <aop:around method="aroundMethod" pointcut-ref="pointcut"/>
        </aop:aspect>
        <aop:aspect ref="vildationAspect" order="1">
            <aop:before method="validateArgs" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

Calculator.java

package com.study.spring2.aop.xml;

public interface Calculator {
    int add(int i, int j);

    int sub(int i, int j);

    int mul(int i, int j);

    int div(int i, int j);
}

CalculatorImpl.java

package com.study.spring2.aop.xml;

public class CalculatorImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        return i + j;
    }

    @Override
    public int sub(int i, int j) {
        return i - j;
    }

    @Override
    public int mul(int i, int j) {
        return i * j;
    }

    @Override
    public int div(int i, int j) {
        return i / j;
    }
}

LoggingAspect.java

package com.study.spring2.aop.xml;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Arrays;
import java.util.List;

public class LoggingAspect {
    public void declareJoinPointExpresson() {
    }

    public void beforeMethod(JoinPoint joinPoint) {
        String       methodName = joinPoint.getSignature().getName();
        List<Object> args       = Arrays.asList(joinPoint.getArgs());
        System.out.println("The Method " + methodName + " begins with " + args);
    }

    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " ends");
    }

    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " ends with " + result);
    }

    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The Method " + methodName + " occurs with excetion: " + ex);
    }

    public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) {
        Object result     = null;
        String methodName = proceedingJoinPoint.getSignature().getName();
        try {
            //前置通知
            System.out.println("The Method " + methodName + " begins with " + Arrays.asList(proceedingJoinPoint.getArgs()));
            //执行目标方法
            result = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("The Method " + methodName + " ends with " + result);
        } catch (Throwable e) {
            //异常通知
            System.out.println("The Method " + methodName + " occurs with excetion: " + e);
            throw new RuntimeException(e);
        }
        //后置通知
        System.out.println("The Method " + methodName + " ends");
        return result;
    }
}

VildationAspect.java

package com.study.spring2.aop.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

public class VildationAspect {
    public void validateArgs(JoinPoint joinPoint) {
        System.out.println("Validate:" + Arrays.asList(joinPoint.getArgs()));
    }
}

Main.java

package com.study.spring2.aop.xml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        //1. 创建 Spring 的 IOC 容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop-xml.xml");
        //2. 从 IOC 容器中获取 bean 的实例
        Calculator calculator = (Calculator) ctx.getBean("calculator");
        //3. 使用 bean
        int result = calculator.add(3, 6);
        System.out.println(result);

        result = calculator.div(12, 3);
        System.out.println(result);
    }
}

Spring的Xml文件配置

创建一个Bean

applictionContext.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="helloWorld" class="com.study.spring.pojo.HelloWorld">
        <property name="name" value="china-spring"/>
    </bean>

</beans>

Bean熟悉值包含特殊字符的处理方式

applictionContext.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="car1" class="com.study.spring.pojo.Car">
        <constructor-arg name="brand" value="BMW"/>
        <!-- 如果字面包含特殊字符可以使用 <![CDATA[]]> 包裹-->
        <!-- 属性值也可以通过 value 子节点进行配置-->
        <constructor-arg name="city"><value><![CDATA[<Beijing'>]]></value></constructor-arg>
        <constructor-arg name="price" value="1000000"/>
        <constructor-arg name="maxSpeed" value="300"/>
    </bean>

</beans>

Bean引用

applictionContext.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="car1" class="com.study.spring.pojo.Car">
        <constructor-arg name="brand" value="BMW"/>
        <constructor-arg name="city" value="Shanghai"/>
        <constructor-arg name="price" value="1000000"/>
        <constructor-arg name="maxSpeed" value="300"/>
    </bean>

    <bean id="person" class="com.study.spring.pojo.Person">
        <property name="name" value="Tom"/>
        <property name="age" value="20"/>
        <!-- 可以使用 property 的 ref 属性建立 bean 之间的引用关系-->
        <property name="car" ref="car1"/>
    </bean>
</beans>

内部Bean

applictionContext.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="person" class="com.study.spring.pojo.Person">
        <property name="name" value="Tom"/>
        <property name="age" value="20"/>
        <property name="car">
            <!-- 内部 bean ,不能被外部 bean 引用 -->
            <bean class="com.study.spring.pojo.Car">
                <constructor-arg name="brand" value="Ford"/>
                <constructor-arg name="city" value="Changan"/>
                <constructor-arg name="price" value="1500000"/>
                <constructor-arg name="maxSpeed" value="140"/>
            </bean>
        </property>
    </bean>
</beans>

Bean为级联属性赋值

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="car1" class="com.study.spring.pojo.Car">
        <constructor-arg name="brand" value="BMW"/>
        <constructor-arg name="city" value="Shanghai"/>
        <constructor-arg name="price" value="1000000"/>
        <constructor-arg name="maxSpeed" value="300"/>
    </bean>

    <bean id="person" class="com.study.spring.pojo.Person">
        <property name="name" value="Tom"/>
        <property name="age" value="20"/>
        <property name="car" ref="car1"/>
        <!-- 为级联属性赋值 -->
        <property name="car.maxSpeed" value="500"/>
    </bean>
</beans>

Bean配置集合属性

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="person1" class="com.study.spring.pojo.collection.Person">
        <property name="name" value="Jerry"/>
        <property name="age" value="30"/>
        <property name="cars">
            <list>
                <bean class="com.study.spring.pojo.collection.Car">
                    <constructor-arg name="brand" value="FT"/>
                    <constructor-arg name="city" value="XA"/>
                    <constructor-arg name="price" value="100000"/>
                    <constructor-arg name="maxSpeed" value="220"/>
                </bean>
                <bean class="com.study.spring.pojo.collection.Car">
                    <constructor-arg name="brand" value="FT1"/>
                    <constructor-arg name="city" value="XA1"/>
                    <constructor-arg name="price" value="110000"/>
                    <constructor-arg name="maxSpeed" value="230"/>
                </bean>
            </list>
        </property>
    </bean>
</beans>

配置Properties属性值

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">

    <!-- 配置 Properties 属性值 -->
    <bean id="dataSource" class="com.study.spring.pojo.DataSource">
        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
                <prop key="jdbcUrl">jdbc:mysql://127.0.0.1:3306/blog</prop>
                <prop key="driverClass">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
    </bean>
</beans>

配置单例的集合

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"
       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
       http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 配置单例的集合 bean ,以供多个 bean 调用, 需要导入 util 命名空间-->
    <util:list id="cars">
        <ref bean="car1"/>
        <ref bean="car1"/>
        <ref bean="car1"/>
    </util:list>
</beans>

通过p命名空间为Bean赋值

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" 
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过 p 命名空间为 bean 赋值,需要先导入 p 命名空间,相对于传统的配置方式更加简洁 -->
    <bean id="person2" class="com.study.spring.pojo.collection.Person" p:name="Queen" p:age="20" p:cars-ref="cars"/>
</beans>

Bean自动装配

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.study.spring.pojo.autowire.Address" id="address" p:city="Beijing" p:street="Chaoyang"/>
    <bean class="com.study.spring.pojo.autowire.Car" id="car" p:brand="Audi" p:price="2000000"/>
    <bean class="com.study.spring.pojo.autowire.Person" id="person" p:name="Jay" p:address-ref="address"
          p:car-ref="car"/>
    <!--
    可以使用 autowire 属性指定自动装配方式。
    byName 根据 bean 的名字和当前 bean 的 setter 风格的属性名进行自动装配。若有匹配的,则装配;若没有匹配的,则不装配。
    byType 根据 bean 的类型和当前 bean 的属性类型进行自动装配。若 IOC 容器中有1个以上的类型匹配,则抛异常。
    -->
    <bean class="com.study.spring.pojo.autowire.Person" id="person1" p:name="Jay" autowire="byName"/>
    <bean class="com.study.spring.pojo.autowire.Person" id="person3" p:name="Jay" autowire="byType"/>

</beans>

Bean的继承

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- bean 的配置继承:使用 bean 的 parent 属性指定继承哪个 bean 的配置-->
    <bean class="com.study.spring.pojo.autowire.Address" id="address" p:city="Beijing" p:street="WuDaoKou"/>
    <bean class="com.study.spring.pojo.autowire.Address" id="address2" parent="address"/>

    <!--
    抽象 bean:abstract 属性为 true 的 bean。这样的 bean 不能被 IOC 容器实例化,只能用来被继承。
    若一个 bean 的 class 属性没有被指定,则该 bean 必须是一个抽象 bean。
    -->
    <bean class="com.study.spring.pojo.autowire.Address" id="address3" p:city="Beijing" p:street="WuDaoKou" abstract="true"/>
    <bean id="address1" parent="address3" p:street="DaZhongSi"/>
</beans>

Bean的依赖

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 要求在配置 person 时,必须有一个关联的 car! 换句话说 person 这个 bean 依赖于 car 这个 bean -->
    <bean class="com.study.spring.pojo.autowire.Car" id="car2" p:brand="BMW" p:price="300000"/>
    <bean class="com.study.spring.pojo.autowire.Person" id="person" p:name="Tom" p:address-ref="address" p:car-ref="car2" depends-on="car2"/>
</beans>

Bean的作用域

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        使用 bean 的 scope 属性来配置 bean 的作用域
        singleton:默认值. 容器初始化时创建 bean 实例,在整个容器生命周期内只创建这一个 bean (单例的)
        prototype:原型的. 容器初始化时不创建 bean 实例,而在每次请求时都创建一个新的 bean 实例,并返回。
    -->
    <bean class="com.study.spring.pojo.autowire.Car" id="car3" p:brand="Audi" p:price="500000" scope="prototype"/>
</beans>

Bean引用外部文件

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"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 导入属性文件 -->
    <context:property-placeholder location="jdbc.properties"/>

    <!-- 使用外部文件的属性 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
        <property name="driverClassName" value="${driverClassName}"/>
    </bean>
</beans>

jdbc.properties

username=root
password=root
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306

使用SpEL为属性赋值

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="address" class="com.study.spring.pojo.spel.Address">
        <!-- 使用 SpEL 为属性赋一个字面值 -->
        <property name="city" value="#{'Beijing'}"/>
        <property name="street" value="WuDaoKou"/>
    </bean>

    <bean id="car" class="com.study.spring.pojo.spel.Car">
        <property name="brand" value="Audi"/>
        <property name="price" value="500000"/>
        <!-- 使用 SpEL 引用类的静态属性 -->
        <property name="tyrePerimeter" value="#{T(java.lang.Math).PI * 80}"/>
    </bean>

    <bean id="person" class="com.study.spring.pojo.spel.Person">
        <!-- 使用 SePL 来引用其他的 bean -->
        <property name="car" value="#{car}"/>
        <!-- 使用 SePL 来引用其他的 bean 的属性 -->
        <property name="city" value="#{address.city}"/>
        <!-- 在 SePL 中使用运算符 -->
        <property name="info" value="#{car.price > 300000 ? '金领':'白领 '}"/>
        <property name="name" value="Tom"/>
    </bean>

</beans>

TestNG传参的几种方式

1.通过Xml文件传参

TestNg.java

package com.test;

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

/**
 * @author shijl
 */
public class TestNG {
    @Parameters({"a", "b"})
    @Test
    public static void testNG(String a, String b) {
        System.out.println(a);
        System.out.println(b);
    }
}

testNG.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="test">
    <!-- 参数配置 -->
    <parameter name="a" value="aaa"/>
    <parameter name="b" value="bbb"/>

    <!-- 执行测试 -->
    <test name="test"><classes><class name="com.test.TestNG"/></classes></test>
</suite>

执行结果:

aaa
bbb

2.通过@DataProvider传参

package com.test;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

/**
 * @author shijl
 */
public class TestNG {
    @DataProvider(name = "xxx")
    public static Object[][] xxx() {
        return new Object[][]{
                {"aaa", "bbb"},
                };
    }

    @Test(dataProvider = "xxx")
    public static void testNG(String a, String b) {
        System.out.println(a);
        System.out.println(b);
    }
}

执行结果:

aaa
bbb

Shell多进程

echo.sh

#!/bin/bash
for (( i = 0; i < 10000; i++ )); do
    echo "process"${1}"的输出"${i};
done

start.sh

#!/bin/bash
for (( i = 0; i < 5; i++ )); do
    ./echo.sh ${i} &
done

执行结果(摘取部分)

几个进程是并发执行的
...
process3的输出9896
process0的输出9641
process0的输出9642
process3的输出9897
process4的输出9876
process0的输出9643
process4的输出9877
process0的输出9644
process4的输出9878
process0的输出9645
process4的输出9879
process0的输出9646
process4的输出9880
process4的输出9881
process4的输出9882
process4的输出9883
process4的输出9884
...

两个有序数组的合并

实现代码

package com.test;

import java.util.Arrays;

public class AppendArray {
    public static void main(String[] args) {
        int[] arrayA = {1, 3, 5, 5, 7, 9, 15};
        int[] arrayB = {2, 4, 6, 8, 8, 10};

        System.out.println(Arrays.toString(getNewArray(arrayA, arrayB)));
    }

    private static int[] getNewArray(int[] a, int[] b) {
        int[] arrayNew       = new int[a.length + b.length];
        int   arrayNewLength = a.length + b.length;
        for (int i = 0; i < arrayNewLength; i++) {
            if (a.length == 0 && b.length != 0) {
                arrayNew[i] = b[0];
                b = deleteFirstValue(b);
            } else if (a.length != 0 && b.length == 0) {
                arrayNew[i] = a[0];
                a = deleteFirstValue(a);
            } else if (a[0] < b[0]) {
                arrayNew[i] = a[0];
                a = deleteFirstValue(a);
            } else {
                arrayNew[i] = b[0];
                b = deleteFirstValue(b);
            }
        }

        return arrayNew;
    }

    private static int[] deleteFirstValue(int[] a) {
        int[] arrayNew = new int[a.length - 1];
        for (int i = 0; i < a.length - 1; i++) {
            arrayNew[i] = a[i + 1];
        }

        return arrayNew;
    }
}

执行结果

[1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10, 15]

sqlmap常用命令

基本信息:

sqlmap -u "http://localhost/test.php?id=11" -v 5(5代表level,0-5)

所有dbs:

sqlmap -u "http://localhost/test.php?id=11" -v 5 --dbs

所有用户:

sqlmap -u "http://localhost/test.php?id=11" -v 5 —users

当前使用的db:

sqlmap -u "http://localhost/test.php?id=11" -v 5 --current-db

当前用户:

sqlmap -u "http://localhost/test.php?id=11" -v 5 --current-user

某个库所有表名:

sqlmap -u "http://localhost/test.php?id=11" -v 1 -D test —tables

某个表所有列名:

sqlmap -u "http://localhost/test.php?id=11" -v 0 -D test -T deskstatus —columns

某个表所有数据:

sqlmap -u "http://localhost/test.php?id=11" -v 0 -D test -T deskstatus —dump

获取密码:

sqlmap -u "http://localhost/test.php?id=11" --passwords

获取指定用户密码:

sqlmap -u "http://localhost/test.php?id=11" --password -U root

获取指定列:

sqlmap -u "http://localhost/test.php?id=11" -D test -T deskstatus -C field1 —dump

sql查询:

sqlmap -u "http://localhost/test.php?id=11" --sql-query "select * from mysql.user”

是否DBA:

sqlmap -u "http://localhost/test.php?id=11" --is-dba

sql版本:

sqlmap -u "http://localhost/test.php?id=11" -b

输出到文件:

sqlmap -u="http://localhost/test.php?id=11" -o "d:/log.txt”

post请求:

sqlmap -u "http://localhost/test.php?id=11" --data="cid=xxxxx;uid=xxxx;time=xxxxx;sign=xxxx%3D" --param-del=";"  —dbs

IP合法性校验

实现思路

1.校验不为空
2.按照.切割,判断数组长度是否为4
3.遍历数组,判断每个元素是否为数字
4.判断每个元素是否0<= X <=255(特殊:第一个元素需要!=0)

代码实现

package com.test;

import org.bouncycastle.util.Strings;

public class CheckIP {
    public static void main(String[] args) {
        String ip = "10.0.2.78";
        if (isValid(ip)) {
            System.out.println(ip + ":合法");
        } else {
            System.out.println(ip + ":非法");
        }
    }

    public static boolean isValid(String ip) {
        if ("".equals(ip)) {
            return false;
        }
        String[] ipArr = Strings.split(ip, '.');
        if (ipArr.length != 4) {
            return false;
        }

        for (int i = 0; i < 4; i++) {
            if (!isNumber(ipArr[i])) {
                return false;
            }
            int a = Integer.valueOf(ipArr[i]);
            if (a < 0 || a > 255) {
                return false;
            }
            if (i == 0 && a == 0) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNumber(String s) {
        try {
            Integer.valueOf(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

执行结果

10.0.2.78:合法

冒泡排序

package com.test;

import java.util.Arrays;

public class BubbleOrder {
    public static void main(String[] args) {
        int[] a = {21, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
        System.out.println(Arrays.toString(order(a)));
    }

    public static int[] order(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - i - 1; j++) {
                if (a[j] > a[j + 1]) {
                    changeOrder(a, j);
                }
            }
        }
        return a;
    }

    public static void changeOrder(int[] a, int m) {
        int tmp = a[m];
        a[m] = a[m + 1];
        a[m + 1] = tmp;
    }
}

执行结果:

[3, 5, 9, 21, 32, 34, 35, 37, 50, 55, 64, 70, 82, 89]