2020-12-31小黄自学文档整理(其实是小白,因为姓黄)

Mybatis持久层框架学习

1.简介

2.第一个mybatis程序

1.环境搭建

​ 1.1创建maven项目

​ pom文件导入项目依赖jar包

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>
        
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		lombok是用来在当中引入注解,不用手动创建类中的构造函数和getter、setter方法
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>

1.2完成环境配置文件mybatis-config.xml

​ 引入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">

基本功能实现的配置文件

<?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">
<!--config 约束-->
<configuration>
    <!--引入外部配置文件-->
    <!--将连接数据库的信息写在db.properties中-->
    <properties resource="db.properties"/>
    <!--日志工厂 #日志工厂
        #如果一个数据库操作出现异常,日志就是最好的助手
    -->

    <settings>
        <!--标准日志工厂实现-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--<setting name="logImpl" value="log4j"/>-->
    </settings>


    <!-- typeAlias类型别名,为java类中设置一个别名-->
    <typeAliases>
        <!--方法①,可以自定义随便定义名字-->
        <!--<typeAlias type="entity.User" alias="User"/>-->
        <!--方法②可以指定一个包名,mybatis会自动在这个包名下搜索所需要的javaBean,比如扫描实体类的包,默认别名就是为这个类的类名。首字母小写可以给实体类起别名-->
        <package name="entity"/>
        <!--方法③使用注解@Alias("xxx")在类的名字上面加-->
    </typeAliases>

    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
     			 <!--皆从db.properties文件中获取数据库连接信息-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--指定映射配置文件的位置,映射文件指的是每个dao独立的配置文件-->
    <!--MapperRegistry:注册绑定Mapper文件-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
        <mapper resource="mapper/TeacherMapper.xml"/>
        <mapper resource="mapper/StudentMapper.xml"/>
    </mappers>

</configuration>

1.3创建db.propertis文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_self?serverTimezone=UTC
username=root
password=2580

1.4创建MybatisUtils

public class MybatisUtils {
    private static  SqlSessionFactory sqlSessionFactory;
    static{
        try {
            String resourse="mybatis-config.xml";
            InputStream inputStream= Resources.getResourceAsStream(resourse);
            //SqlSessionFactoryBuilder只实例化一次,一旦创建SqlSessionFactory就没用了
            /*
                sqlSessionFactory一旦创建就一直存在,没有任何理由去创建另一个实例
                最佳作用域是应用作用域,创建多浪费资源,最简单就是单例模式或者静态单例模式
            */
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /*
    	sqlSession
    	增删改查皆使用sqlSession,不再使用jdbc中的Statement或者PreparedStatement
    	使用完立即关闭,否则浪费资源
    	实例现成不安全,不能共享
    	每收到一个http请求都会创建一个sqlsession
    */
    public static SqlSession getSqlSession(){
       //如果sqlSessionFactory.openSession()方法中传入一个true,即代表对数据库进行操作
       //是自动提交,如果没有传入,在操作时候需要手动提交sqlsession的commit()方法,才能完成对数		  据库的操作(例如更新,插入操作)
        return sqlSessionFactory.openSession();
    }
}


3.log4j日志使用

#<!--
##什么是log4j  可以控制日志信息输送的目的地是控制台,文件,GUI组件
##可以控制每一条日志的输出格式
##定义每一条日志信息的级别,能更加细致控制日志的生成过程
##通过一个配置文件来灵活进行配置,不需要修改应用代码
##-->


log4j.rootLogger=debug, stdout, R
#控制台输出相关配置
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n
#文件输出相关配置
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=firestorm.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
#日志输出类别
log4j.logger.com.codefutures=DEBUG

## 4.创建mapper文件

resource目录下创建mapper包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8e6e7Opd-1609410796699)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126162529648.png)]

dao包下面存放pojo借口类,定义方法,无需实现。

案例:

```java
public interface IUserDao {
    List<User>findAll();
    User getUserById(int id);
    int insertUser(User user);
    int updateUser(User user);
    int deleteUserById(User user);
//    使用mybatis完成分页功能
    List<User>getUserByLimit(Map<String, Integer> map);
}

UserMapper.xml

注:

​ resultType 返回的是一个结果

​ resultMap返回的是一个集合

​ parameterType参数类型

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间绑定的是pojo的接口类-->
<mapper namespace="dao.IUserDao">
    
    <!--resultMap功能是结果集映射,解决字段名和数据库表中属性名不一致的问题-->
    <!--如果resultMap中的字段和数据库中的属性名一致,可以不用写-->
    <resultMap id="userMap" type="User">
        <result column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="address" property="add"/>
    </resultMap>
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>
  
    <!--resultType是返回值类型-->
    <!--<select id="findAll" resultType="User">-->
        <!--select * from user;-->
    <!--</select>-->

    <!--parameterType是参数类型-->
    <select id="getUserById" parameterType="int" resultType="entity.User">
        select * from user where id=#{id}
    </select>
        
    <insert id="insertUser" parameterType="entity.User" >
        insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address});
    </insert>

    <update id="updateUser" parameterType="entity.User">
        update user set username=#{username} where id=#{id}

    </update>

    <delete id="deleteUserById" parameterType="int">
        delete from user where id=#{id}

    </delete>

    <!--分页-->
    <select id="getUserByLimit" parameterType="map" resultMap="userMap">
        select * from user limit #{startIndex},#{pageSize}
    </select>


5.多表嵌套查询

6.注解的使用

5.1引入lombokjar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zrmud09e-1609410796700)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126163525823.png)]

5.2注解实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
//Data注解:无参构造、get、set、tostring、hashcode、equals
//@AllArgsConstructor 生成有参构造
//@NoArgsConstructor 生成无参构造
public class User implements Serializable {
    private Integer id;
    private String username;
    private String sex;
    private String add;
}

12.动态Sql

动态sql的几大标签

​ 1.If

 <select id="queryBlog" parameterType="map" resultType="blog">
        SELECT * FROM blog
        <where>
            <if test="title != null">
                 title=#{title}
            </if>
            <if test="views != null">
                and views =#{views}
            </if>
        </where>
    </select>

​ 2.trim(where,set)

where元素只会在查询语句中至少满足一个条件下才会插入where语句,且语句中如果有and或者or开头的,where也会将其去掉
     <select id="queryBlog" parameterType="map" resultType="blog">
        SELECT * FROM blog
        <where>
            <if test="title != null">
                 title=#{title}
            </if>
            <if test="views != null">
                and views =#{views}
            </if>
        </where>
    </select>

案例1:
Test类中没有对于map没有传递任何数据值,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ZEX4tW3-1609410796702)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126144940304.png)]

Mapper文件SQL语句

  <select id="queryBlog" parameterType="map" resultType="blog">
        SELECT * FROM blog
        <where>
            <if test="title != null">
                 title=#{title}
            </if>
            <if test="views != null">
                and views =#{views}
            </if>
        </where>
    </select>

运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IBnMLTEA-1609410796705)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126144905126.png)]

test类中赋值

public class TeacherTest {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IBlogDao mapper = sqlSession.getMapper(IBlogDao.class);
        HashMap map=new HashMap();
        map.put("title","spring全家桶");
//        map.put("author","胡雅楠");
        map.put("views",5555);
        List<Blog> blogs = mapper.queryBlog(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDA0T6lc-1609410796706)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126145525478.png)]

public class TeacherTest {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IBlogDao mapper = sqlSession.getMapper(IBlogDao.class);
        HashMap map=new HashMap();
        map.put("title","spring全家桶");
//        map.put("author","胡雅楠");
//        map.put("views",5555);
        List<Blog> blogs = mapper.queryBlog(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FgntPnCS-1609410796709)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126145704951.png)]

​ 3.choose(when,otherwise)

choose相当于java中的switch case 语句
    <select id="queryBlogChoose" parameterType="map"  resultType="Blog">
          select * from blog
          <where>
              <choose>
                  <when test="title != null">
                      title=#{title}
                  </when>
                  <when test="author != null">
                      and author=#{author}
                  </when>
                  <otherwise>
                      and views=#{views}
                  </otherwise>
              </choose>
          </where>
    </select>

SQL片段:

​ 有时候将一些公共部分抽取出来方便复用。

1.在使用sql标签抽取公共部分  
<sql id="dynamicSqlRepeatCodeIntgrate">
        <if test="title != null">
            title=#{title}
        </if>
        <if test="views != null">
            and views =#{views}
        </if>
    </sql>
2.在需要使用的地方使用include标签引用即可
    <select id="queryBlogSql" parameterType="map" resultType="blog">
        SELECT * FROM blog
        <where>
           <include refid="dynamicSqlRepeatCodeIntgrate"></include>
        </where>
    </select>
            
注意事项:
	最好基于单表定义sql片段
    不要在1中存在where标签

注意:open中的and和括号必须有空格,否则报错

 <!--foreach标签使用 select * from blog where 1=1 and(id=1 or id=2 or id=3) -->
    <select id="selectByForeach" parameterType="map" resultType="blog" >
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="and(" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q3ndhm6F-1609410796711)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130155031912.png)]

正确写法:

    <select id="selectByForeach" parameterType="map" resultType="blog" >
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>
  @Test
    public void testSelectByForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IBlogDao mapper = sqlSession.getMapper(IBlogDao.class);
        HashMap map=new HashMap();
        List<String> ids=new ArrayList<String>();
        ids.add("1");
        ids.add("2");
        ids.add("3");
        map.put("ids",ids);
        List<Blog> blogs = mapper.selectByForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNbLaHMW-1609410796712)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130155208459.png)]

如果ids是为空的没有赋值的集合,mybatis会自动忽略后面的标签,实际语句变成select * from blog

  @Test
    public void testSelectByForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IBlogDao mapper = sqlSession.getMapper(IBlogDao.class);
        HashMap map=new HashMap();
        List<String> ids=new ArrayList<String>();
        map.put("ids",ids);
        List<Blog> blogs = mapper.selectByForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Di26H5eZ-1609410796715)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130155406570.png)]

动态sql就是在拼接sql语句,只要保证sql的正确性,按照sql格式,排列组合即可

13.缓存

13.1.简介

1.什么是缓存?

  1. ​ 存在内存的临时数据
  2. ​ 将用户经常查询的数据放在缓存中,用户去查询就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

2.为什么使用缓存?

  • ​ 减少和数据库的交互次数,减少系统开销,提高系统效率

3,什么样的数据使用缓存?

  • ​ 经常查询并且不经常改变的数据

13.2.一级缓存

一级缓存也叫本地缓存 Sqlsession

​ 与数据库同一次会话期间查询到的数据会放在本地缓存中

​ 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库

//查询只走了一次
public class UserTest {
    @Test
    public void testUserCache(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IUserDao mapper = sqlSession.getMapper(IUserDao.class);
        User user = mapper.getUserById(3);
        System.out.println(user);
        System.out.println("=============");
        User user1 = mapper.getUserById(3);
        System.out.println((user==user1));
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJLQZjPj-1609410796717)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130163324332.png)]

缓存失效情况:

​ 1.查询不同的东西

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5837sVn-1609410796718)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130163940453.png)]

​ 2.增删改操作,可能会改变原来的数据,所以必定会刷新缓存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-buljtwnd-1609410796720)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201130183529671.png)]

​ 3.查询不同的mapper.xml

​ 4.手动清理缓存

​ sqlsession.clearCache();

小结:一级缓存默认是开启的,只在一次sqlsession中有效,也就是拿到连接关闭这个连接的区间之间。一级缓存相当于一个Map

13.3.二级缓存

​ 在mapper.xml文件中加入一个就是二级缓存

映射语句中所有select语句会被缓存

映射语句文件中所有insert,update,delete语句会刷新缓存

缓存会使用最近最少使用算法(LRU,)

​# Spring学习

1.spring简介

spring优点:

​ 1.一个开源免费框架

​ 2.一个轻量级,非入侵式框架

​ 3.控制反转IOC,面向切面编程AOP

​ 4.支持事务处理,对框架整合的支持

总结:spring是一个轻量级的控制反转IOC和面向切面编程的框架

1.2组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OtlreqGs-1609411012065)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201127113250819.png)]

Spring Boot

​ 一个快速的开发脚手架

​ 基于SpringBoot可以快速开发的单个微服务

​ 约定大于配置

SpringCloud

​ SpringCloud是基于SpringBoot实现的

弊端:发展太久,违背原来理念,配置十分繁琐,所以要学习springboot

1.3IOC理论推导

1、UserDao 接口

2、UserDaoImpl实现类

3、UserService业务接口

4、UserServiceImpl业务实现类

理解:

​ dao包下面放置了多个业务,用户想使用不同的业务时候,程序员要在UserServiceImpl中实例化不同的对象,要程序员根据用户需求修改代码。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dz5rfeGT-1609411012067)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201202125622550.png)]

public class UserServiceImpl implements UserService {
    //用户实际调用的是业务层,dao层不需要他们接触
    private UserDao userDao=new UserDaoOracleImpl();
    //每次用户提出不同的要求,程序员都要在UserServiceImpl修改代码,控制权在程序员手上,如果项目庞大,改动十分繁琐
    public void getUser() {
        userDao.getUser();
    }
}

修改UserServiceImpl中的代码

public class UserServiceImpl implements UserService {
    //通过setter注入,在将控制权翻转,控制权不在程序员手上,而是在用户手上。
    //使用setter注入,程序不再具有主动性,而是被动变成了接收对象,这就是控制反转思想
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void getUser() {
        userDao.getUser();
    }
}

耦合性大大降低,可以更专注业务的实现,这是IOC的原型,思想

1.4创建项目

导包:spring-webmvc spring-jdbc

创建目录如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vhlyRKDw-1609411012071)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201202150004152.png)]

在resource目录下创建applicationContext.xml文件


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="hello" class="com.huang.pojo.Hello">
        <property name="str" value="spring"/>
    bean>

    <bean id="UserDaoImpl" class="com.huang.dao.UserDaoImpl"/>
    <bean id="UserDaoMysqlImpl" class="com.huang.dao.UserDaoMysqlImpl"/>
    
    <bean id="UserServiceImpl" class="com.huang.service.UserServiceImpl">
       <property name="userDao" ref="UserDaoImpl">property>
    bean>
beans>

测试类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGHLbrdG-1609411012074)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201202150536493.png)]

思考问题:

​ 对象是谁创建的?

​ 对象的属性是怎么设置的?

这个过程就叫控制反转:

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring之后,对象是由Spring来创建的。

反转:程序本事不创建对象,而变成被动的接收对象。

依赖注入:就是利用set方法来进行注入。

IOC是一种编程思想,由主动编程变成被动的接收

2.IOC创建对象方式

1.使用无参构造创建对象(系统默认方式)

2.有参构造

​ 1.下标赋值。实体类中写有参构造

public class User {
    private String username;
    public User(String username) {
        this.username = username;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
}


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">  
	
    <bean id="hello" class="com.huang.pojo.Hello">
        <property name="str" value="spring"/>
    bean>
beans>

2.通过类型创建,不建议使用

 <bean id="user" class="com.huang.pojo.User">
        <constructor-arg type="java.lang.String" value="huang"/>
 bean>

3.直接通过参数名来设置

  <bean id="user" class="com.huang.pojo.User">
        <constructor-arg name="username" value="huang"/>
    bean>

总结:配置文件加载时候,容器中管理的对象已经被初始化了

2.1Spring配置

2.1.1别名

​ alias另起别名,类似mybatis中的起别名

 <bean id="user" class="com.huang.pojo.User">
        <constructor-arg name="username" value="huang"/>
 bean>
 <alias name="user" alias="userNew"/>
public class SpringTest {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        User user=(User) context.getBean("userNew");
        System.out.println(user.toString());

    }
}

2.1.2Bean的配置

id:bean的唯一标识符,相当于对象名
name:也是别名,name可以同时取多个别名
class:bean对象所对应的全限定名:包名+类型
scope:
   <bean id="user" class="com.huang.pojo.User" name="user1 user2">
        <constructor-arg name="username" value="huang"/>
    bean>

2.1.3Import

一般用于团队开发使用,可以将多个配置文件,汇总成一个.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cgMRhB2g-1609411012080)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203134840508.png)]


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="applicationcontext.xml"/>
beans>

3.依赖注入DI

3.1、构造器注入

前面已经说过了

3.2、set注入(重点)

依赖注入:set注入

  • ​ 依赖:bean对象创建依赖于容器

  • ​ 注入:bean对象中的所有属性,由容器来注入

    实体类

public class Address {
    private String address;
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address.getAddress() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}


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

    <bean id="address" class="com.huang.pojo.Address">
        <property name="address" value="江苏省徐州市睢宁县官山镇黄圩村"/>
    bean>

    <bean id="student" class="com.huang.pojo.Student">
        <property name="name" value="huangyuhang"/>
        <property name="address" ref="address" />
        
        <property name="books">
            <array>
                <value>javaEEvalue>
                <value>c#value>
                <value>pythonvalue>
            array>
        property>

        
        <property name="hobbys">
            <list>
                <value>音乐value>
                <value>篮球value>
            list>
        property>

        
        <property name="card">
            <map>
                <entry key="身份证" value="320324199609094477"/>
            map>
        property>

        
        <property name="games">
            <set>
                <value>LOLvalue>
                <value>COCvalue>
            set>
        property>
        
        
        <property name="wife">
            <null/>
        property>
        
        
        <property name="info">
            <props>
                <prop key="学号">Z2019120114prop>
            props>
        property>

    bean>
beans>

3.3、拓展方式注入

使用p命名空间和c命名空间来进行注入

P命名空间注入

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

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    bean>

    <bean name="john-modern"
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

    <bean name="jane" class="com.example.Person">
        <property name="name" value="Jane Doe"/>
    bean>
beans>

4.Bean作用域

4.1singleton单例(默认)

只创建一个实例

  <bean id="address" class="com.huang.pojo.Address" scope="singleton">
        <property name="address" value="江苏省徐州市睢宁县官山镇黄圩村"/>
    bean>
  public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        Student student=(Student) context.getBean("student");
        Student student1=(Student)context.getBean("student");
        System.out.println(student==student1);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZeqwMfzA-1609411012081)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203193436013.png)]

4.2prototype原型模式

每次从容器get时候都会产生一个新的对象

 <bean id="student" class="com.huang.pojo.Student" scope="prototype">
        <property name="name" value="huangyuhang"/>
        <property name="address" ref="address" />
bean>
  public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        Student student=(Student) context.getBean("student");
        Student student1=(Student)context.getBean("student");
        System.out.println(student==student1);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ORPafMbj-1609411012083)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203193350602.png)]

4.3几大web作用域对象

session

application

request

websocket

此四大对象只能在web开发中使用到

5.bean的自动装配(Autowired)

自动装配事sping满足bean依赖一种方式

spring会在上下文中自动寻找,并自动给bean装配属性

在spring中又三种装配方式

​ 1.xml显示配置

    <bean id="dog" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="people" class="com.huang.autowiredtest.pojo.People">
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
        <property name="name" value="huang"/>
    bean>


实体类

public class Cat {
    public void shout(){
        System.out.println("miaomiao");
    }
}


public class Dog {

    public void shout(){
        System.out.println("wangwang");
    }
}

public class People {
    private Dog dog;
    private Cat cat;
    private String name;

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public String getName() {
        return name;
    }

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

Test类
    public class AutoWiredTest {
    @Test
    public void testAutoWired(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        People people = context.getBean("people", People.class);
        people.getCat().shout();
        people.getDog().shout();
    }
}



[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DST3qIgq-1609411012084)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203200035236.png)]

​ 2.java显示配置

​ 3.隐式的自动装配Bean(重要)

第一种:

​ 通过autowire=byName属性

  <bean id="dog" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="people" class="com.huang.autowiredtest.pojo.People" autowire="byName">
        <property name="name" value="huang"/>
    bean>

public class AutoWiredTest {
    @Test
    public void testAutoWired(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        People people = context.getBean("people", People.class);
        people.getCat().shout();
        people.getDog().shout();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OwOmlOSG-1609411012086)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203200219228.png)]

如果将cat名字改掉

   <bean id="dog" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat111" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="people" class="com.huang.autowiredtest.pojo.People" autowire="byName">
        <property name="name" value="huang"/>
    bean>

public class AutoWiredTest {
    @Test
    public void testAutoWired(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        People people = context.getBean("people", People.class);
        people.getCat().shout();
        people.getDog().shout();
    }
}

会导致空指针异常找不到cat

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jB6WbDLm-1609411012086)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203200332235.png)]

如果将autowire=byType

   <bean id="dog" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat111" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="people" class="com.huang.autowiredtest.pojo.People" autowire="byType">
        <property name="name" value="huang"/>
    bean>

public class AutoWiredTest {
    @Test
    public void testAutoWired(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");
        People people = context.getBean("people", People.class);
        people.getCat().shout();
        people.getDog().shout();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OLrkCJVT-1609411012088)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203200504576.png)]

总结:byName会自动在容器上下文中查找,和自己对象set方法后的值对应的beanId

​ byType会自动在容器上下文中查找,和自己对象属性类型相同的bean(要保证类型全局唯一,且byType可以将beanid省略,把cat的beanid和dog的beanid去掉)

byname:需要保证所有的baan的id唯一,且bean需要和自动注入属性的set方法的值一致

byType:需要保证所有bean的class唯一,且这个bean需要和自动注入的属性的类型一致

5.1注解实现自动装配

jdk1.5 spring2.5就支持了

使用注解须知:
1.导入配置约束 context约束

​ 2.配置注解的支持




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

    <context:annotation-config/>

beans>

@AutoWired:直接在属性上放置即可,可以忽略set方法在实体类中

使用AutoWired我们可以不用编写set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字Byname

科普:

@nullable:字段标记了这个注解,说明这个字段可以为null
@Autowired(required=false):显示定义了autowired属性为false,说明这个对象可以为null,否则不允许为空
@qualifier(value="xxx")可以在实体类中的属性名上自定义名字,然后与bean文件中的id名一致即可

​ 如果@AutoWired自动装配环境比较复杂,自动装配无法通过一个注解[@Autowired]完成的时候,我们可以使用@qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象(Autowired与qualifier是一套)


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    
   
        
    <context:annotation-config/>
    
    <bean id="dog11" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat21" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="dog111" class="com.huang.autowiredtest.pojo.Dog"/>
    <bean id="cat222" class="com.huang.autowiredtest.pojo.Cat"/>
    <bean id="people" class="com.huang.autowiredtest.pojo.People" />

beans>

public class People {
    @Autowired
    @Qualifier(value = "dog111")
    private Dog dog;
    @Autowired
    @Qualifier(value = "cat21")
    private Cat cat;
    private String name;
    public Dog getDog() {
        return dog;
    }
    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
注意:当配置了@autowired时候,set方法可以省略。

还有一个注解是@Resource(先通过bean名字去查找,然后通过名字去查找,都失败情况下报错,可以指定名字:@Resource(name=“xxx”))




5.2@AutoWired与@Resource区别

都是用来自动装配的,放在属性字段上

@AutoWired通过byType,必须要求对象存在

@Resource是先通过byName注入,再byType注入

执行顺序不同:AutoWired默认通过byType的方式实现

​ Resource默认通过byname实现

@AutoWired如果不能唯一自动装配属性,则需要@qualifier(value=“xxxx”)配合实现

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入

@Resource默认按 byName自动注入罢了。

@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
  @Resource装配顺序

1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

@Autowired 与@Resource的区别:

1、 @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,

总结:

​ @Autowired//默认按type注入
​ @Qualifier(“cusInfoService”)//一般作为@Autowired()的修饰用
​ @Resource(name=“cusInfoService”)//默认按name注入,可以通过name和type属性进行选择性注入

一般@Autowired和@Qualifier一起用,@Resource单独用。

6.Spring注解开发

使用注解开发,必须保证aop包导入

6.1 bean

//Component 组件
@Component
public class User {
    public String name="huang";

}

<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:component-scan base-package="com.huang.pojo"/>
    
    <context:annotation-config/>
beans>

6.2属性如何注入

@Component
public class User {
    @Value("黄宇航")
    public String name;

}
 <bean id="user" class="com.huang.pojo.User">
        <property name="name" value="黄宇航"/>
 bean>
这段代码就相当于上面的代码,value对应property
bean id=xxx对应于component注解

6.3衍生的注解

@component有几个衍生注解,在web开发中,会按照mvc三层架构分层

dao层 @Repository

service层 @service

controller @congtroller

这四个注解功能是一样的,都是代表将某个类注册到spring容器中,装配bean

6.4自动装配置

@Autowired

@nullable

@resource

@qualifier

6.5作用域

@Scope

单例模式

原型模式

//Component 组件
@Component
@Scope("singleton")
public class User {
    @Value("黄宇航")
    public String name;

}

6.6小结

xml与注解

  • xml更加万能,适用于任何场合,维护简单方便
  • 注解:不是自己类使用不了,维护相对复杂

xml与注解最佳实践:

  • ​ xml用来管理bean
  • ​ 注解只负责完成属性的注入
  • 在使用过程中,只需要注意一个问题,必须让注解生效,就需要开启注解的支持
   
    <context:component-scan base-package="com.huang.pojo"/>
    
    <context:annotation-config/>

7.使用javaConfig实现配置

使用java方式配置spring

完全不适用spring的xml配置了,全权交给java来做

javaConfig是Spring一个子项目,在Spring4之后,成为了一个核心内容。

8.AOP

8.1代理模式

为什么要学代理模式?因为这就是SpringAOP的底层【SpringAop和SpringMVC】

代理模式分类:

​ 静态代理:

​ 动态代理:

静态代理代码步骤:

​ 1.接口

public interface Rent {
    public void rent();
}

​ 2.真实角色

public class LandLord implements Rent {
    public void rent() {
        System.out.println("房东要出租房子");
    }
}

​ 3.代理角色

//出了出租房子以外,其余皆是附属操作
public class Proxy implements Rent {
    private LandLord landLord;
    public Proxy(LandLord landLord) {
        this.landLord = landLord;
    }
    public Proxy() {
    }
    //房东出租房子
    public void rent() {
        seeHouse();
        landLord.rent();
        contact();
        fare();
    }
    public void seeHouse(){
        System.out.println("看房子");
    }
    public void fare(){
        System.out.println("收房费");
    }
    public void contact(){
        System.out.println("签合同");
    }

}

​ 4.客户端访问代理角色

 public static void main(String[] args) {
        //房东要租房子
        LandLord landLord=new LandLord();
        //代理,中介帮房东租房子,但会有一些附属操作
        Proxy proxy=new Proxy(landLord);
        proxy.rent();
    }

代理模式的好处:

​ 可以使真是角色的操作更加纯粹,不用关注一些公共业务

​ 公共就交给代理角色,实现业务的分工

​ 公共业务发生扩展时候,方便集中管理

缺点:

​ 一个真实角色就会产生一个代理角色;代码量会翻倍。开发效率会变低

8.2AOP思想图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oCFkSaMl-1609411012089)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201209181811321.png)]

就是在不改变原有的代码基础上,实现新的方法

8.3动态代理

​ 动态代理和静态代理角色一样

​ 动态代理的代理类是动态生成的,不是我们直接写好的

动态代理分为两大类:基于接口的动态代理,基于类的动态代理。

  • ​ 基于接口:JDK动态代理
  • ​ 基于类:cglib
  • ​ java字节码实现:javasist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

InvocationHandler:是一个接口,位于java.lang.reflect包下

动态代理:

public interface Rent {
    public void rent();
}

//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }
    //生成得到代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果(处理代理的人)
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现
        Object invoke = method.invoke(rent, args);
        return invoke;
    }
}

public class Client {
    public static void main(String[] args) {
        //真实角色
        LandLord landLord=new LandLord();
        //代理角色,现在没有
        ProxyInvocationHandler pih=new ProxyInvocationHandler();
        //通过调用程序处理角色来处理我们要调用的接口对象
        pih.setRent(landLord);
        Rent proxy = (Rent) pih.getProxy();//proxy是动态生成的,并没有写
        proxy.rent();
    }
}

改写:万能动态代理:

public interface IHuYaNan {
    public void add();
    public void delete();
    public void update();
    public void query();
}
public class HuYaNanImpl implements IHuYaNan {
    public void add() {
        System.out.println("add方法");
    }

    public void delete() {
        System.out.println("delete方法");
    }

    public void update() {
        System.out.println("update方法");
    }

    public void query() {
        System.out.println("query方法");
    }
}

//用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;
    
    public void setTarget(Object target) {
        this.target = target;
    }
    //生成得到代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果(处理代理的人)
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现
        log(method.getName());
        Object invoke = method.invoke(target, args);

        return invoke;
    }
    public void log(String name){
        System.out.println("debug:"+name);
    }
}

public class Client {
    public static void main(String[] args) {
        HuYaNanImpl huYaNan=new HuYaNanImpl();
        ProxyInvocationHandler proxyInvocationHandler=new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(huYaNan);//设置要代理的对象
        IHuYaNan proxy = (IHuYaNan) proxyInvocationHandler.getProxy();//注:是接口类型!
        proxy.delete();
    }
}

Proxy:s是生成动态代理实例的

InvocationHandler:调用处理程序并返回一个结果

动态代理好处:

  • ​ 一个动态代理的是一个接口,一般是对应一类业务
  • ​ 一个动态代理类可以代理多个类,只要是实现了同一个接口即可

8.4AOP实现方式一(API接口)

创立接口,定义接口中的业务方法
public interface IUserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

实现接口中的方法
public class UserServiceImpl implements IUserService {
    public void add() { System.out.println("add方法被调用了"); }
    public void delete() { System.out.println("delete方法被调用了"); }
    public void update() { System.out.println("update方法被调用了"); }
    public void select() {System.out.println("select方法被调用了");}
}

定义log类
public class Log implements MethodBeforeAdvice {
    //method:要执行的目标对象的方法;objects:参数 object:target
    public void before(Method method, Object[] objects, Object o) throws Throwable 	   {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}

定义afterlog类
public class AfterLog implements AfterReturningAdvice {
    //returnValue:返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了;返回结果为"+returnValue);
    }
}

定义配置文件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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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="userService" class="service.UserServiceImpl" />
        <bean id="log" class="log.Log"/>
        <bean id="afterlog" class="log.AfterLog"/>

        <!--aop配置导入aop约束-->
    <!--方式一-->
    <aop:config>
        <!--切入点(在哪个地方执行我们需要的spring方法);expression:表达式  execution:要执行的位置(* * * * *) -->

        <aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

        
        
测试类
注意:★☆★☆★☆getbean返回的类型一定要转换成接口类型,而不是serviceimpl类型★☆★☆★☆★☆
public class AopTest {
    @Test
    public void aopTest(){
		ApplicationContext context = new 			ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理代理的是一个接口
        IUserService userService = (IUserService) context.getBean("userService");
        userService.add();
    }
}


8.5方式二自定义类实现AOP(主要是切面定义)

步骤一:先自定义一个log类
public class DIYPointCut {
    public void before(){

        System.out.println("before被调用了");
    }
    public void after(){
        System.out.println("after被调用了");
    }
}

步骤二: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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">


    <bean id="DiyPointCut" class="diy.DIYPointCut"/>
        
步骤三:配置aop:config        
        
        
        
    <aop:config>
         <!--这句话的意思是找到一个类的所有方法,并且不管有多少参数-->
        <aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <aop:aspect ref="DiyPointCut">
            <aop:after method="after" pointcut-ref="pointcut"/>
           <aop:before method="before" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>


</beans>

8.6方式三使用注解实现

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    @After("execution(* service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }
    @Before("execution(* service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }

    @Around("execution(* service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前");
//        获得签名
        Signature signature=joinPoint.getSignature();
        System.out.println("signature:"+signature);

        Object proceed = joinPoint.proceed();
        System.out.println("环绕后");
    }
}


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="userService" class="service.UserServiceImpl" />
        <bean id="log" class="log.Log"/>
        <bean id="afterlog" class="log.AfterLog"/>

    <bean id="annotationPointCut" class="annotationpointcut.AnnotationPointCut"/>
    
    <aop:aspectj-autoproxy />
beans>
public class AopTest {
    @Test
    public void aopTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService userService = (IUserService) context.getBean("userService");
        userService.add();
    }
}

8.7Aop在Spring中的作用

横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如:日志,安全,缓存,事务等等

切面(Aspect):横切关注点被模块化的特殊对象。 是一个类

通知(Advice):切面必须要完成的工作。 类中的一个方法

目标(Target):被通知对象

代理(Proxy):向目标对象应用通知之后创建的对象

切入点(PointCut):切面通知 执行的 地点 的定义

连接点(JointPoint):与切入点匹配的执行点

9.整合Mybatis

9.1第一种整合方式

1.编写数据源配置

2.sqlsessionFactory

3.sqlSessionTemplate(线程安全且可以被多个映射器或者dao共享使用)

spring-dao.xml


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

    
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value="2580"/>
        <property name="url" value="jdbc:mysql://localhost:3306/ee?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&characterEncoding=UTF8"/>
    bean>

    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    bean>

    
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        
            <constructor-arg index="0" ref="sqlSessionFactory"/>
    bean>
    
beans>


/*
	原先的mybatis中的配置文件mybatis-config.xml中的代码就可以省去,spring已经可以将其配置到spring配置中。
	mybatis-config.xml只需要关注typeAliases,和mappers注册即可
*/
mybatis-config.xml


<configuration>

    <typeAliases>
        <package name="com.huang.pojo"/>
    typeAliases>

    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    mappers>
configuration>

4.需要给接口加实现类[]

public interface IUserService {
    public List<User> findAllUser();
}


public class UserServiceImpl implements IUserService {
    //所有操作都使用session,现在都使用sqlsessionTemplate
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    public List<User> findAllUser() {
        IUserService mapper = sqlSession.getMapper(IUserService.class);
        List<User> allUser = mapper.findAllUser();
        return allUser;
    }
}


5.将自己写的实现类注入到spring中

applicationContext.xml

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

    //将spring-dao.xml配置文件导入到applicationContext.xml中,整合成一个配置文件
    <import resource="spring-dao.xml"/>

    <bean id="usermapper" class="com.huang.dao.UserServiceImpl">
        <property name="sqlSession" ref="sqlSession"/>
    bean>

beans>

6.测试使用

public class MybatisAndSpring {
    @Test
    public void test() throws IOException {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService userService = (IUserService) context.getBean("usermapper");
        List<User> allUser = userService.findAllUser();
        for (User user : allUser) {
            System.out.println(user.getName());
        }
    }

9.2第二种整合

10.事务

10.1回顾事务

  • 要么都成功,要么都是失败
  • 事务再项目开发中,十分重要,涉及到数据的一致性,不能马虎
  • 确保完整性和一致性

事务ACID原则:

  • 原子性

  • 一致性

  • 隔离性:多个业务可能操作同一个资源,防止数据损坏

  • 持久性:事务一旦提交,无论系统发生什么问题,结果都不会收到影响,被持久化写入存储器中

10.2Spring中的事务管理

声明式事务:AOP

编程式事务:需要在代码中,进行事务的管理

★★★杂点★★★

public,private,protected三大修饰符的作用域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6vub023J-1609411012091)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201203195455389.png)]

String类型不赋值,默认为空

SpringMVC

1.1MVC

​ model模型(dao,service)

​ 数据模型:提供要展示的数据,因此包含数据和行为,可以认为式领域模型或javaBean组件

​ view(视图jsp)

​ :负责进行模型的展示,一般就是用户界面

​ controller(servlet)

​ :接收用户请求,委托给模型进行处理(状态改变),处理完毕后吧返回的模型数据返回给视图,由视图负责展示(调度员作用)

前端 数据传输 实体类

实体类:用户名,密码。。。。。20个字段

登录功能:只需要用户名和密码,其余字段不需要,浪费

pojo细分:

​ pojo:User

​ vo:UserVo

​ dto:

1.2初识SpringMVC

特点:轻量级

​ 高效

​ 与spring兼容性好,无缝结合

​ 约定大于配置

​ 功能强大:RESTful,数据验证、格式化、本地化、主题等

​ 简洁灵活

原理:

​ 当发起请求时候被前置控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者

  1. HanderMapping为处理器映射,DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
  2. HandlerExecution表示具体的Handler,主要作用识根据url查找控制器,如上url被查找控制器为hello
  3. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
  4. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
  5. Handler让具体的Controller执行
  6. Controller将具体执行的信息返回给HandlerAdapter,如ModelAndView
  7. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
  8. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
  9. 视图解析器将解析的逻辑视图名传给DispatcherServlet
  10. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
  11. 最终将视图呈现给用户

1.3注解RequestMapping

@RequestMapping注解用于映射url到控制器或一个特定的处理程序方法。可用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

2.Restful风格

1.概念:Restful就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更加简洁,更有层次,更易于实现缓存等机制

功能:

​ 资源:互联网所有的事物都可以被抽象为资源

​ 资源操作:使用POST,DELETE,PUT,GET使用不同方法对资源进行操作

​ 分别对应:添加、删除、修改、查询

2.传统方式操作资源:通过不同的参数来实现不同的效果,方法单一,post和get

  • http://127.0.0.0/item/queryItem.action?id=1 查询 GET
  • http://127.0.0.0/item/saveItem.action 新增,POST
  • http://127.0.0.0/item/updateItem.action 更新,POST
  • http://127.0.0.0/item/deleteItem.action?id=1 删除,GET或POST

3.使用Restful操作资源:可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但功能可以不同

  • ​ http://127.0.0.1/item/1 查询 GET
  • ​ http://127.0.0.1/item 新增,POST
  • ​ http://127.0.0.1/item 更新 PUT
  • ​ http://127.0.0.1/item/1 删除 DELETE

4.在SpringMVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URL模板变量上

未加@pathvariable注解之前
@Controller
public class RestfulController {
//原路径 http://localhost:8080/huang/add?a=1&b=2 执行是成功的
    @RequestMapping("/add")
    public String restfulTest(int a,int b,Model model){
        int res=a+b;
        model.addAttribute("msg","结果是"+res);
        return "restful";
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZV3xM5Fv-1609411048537)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201226160420168.png)]

加了注解@PathVariable
    路径未http://localhost:8080/abb/1/2
    @RequestMapping("/abb/{a}/{b}")
    public String restfulTest1(@PathVariable int a,@PathVariable int b,Model model{
        int res=a+b;
        model.addAttribute("msg","结果"+res);
        return "restful";
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWrD5zXC-1609411048540)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201226161221719.png)]

value与path作用相同,但当把value换成name,资源访问失败,找不到资源   
 方式1
    @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
public String test2(@PathVariable int a,@PathVariable int b,Model model){
        int res=a+b;
        model.addAttribute("msg","test2的结果为"+res);
        return "restful";
}

方式2
       @RequestMapping(path = "/add/{a}/{b}",method = RequestMethod.GET)
public String test2(@PathVariable int a,@PathVariable int b,Model model){
        int res=a+b;
        model.addAttribute("msg","test2的结果为"+res);
        return "restful";
}
方式3
    当没有value或者path时候,method方法不能使用,且不知道为什么路径后面会多个 
@RequestMapping("/add/{a}/{b}")
public String test2(@PathVariable int a,@PathVariable int b,Model model){
        int res=a+b;
        model.addAttribute("msg","test2的结果为"+res);
        return "restful";
}



[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OeZ1TWac-1609411048541)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201226233204885.png)]

@RequestMapping(name = "/add/{a}/{b}",method = RequestMethod.GET)
public String test2(@PathVariable int a,@PathVariable int b,Model model){
        int res=a+b;
        model.addAttribute("msg","test2的结果为"+res);
        return "restful";
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VHJ0jP7q-1609411048545)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201226232649141.png)]

3.SpringMVC结果跳转方式

ModelAndView

public class NoAnnocationController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView md=new ModelAndView();
        md.addObject("msg","Hello,NoAnnotationController");
        md.setViewName("/noController");
        return md;
    }
}

通过Request和Response

没有视图解析器时候
    @Controller
public class RedirectOrRequest {

    @RequestMapping("/test/t1")
    public String test(Model model){

        model.addAttribute("msg","test");
        //转发
        return "/WEB-INF/jsp/restful.jsp";
    }

    @RequestMapping("/test/t2")
    public String test2(Model model){

        model.addAttribute("msg","test2");
        //转发 地址不变
        return "forward:/WEB-INF/jsp/restful.jsp";
    }


    @RequestMapping("/test/t3")
    public String test3(){
        //重定向 地址栏会变化
        return "redirect:/index.jsp";
    }


}

当有视图解析器的时候
@Controller
public class RedirectOrRequest {
   @RequestMapping("/test/t1")
   public String test(Model model){
        model.addAttribute("msg","test:转发");
       //转发返回的字符串就是视图名,转发地址不变
        return "restful";
    }

    @RequestMapping("/test/t2")
    public String test2(Model model){
    	//重定向地址栏会发生变化
        model.addAttribute("msg","test2:重定向");
        return "redirect:/index.jsp";
    }

}

3.1接收请求参数以及数据回显

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private int age;
}


@Controller
@RequestMapping("/user")
public class UserController {
    @GetMapping("/t1")
    public String test(String name, Model model){
        //1.接收前端参数
        System.out.println("接收前端参数"+name);
        //2.将返回的结果传递给前端
        model.addAttribute("msg",name);
        //3.跳转视图
        return "restful";
    }
}

当网址站中的参数传递,当传递的参数名为name时候,可以完成传参,别的名字不行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vn14DtNo-1609411048547)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201227165111485.png)]

当name改成username时
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xMcanKtk-1609411048550)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201227165152258.png)]

如何能自定义名,让username也同样生效
      @GetMapping("/t2")
    public String tes2(@RequestParam("username") String name, Model model){
        //1.接收前端参数
        System.out.println("接收前端参数"+name);
        //2.将返回的结果传递给前端
        model.addAttribute("msg",name);
        //3.跳转视图
        return "restful";
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOV36K2c-1609411048551)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201227165902749.png)]

当前端提交的是一个对象的时候,要求提交的表单域和对象的属性名一致,参数使用对象即可
    
     @GetMapping("/t2")
    public String test3(User user){
        return "restful";
    }
}

如果使用对象的话,前端传递的参数名和对象必须一致,否则就是null

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N002lL31-1609411048553)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201227171927989.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CxMu62Ba-1609411048554)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201227172017209.png)]

数据显示到前端:
    第一种
    public class ControllerTest1 implements Controller{
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse){
        ModelAndView md=new ModelAndView();
        md.addObject("msg","Hello,NoAnnotationController");
        md.setViewName("/noController");
        return md;             
        }               
    }

第二种
    @RequestMapping("/test/hello")
    public String test(@RequestParam("username")String name.Model model){
    	//相当于req.setAttribute("name",name)	
    	model.addAttribute("msg","test/hello");
    	System.out.println(name);    	
    	return "restful";    
}
第三种
    

4.乱码解决问题

4.1第一种猜想方案(失败)

​ springmvc中的项目,来方法中配置了HttpServletRequest,HttpServletResponse设置编码为utf-8依旧不成功

@Controller
public class EncodingController {
    @RequestMapping("/encode/test")
    public String test1(Model model, String name, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        System.out.println(name);
        model.addAttribute("msg",name);
        return "restful";
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tRbrLpc7-1609411048556)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201229222559793.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLzy59Qm-1609411048556)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201229222613555.png)]

4.2配置springMVC过滤器

web.xml中
    配置springmvc的过滤器
      <filter>
        <filter-name>encoding</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>encoding</filter-name>
        
        <url-pattern>/*
    




★★★★★★★★★★★重点内容 ★★★★★★★★★★★
  <url-pattern>/*
  /*
  /二者之间的区别
  /*匹配所有的url,包括带有扩展名的,一般只用于在过滤器上
  /是可以拦截“.js”,“.css”,".png"等静态资源的访问
  除了能够处理静态资源外还能处理http缓存请求,媒体数据流,和文件下载简历
  且项目中如果配置了/会覆盖掉tomcat默认的default servlet
  
  当配置了/
  有两种配置方式
   第一种:
    
        
        
        

    
        

  
  
         

5.JSON

5.1json介绍

​ 前后端分离时代:

​ 后端部署后端:提供接口,提供数据

	1.JSON(JavaScript Object Notation,JS对象标记):轻量级,文本格式(相当于java中的字符串),能够有效提升网络传输效率
    
    对象表示为键值对,数据由逗号分隔
    花括号保存对象
    方括号保存数组
    {”name“:"huangyunang"}
    {”age“:"18"}
    {”sex“:"男"}
    2.JSON是javaScript对象的字符串表示法,使用文本表示一个JS对象的信息,本质是一个字符串
        
        JSON和JavaScript对象互转
        2.1)要实现从json字符串转换为javaScript对象使用JSON.parse()方法
    	2.2)要实现从javaScript对象转换为JSON字符串,使用JSON.stringify()方法
    

​ 前端独立部署,负责渲染后端的数据

5.2json互相转换

步骤一 
    创建一个静态html,与index.jsp同目录
   
遇到的问题:静态资源访问不到
    	  动态资源可以访问
    
解决问题:在web.xml文件中加入
      <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

步骤二:    
    var user={
            name:"黄宇航",
            age:3,
            sex:"男"
       };
        //将js对象转为json对象
        var s = JSON.stringify(user);
        //将json转为js对象
        var parse = JSON.parse(s);
        console.log(s);
        console.log(parse);
    </script>

5.3JackSon使用

步骤一
    创建User实体类
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private String name;
        private String sex;
        private int age;
    }


<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">
    <servlet>
        <servlet-name>springmvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:springmvc-servletparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>

    
    <servlet-mapping>
        <servlet-name>springmvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>


    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        <url-pattern>*.htmlurl-pattern>
    servlet-mapping>

    <filter>
        <filter-name>encodingfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>utf-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>encodingfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

web-app>
springmvc-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="com.huang.controller" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <mvc:annotation-driven />

</beans>
UserController
@Controller
public class UserController {
    @RequestMapping("/json")
    @ResponseBody//加了这个注解,就不会走视图解析器,直接返回一个字符串
    public String jsonTest(){
        //创建一个对象
        User user=new User("黄宇航","男",18);

        return user.toString();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0aSrQq51-1609411048558)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230221727343.png)]

将数据转为json
    UserController
    @Controller
public class UserController {
    @RequestMapping("/json")
    @ResponseBody//加了这个注解,就不会走视图解析器,直接返回一个字符串
    public String jsonTest() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        //创建一个对象
        User user=new User("黄宇航","男",18);
        String str = mapper.writeValueAsString(user);
        return str;
    }
}

    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EgB2zSev-1609411048559)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230222116753.png)]

@Controller
public class UserController {
    第一种方式:在注解上加入produces属性
    @RequestMapping(value="/json",produces = "application/json;charset=utf-8")
    @ResponseBody//加了这个注解,就不会走视图解析器,直接返回一个字符串
    public String jsonTest() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        //创建一个对象
        User user=new User("黄宇航","男",18);
        String str = mapper.writeValueAsString(user);
        return str;
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdBMAauj-1609411048560)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230222511510.png)]

5.4乱码优化统一解决

springmvc-servlet.xml
   第二种方式:
    加入固定配置,只要使用json
    
    <!--Json乱码问题配置-->
    <mvc:annotation-driven >
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

@Controller
public class UserController {
    @RequestMapping(value="/json")
    @ResponseBody//加了这个注解,就不会走视图解析器,直接返回一个字符串
    public String jsonTest() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        //创建一个对象
        User user=new User("黄宇航","男",18);
        String str = mapper.writeValueAsString(user);
        return str;
    }
}

5.5@Controller和@RestController区别

@RestController
下面的所有方法都只会返回json字符串,不加这个@ResponseBody注解
@Controller是返回视图解析器  与@ResponseBody配合使用返回json字符串

5.6json不同的对象

json一个字符串
@Controller
public class UserController {
    //    字符串
    @RequestMapping("/json")
    @ResponseBody//加了这个注解,就不会走视图解析器,直接返回一个字符串
    public String jsonTest() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        //创建一个对象
        User user=new User("黄宇航","男",18);
        String str = mapper.writeValueAsString(user);
        return str;
    }

json一个数组
//   数组
    @RequestMapping("/json2")
    @ResponseBody
    public String jsonTest2() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        List<User> users=new ArrayList<User>();

        User user1=new User("胡雅楠","25",2);
        User user2=new User("黄宇航","25",2);
        User user3=new User("施叶","25",2);
        User user4=new User("杨琪","25",2);
        User user5=new User("颜钰静","25",2);

        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);
        String s = mapper.writeValueAsString(users);
        return s;

    }
//时间戳
json一个时间戳
    @RequestMapping("/json3")
    @ResponseBody
    public String jsonTest3() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        Date date=new Date();
        //自定义日期格式
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //ObjectMapper,时间解析后的默认格式为:Timestamp。时间戳
//        return mapper.writeValueAsString(date);
        return mapper.writeValueAsString(sdf.format(date));
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p5WLdxiI-1609411048562)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230230059063.png)]

另一种时间戳方式
      //时间戳
    @RequestMapping("/json4")
    @ResponseBody
    public String jsonTest4() throws JsonProcessingException {
        ObjectMapper mapper=new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        //自定义日期格式
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        mapper.setDateFormat(sdf);
        Date date=new Date();
        return mapper.writeValueAsString(sdf.format(date));

    }
与上面等同

后述还在自学中,第一次整理,有部分缺少,后续补上,激励 一下,哎嘿嘿

你可能感兴趣的:(2020-12-31小黄自学文档整理(其实是小白,因为姓黄))