第十周总结-day55-59

LayUI

LayUI异步登录1.页面

<body>
<div id="container">
    <div></div>
    <div class="admin-login-background">
        <div class="admin-header">
            <span>layuimini</span>
        </div>
        <form id="form" class="layui-form">
            <div>
                <i class="layui-icon layui-icon-username admin-icon"></i>
                <input type="text" name="username" id="username" placeholder="请输入用户名" autocomplete="off" class="layui-input admin-input admin-input-username" value="admin">
            </div>
            <div>
                <i class="layui-icon layui-icon-password admin-icon"></i>
                <input type="password" name="password" id="password" placeholder="请输入密码" autocomplete="off" class="layui-input admin-input" value="123456">
            </div>
            <div>
                <input type="text" name="captcha" placeholder="请输入验证码" autocomplete="off" class="layui-input admin-input admin-input-verify" value="xszg">
                <img class="admin-captcha" width="90" height="30" src="../images/captcha.jpg">
            </div>
            <button   class="layui-btn admin-button" lay-submit="" lay-filter="login">登 陆</button>
        </form>
    </div>
</div>
<!--jquery的js文件-->
<script src="/LayUI_war_exploded/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script>
<script src="/LayUI_war_exploded/lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<!--layUI--脚本--表单模块-->
<script>
    layui.use(['form'], function () {
        var form = layui.form,
            layer = layui.layer;

        // 登录过期的时候,跳出ifram框架
        if (top.location != self.location) top.location = self.location;

        // 进行登录操作
        //layUI表单提交操作
       form.on('submit(login)', function (data) {
            data = data.field; //将原生js对象转换成layUi里面的js对象
            //alert(data.username+"--"+data.password) ;
            if (data.username == '') {
                layer.msg('用户名不能为空');
                return false;
            }
            if (data.password == '') {
                layer.msg('密码不能为空');
                return false;
            }
            //忽略验证码
            if (data.captcha == '') {
                //layer.msg('验证码不能为空');
                return true;
            }

            //jquery的ajax
            $.ajax({
                url:"/LayUI_war_exploded/admin_login",
                type:"post",
                //发送json数据---JSON.stringfy(
                data: JSON.stringify(data) , //data {"username":xx","password":"xxx"}
                //规定发送的数据格式是json格式
                contentType:"applicaton/json",
                success:function(resp){ //服务器响应数据---解析成json
                    //处理resp
                    layer.msg(resp.msg, function () {
                        window.location = '/LayUI_war_exploded/index.html';
                    })
                },
                dataType:"json" //服务器响应格式
            })
           /* layer.msg('登录成功', function () {
                window.location = '/index.html';
            });*/
            return false;
        });
    });
</script>
</body>

LayUI异步登录2.servlet

@WebServlet("/admin_login")
public class AdminLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //这种方式不适合:前端application/json 数据格式
        //String username = request.getParameter("username");
        //System.out.println(username);

        //创建Map集合----存放前端提交所有参数
        Map<String,Object> parms = new HashMap<>() ;

        //获取前端提交的字节输入流
        ServletInputStream inputStream = request.getInputStream() ;
        //commons-IO-提供 IOUtils
        //public String toString(InputStream inputstraem,String encoding)
        //参数1:获取到post提交的内容 -- 保存在字节输入流中 (获取到流的内容)
        //参数2:编码 :支持utf-8
        String jsonStr = IOUtils.toString(inputStream, "utf-8");
        System.out.println(jsonStr) ;//{"username":"李国栋","password":"123456","captcha":"xszg"}
        //fastjson.jar包-- 工具栏JSON--将上面的这个json传解析成实体
        //JSONObject parseObject(String text, Class<T> class):参数1:获取json串,参数2:将对应的内容存在实体中,当前类型的字节码文件
        Map map = JSON.parseObject(jsonStr, Map.class);
        //System.out.println(map) ;//{password=123456, captcha=xszg, username=梁飞虎}
        parms.putAll(map) ;
        //遍历parms
       /* Set<Map.Entry<String, Object>> entries = parms.entrySet();
        for(Map.Entry<String,Object> entry:entries){
            //获取键和值
            String key = entry.getKey();
            String value = (String) entry.getValue();
            System.out.println(key+"--"+value);
        }*/
        String username = (String) parms.get("username");
        String password = (String) parms.get("password");
        System.out.println(username+"---"+password) ;
        //调用业务接口,通过用户名和密码完成登录逻辑
        AdminService adminService = new AdminServiceImpl() ;
        BaseResp baseResp = adminService.getAdminByName(username, password);
        //解析成json格式
        JSONObject jsonObject = new JSONObject() ;
        String  baseRespStr= jsonObject.toJSONString(baseResp);
        System.out.println(baseRespStr) ;
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(baseRespStr) ;
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }
}

LayUI一步登陆3.service/dao

public class AdminServiceImpl  implements  AdminService{
    /**
     * 获取管理员信息,返回响应实体
     * @param username 管理员名称
     * @param password 密码
     * @return 返回结果对象
     */
    @Override
    public BaseResp getAdminByName(String username, String password) {
        try {
            AdminDao adminDao = new AdminDaoImpl() ;
            Admin admin = adminDao.selectAdminByName(username);
            if(admin!=null){
                //判断管理员密码
                if(password.equals(admin.getPassword())){
                    return  new BaseResp(0,"登录成功",null,null) ;
                }
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //没有查到
        return new BaseResp(1,"error",null,null) ;
    }
}

public class AdminDaoImpl  implements AdminDao {
    @Override
    public Admin selectAdminByName(String username) throws SQLException {
        QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
        String sql = "select * from admin where username = ?" ;
        Admin admin = qr.query(sql, new BeanHandler<>(Admin.class), username);
        return admin;
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseResp {

    private Integer code ; //0表示数据,1表示没有数据
    private String msg ; //消息字符串提示内容
    private Object data ; //响应实际内容:实体或者list或者Map
    private Integer count ; //总记录
}

LayUI表格使用

 {
          "title": "用户管理",
          "href": "",
          "icon": "fa fa-flag-o",
          "target": "_self",
          "child": [
            {
              "title": "查询用户",
              "href": "/LayUI_war_exploded/page/admin/user_list.html",
              "icon": "fa fa-stumbleupon-circle",
              "target": "_self"
            }
          ]
        },

<head>
    <meta charset="UTF-8">
    <title>用户列表页面</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="/LayUI_war_exploded/lib/layui-v2.5.5/css/layui.css" media="all">
  <link rel="stylesheet" href="/LayUI_war_exploded/css/public.css" media="all">
</head>
<body>

    <script type="text/html" id="toolbarDemo">
      <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm data-add-btn"> 添加用户 </button>
        <!--   <button class="layui-btn layui-btn-sm layui-btn-danger data-delete-btn"> 删除用户 </button>-->
      </div>
    </script>

    <!--删除-->
    <script type="text/html" id="barDemo">
      <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
    </script>

    <!--layui的过滤属性值-->
    <table class="layui-hide"
           id="currentTableId"

           lay-filter="currentTableFilter"></table>

    <script type="text/html" id="currentTableBar">
      <a href="shopadd.html" class="layui-btn layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
      <a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
    </script>

  </div>
</div>
<script src="/LayUI_war_exploded/lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<script src="/LayUI_war_exploded/lib/jquery-3.4.1/jquery-3.4.1.min.js" charset="utf-8"></script>
<script>

  /*
  *   加载和初始化模块 表单模块,表格模块
  * */
  layui.use([ 'table','util'], function () {
    var table = layui.table, //给表格组件初始化
            util = layui.util;  //表格中的单元格编辑进行初始化

    table.render({
      //发送json数据
      elem: '#currentTableId', //获取当前table标签对象
      url: '/LayUI_war_exploded/findAllUser?page=1&limit=10', // 请求的后台接口
      toolbar: '#toolbarDemo',
      defaultToolbar: ['filter', 'exports', 'print', { //默认的工具栏: 右边:打印,导出,帅选列
        title: '',
        layEvent: 'LAYTABLE_TIPS',
        icon: 'layui-icon-tips'
      }],

      //表格中的数据内容
      cols: [[

        {type: "checkbox", width: 50, fixed: "left"},
              //field:实体属性名称
              //tittle:列的标题名称
        {field: 'uid', width: 80, title: '用户ID', sort: true},
        {field: 'username', width: 80, title: '用户名'},
        {field: 'password', width: 80, title: '密码'},
        {field: 'name', width: 80, title: '真实姓名'},
        {field: 'email', title: '邮箱', minWidth: 150},
        {field: 'birthday', width: 80, title: '出生日期', sort: true},
        {field: 'sex', width: 80, title: '性别'},
        {title: '操作', minWidth: 50, templet: '#currentTableBar', fixed: "right", align: "center"}
      ]],
      limit: 10,
      page: true/*开启分页*/
    });
    
    
   //监听单元格编辑
    //currentTableFilter table标签中的lay-filter属性值
    table.on('edit(currentTableFilter)', function(obj){
      var value = obj.value //得到修改后的值
              ,data = obj.data //得到所在行所有键值
              ,field = obj.field; //得到字段

      // layer.msg('[ID: '+ data.id +'] ' + field + ' 字段更改值为:'+ util.escape(value));
    });  
  
  
  
  
protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {

        //接收参数:page参数以及limit每页显示的条数
        //默认第一页,每页显示15条
        String page = request.getParameter("page");
        String limit = request.getParameter("limit");
        System.out.println(page+"---"+limit) ;
        int page_number = Integer.parseInt(page) ;
        int limit_number = Integer.parseInt(limit) ;

        //调用AdminService
        AdminService adminService = new AdminServiceImpl() ;
        BaseResp baseResp = adminService.findUserByPage(page_number, limit_number) ;

        //转换成json,响应前端
        //FastJson
        JSONObject jsonObject = new JSONObject();
        String jsonString = jsonObject.toJSONString(baseResp);
        System.out.println(jsonString);
        response.setContentType("applicaton/json;charset=utf-8") ;
        response.getWriter().write(jsonString);
    }    

前后端json数据

1.导包

        <!--json解析工具:阿里提供的
            可以将前端发送的json进行解析,
            或者也可以后端获取到数据,转换成json,给前端
        -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        
        <!--commons-io-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

2.前端json(post提交)

 $.ajax({
                url:"/LayUI_war_exploded/admin_login",
                type:"post",
                //发送json数据---JSON.stringfy(
                data: JSON.stringify(data) , //data {"username":xx","password":"xxx"}
                //规定发送的数据格式是json格式
                contentType:"applicaton/json",
                success:function(resp){ //服务器响应数据---解析成json
                    //处理resp
                    layer.msg(resp.msg, function () {
                        window.location = '/LayUI_war_exploded/index.html';
                    })

                },
                dataType:"json" //服务器响应格式

            })

3.后端接收并响应json数据

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //这种方式不适合post提交:前端发送的application/json 数据格式
        //String username = request.getParameter("username");
        //System.out.println(username);

        //创建Map集合----存放前端提交所有参数
        Map<String,Object> parms = new HashMap<>() ;

        //获取前端提交的字节输入流
        ServletInputStream inputStream = request.getInputStream() ;
        //commons-IO-提供 IOUtils
        //public String toString(InputStream inputstraem,String encoding)
        //参数1:获取到post提交的内容 -- 保存在字节输入流中 (获取到流的内容)
        //参数2:编码 :支持utf-8
        String jsonStr = IOUtils.toString(inputStream, "utf-8");//io流数据转换为字符串形式的数据
     
        System.out.println(jsonStr) ;//{"username":"李国栋","password":"123456","captcha":"xszg"}
        //fastjson.jar包-- 工具栏JSON--将上面的这个json传解析成实体
        //JSONObject parseObject(String text, Class<T> class):参数1:获取json串,参数2:将对应的内容存在实体中,当前类型的字节码文件
     
        Map map = JSON.parseObject(jsonStr, Map.class);
        //System.out.println(map) ;//{password=123456, captcha=xszg, username=梁飞虎}
        parms.putAll(map) ;

        //遍历parms
       /* Set<Map.Entry<String, Object>> entries = parms.entrySet();
        for(Map.Entry<String,Object> entry:entries){
            //获取键和值
            String key = entry.getKey();
            String value = (String) entry.getValue();
            System.out.println(key+"--"+value);
        }*/
        String username = (String) parms.get("username");
        String password = (String) parms.get("password");

        //调用业务接口,通过用户名和密码完成登录逻辑
        AdminService adminService = new AdminServiceImpl() ;
        BaseResp baseResp = adminService.getAdminByName(username, password);
        //解析成json格式
        JSONObject jsonObject = new JSONObject() ;
        String  baseRespStr= jsonObject.toJSONString(baseResp);

     
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(baseRespStr) ;

MyBatis

mybatis涉及的设计模式

在这里插入图片描述

mybatis核心配置文档结构

configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
		environment(环境变量)
            transactionManager(事务管理器)
            dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)
    
<?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">
<!--xx.dtd是xml文件约束,约束标签-->
<!--核心配置-->
<configuration>
    <!--属性配置,加载外部配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!--实体类的别名配置-->
    <typeAliases>
        <package name="com.qf.pojo"/>
    </typeAliases>
    <!--配置插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    <!--环境配置-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="com.qf.datasource.MyDruidDataSourceFactory">
                <property name="driverClassName" value="${jdbc.driverClassName}"/>
                <!--连接数据库的地址-->
                <property name="url" value="${jdbc.url}"/>
                <!--用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--登录密码-->
                <property name="password" value="${jdbc.password}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>
            </dataSource>
        </environment>

        <!--配置其他环境-->
    </environments>
    <!--加载mapper映射器-->
    <mappers>
        <!--配置接口的包名-->
        <package name="com.qf.mapper"/>
    </mappers>
</configuration>

属性配置properties

 <!--属性配置,加载外部配置文件-->
    <properties resource="jdbc.properties"></properties>
 
jdbc.properties文件: 
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=10

类型别名配置typeAliases

方式1:指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
<typeAliases>
     <package name="com.qf.pojo"/>
</typeAliases>   


方式2:
  <!--type指定的当前实体类的完全限定名称
            alias:实体的类别名(自己指定,见名知意)
            这种方式麻烦(实体类很多,配置很多个typeAlias),可以直接指定实体类的包名
            所有的实体类的包名就是默认当前类名(建议小写),不区分大小写
        -->
    <typeAlias alias="user" type="com.qf.pojo.User"></typeAlias>
    <typeAlias alias="vouser" type="com.qf.pojo.VoUser"></typeAlias>
    <typeAlias alias="queryvo" type="com.qf.pojo.QueryVo"></typeAlias>

配置插件plugins

分页插件:
<plugins>
        <!--插件里面属性
            interceptor指定当前拦截器
        -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

环境配置environments,druid连接池

1.配置druid连接池
  <!--环境配置,默认属于mysql数据库-->
    <environments default="mysql">
        <!--可以配置多个环境-->
        <environment id="mysql">
            <!--mybatis事务管理器,连接数据库操作-->
            <transactionManager type="JDBC"/>
            <!--启用druid连接池 -->
            <dataSource type="com.qf.datasource.MyDruidDataSourceFactory">
 				<!--配置连接池这个类中的属性参数 -->
                <!-- ${获取外部资源文件的key对应的内容} -->
         <property name="driverClassName" value="${jdbc.driverClassName}"/>
                <!--连接数据库的地址-->
                <property name="url" value="${jdbc.url}"/>
                <!--用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--登录密码-->
                <property name="password" value="${jdbc.password}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>
            </dataSource>
        </environment>

        <!--配置其他环境-->
        <!--<environment id="oracle">
            <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>

自定义数据源工厂--提供德鲁伊的数据源DruidDataSource
public class MyDruidDataSourceFactory  extends PooledDataSourceFactory {
    public MyDruidDataSourceFactory(){
        //给数据源进行初始化
        this.dataSource = new DruidDataSource() ;//创建德鲁伊数据源
    }
}


mybatis自带的连接池
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <!--启用mybatis自带的连接池-->
            <dataSource type="POOLED">
                <!--配置连接池这个类中的属性参数
                    org.apache.ibatis.datasource.pooled.PooledDataSource信息
                -->
                <!--驱动类-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的地址-->
      <property name="url" value="jdbc:mysql://localhost:3306/mybatis_01"/>
                <!--用户名-->
                <property name="username" value="root"/>
                <!--登录密码-->
                <property name="password" value="123456"/>

映射配置mappers

方式1.将包内的映射器接口实现全部注册为映射器

实体类的包名,实体名必须和resources文件下的实体类配置文件的结构一致
com.ddl.mapper.EmployeeDao
配置文件resources下:com.ddl.mapper.EmployeeDao.xml

<!--加载mapper映射器-->
    <mappers>
        <!--配置接口的包名,对应-->
        <package name="com.qf.mapper"/>
    </mappers>


方式2. 使用相对于类路径的资源引用    
    <mappers>
        <!--配置多个mapper-->
     <mapper resource="com/qf/mapper/UserDao.xml"></mapper>
     <mapper resource="com/qf/mapper/ProductDao.xml"></mapper>
     <mapper resource="com/qf/mapper/OrderDao.xml"></mapper>-->
    </mappers>

数据访问接口Dao的配置

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--映射器的配置
    namesapce:名称空间指定接口的完全限定名称
-->
<mapper namespace="com.qf.mapper.UserDao">
        <!--大量的sql标签
            id必须和接口文件中的方法名必须一致
            当前接口中的方法有返回值,返回值如果是实体类型或者是List集合
            输出映射:resultType必须要指定为当前实体类型的完全限定名称
            输入映射 paramterType:如果当前接口中方法形式参数是一个实体类型,写上当前类的完全限定名称
            如果形式参数String/int,写成String/int/Integer
            mybatis中书写sql语句,也必须使用占位符号 #{实体类的属性名称一致}
        -->
      <!--插入用户-->
    <insert id="addUser" parameterType="com.qf.pojo.User">
        insert  into user(username,gender,age,address) values(#{username},#{gender},#{age},#{address})
    </insert>
    <select id="findAll" resultType="com.qf.pojo.User">
        select * from user
    </select>
    <!--更新用户-->
    <update id="updateUser" parameterType="com.qf.pojo.User">
        update user set username=#{username},gender = #{gender},age = #{age},address = #{address}
where id = #{id}
    </update>
    <!--删除用户-->
    <delete id="deleteUser" parameterType="int">
        delete from user where id = #{id}
    </delete>
</mapper>

crud实现

public class MybatisTest {
    private AccountDao accountDao ;
    private UserDao userDao ;
    private SqlSession sqlSession ;
    @Before
    public void init() throws IOException {
        //1)读取resource下面的mybatis-config.xml文件
        //org.apache.ibatis.io.Resources --InputStream getResourceAsStream(配置文件名称)
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //2)创建一个对象SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder() ;
        //3)创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载流对象 获取到工厂对象
        //4)创建 SqlSession---就是执行对象--底层就是PreparedStatement
        //SqlSession sqlSession = sqlSessionFactory.openSession();//自动提交
         sqlSession = sqlSessionFactory.openSession(false);//手动提交
        //5)获取AccountDao接口对象---通过mybatis的动态代理获取接口对象
        //mybatis的写法
      //  accountDao = sqlSession.getMapper(AccountDao.class);//接口类型字节码文件
        //ibatis的写法
        //List<Object> objects = sqlSession.selectList("com.qf.mapper.AccountDao.findAllAccounts");
        //使用动态代理,获得Dao接口的对象
        userDao = sqlSession.getMapper(UserDao.class) ;
    }

  添加实现
 @Test
    public void testAddUser(){
        //封装User对象
        User user = new User() ;
        user.setUsername("张蒋杰3") ;
        user.setGender("男3") ;
        user.setAge(23) ;
        user.setAddress("宝鸡市3") ;
        //调用方法
        userDao.addUser(user);
    	}
    }
  @After
    public void commitAndColose(){
        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

优化–别名配置

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author(不区分大小写);若有注解,则别名为其注解值。见下面的例子:
@Alias("author")
public class Author {
    ...
}
1.mybatis.xml核心配置中:
<typeAliases>
 <package name="com.qf.pojo"/>
 </typeAliases>
2. Dao.xml配置中
<!--<insert id="addUser" parameterType="com.qf.pojo.User" > 优化-->
<insert id="addUser" parameterType="user" >   <!--不区分大小写-->

mybatis模糊查询的语法${} 和 #{}

1.占位符#{}
  <select id="selectUsersByUserName" parameterType="java.lang.String" resultType="user">
        select * from user where username like #{username}
    </select>
<!--select * from user where username like concat(' %’,#{username}, ' %'
其中名为conat(‘%’,#{关键字},‘%’)-->

2.字符串拼接${}
使用字符串拼接符号 ${}  固定写法'%${value}%',不推荐,存在字符串拼接,可能导致sql注入
<select id="selectUsersByUserName" parameterType="java.lang.String" resultType="com.qf.pojo.User">
        select * from user where username like '%${value}%'
    </select>

模糊查询实现
  @Test
    public void testselectUsersByUserName(){
//List<User> users = userDao.selectUsersByUserName("%张%") ;
        List<User> users = userDao.selectUsersByUserName("张") ;
        if(users!=null || users.size()>0){
            for(User user:users){
                System.out.println(user);
            }
        }
    }

mybatis关于添加用户的时候,获取到最后一次插入数据id值

 <insert id="addUser" parameterType="user" >  方式二:在insert标签中useGeneratedKeys="true" keyProrerty="id"
   <!--在插入的时候,获取id自增长主键的值,配置一些函数
   selectKey
         属性
         	keyColumn:表的主键字段名称,仅适用insert和update
         	keyProperty:实体类的属性名称,仅适用insert和update
            resultType:返回值自增长主键的值类型
            order:AFTER:在执行插入语句insert之后执行selectkey的语句获取最后一次id的值
 -->
        <selectKey keyColumn="id" keyProperty="id" resultType="int"  order="AFTER">
            <!--通过这个函数获取最后一次自增长主键的id值-->
            SELECT LAST_INSERT_ID() ; 
        </selectKey>
        insert  into user(username,gender,age,address) values(#{username},#{gender},#{age},#{address})
    </insert>

id主键自增长
public void testAddUser(){
        //封装User对象
        User user = new User() ;
        System.out.println("插入前:"+user) ;
        user.setUsername("张蒋杰3") ;
        user.setGender("男3") ;
        user.setAge(23) ;
        user.setAddress("宝鸡市3") ;

        //调用方法
        userDao.addUser(user);
        System.out.println("插入后:"+user);  //显示自增长的id值

    }

方式二:在insert标签中useGeneratedKeys="true" 
 <insert id="addUser" parameterType="user" >  
     
 
     
通过uuid()查询主键
create table t_order(
id varchar (32)primary key, #字符型主键name varchar(50)
)default charset = utf8;

<mapper namespace="com.qf.mybatis.part1.basic.0rderDao">
<insert id="insert0rder" parameterType="order">
<selectKey keyProperty="id" resultType="String" order="BEFORE" ><!-- 插入之前-->
		SELECT REPLACE (UUID(), '-','')  <!--适用于字符类型主键-->
	</selectKey>
		INSERT INTO t_order(id, name) VALUES(#{id},#{name})
< /insert>
< /mapper>

mybatis多个参数传递

指定多个条件查询用户
方式1:使用mybatis参数绑定注解方式(推荐)
 <!--#{}里面的内容需要和@Param里面的参数名称一致 -->
<select id="findUserByMultConditon" resultType="user">
        select * from user where username = #{username} and address = #{address}
    </select>

//dao层
//启用mybatis的@Param注解--指定绑定参数名称,这个参数名称就是等会需要赋值的参数,自定义(#{参数名称})
    User findUserByMultConditon(@Param("username") String name, @Param("address") String addr) ;



方式2:按照参数的顺序进行查询,param1,param2...
 <!--指定多个条件查询用户
        按照参数的顺序进行查询,param1,param2....依次,不利于管理维护(不推荐)
    -->
   <select id="findUserByMultConditon" resultType="com.qf.pojo.User">
        select * from user where username = #{param1}  and address = #{param2}
    </select>
dao:
User findUserByMultConditon(String name,String addr) 



方式3:使用Map集合
    <!-- #{}里面的内容需要和map集合的key一致 -->
   <select id="findUserByMultConditon" resultType="com.qf.pojo.User">
        select * from user where username = #{name} and address  = #{addr}
    </select>
dao:
  //使用Map集合接收所有参数 --复杂类型
  //  User findUserByMultConditon(Map<String,String> map) ;
实现: 
        Map map = new HashMap() ;
        map.put("name","黄老师") ;
        map.put("addr","咸阳市") ;
        User user = userDao.findUserByMultConditon(map);

 
        
方式4:使用自定义vo实体,将参数放在实体中
    <!--通过vo实体查询指定的用户
         参数形式QueryVo实体类型,里面包含另一个实体属性user属性
         获取到QueryVo对象.getUser().getUsername():获取到用户名
         一个实体类中的getXxx()里面xxx就是实体类的bean属性
         ognl简写表达式  get()去掉,第一个字母小写
    -->
<!--方法参数为对象时,可直接使用#{属性名}进行获取-->
    <select id="findUserByQueryVo" parameterType="queryvo" resultType="user">
            select * from user where username = #{user.username}
    </select>     

dao:       
  //通过自定义的实体类,将查询的参数封装到这个类中
    User findUserByMultConditon(VoUser voUser) ;  
        
实现: 
        VoUser voUser = new VoUser() ;
        voUser.setName("高圆圆") ;
        voUser.setAddr("西安市") ;
        User user = userDao.findUserByMultConditon(voUser);
        System.out.println(user); 
        
@Data
@NoArgsConstructor
@AllArgsConstructor
public class QueryVo {
    private User user ;
}

mybatis分页实现

导包
 <!--mybatis的分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.2</version>
        </dependency>

  
  
  @Test
    public void testFindAll() throws IOException {

        //通过mybatis的分页插件完成分页条件
        //PageHelper父类有一个API---
        //public static <E> Page<E> startPage(int pageNum, int pageSize)
        //当前页码1,每页显示3条
        PageHelper.startPage(1,3) ;
        //6)调用方法
        List<User> users = userDao.findAll(); //获取分页列表数据
        //创建PageInfo对象
        PageInfo pageInfo = new PageInfo(users) ;
    
        System.out.println(pageInfo); //展示分页的数据
        if(users!=null || users.size()>0){
            for(User user :users){
                System.out.println(user);
            }
        }
    }
    
    

日志

 Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging

MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会(按上面罗列的顺序)使用第一个查找到的实现。当没有找到这些实现时,将会禁用日志功能 

     
步骤 1:添加 Log4J 的 jar 包
  <!--log4j的日志包-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
     
步骤 2:配置 Log4J.properties

 # Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
# 全局日志配置
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE


#跟踪具体的接口或者接口中的指定方法
#log4j.logger.com.qf.mapper.UserDao.addEmployee=TRACE,跟踪接口中的指定方法
 # 跟踪具体的接口       
log4j.logger.com.qf.mapper.EmployeeDao=TRACE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
#控制台输出
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n


#本地磁盘上产生日志文件
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
#自定义产生的日志文件路径
log4j.appender.LOGFILE.File=E:/Java/QFJava/mybatis_exercise/log4j.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
     
     

动态sql及常见标签

一.sql标签
 <sql id="mySql">   自定义id名称
        select * from user
    </sql>

    <select id="findUserByCondition"  resultMap="baseMap">
          <include refid="mySql"></include>     include标签引入动态sql
     </select>

二:if标签
针对条件进行判断
   mybatis提供动态sql语句之if标签对 条件的参数进行判断
      if标签的test属性,判断赋值的参数是否为null 

 <select id="selectUserByUsername" parameterType="java.lang.String" resultMap="baseMap">
        select * from user where   1 =1
         <if test="userName!=null">
             and username = #{userName}
         </if>
         <if test="userAddress!=null">
             and address = #{userAddress}
         </if>
    </select>

三:where标签
代替sql语句中的where
  <where>
            <if test="userName!=null">
                username = #{userName}
            </if>
 </where>
 mybatis的where标签
       当前if里面条件参数判断都不成立,最终select * from user where ,出现sql异常
		当前if里面条件参数判断都不成立,使用where标签则没有约束条件
四:trim标签
trim:mybatis动态标签
  帮助写sql语句的时候,指定前缀信息/指定后缀信息/忽略前缀信息/忽略后缀信息
            prefix属性:指定前缀
            prefixOverrides:忽略前缀        and | or
            where条件里面第一个and或者or都可以省略
            suffix=指定的后缀名称
            suffixOverrid es:忽略后缀的信息

<select id="findUserByCondition"  resultMap="baseMap">
  <include refid="mySql"></include>
        <trim prefix="where"  prefixOverrides="and">
        <where>
            <if test="userName!=null">
               username = #{userName}
            </if>
            <if test="userAddress!=null">
                and address = #{userAddress}
            </if>
        </where>
        </trim>
    </select>

五:set标签
 <update id="updateUser" parameterType="user">
<!--mybatis动态sql之set标签
        加入动态标签:动态判断这参数值
-->
            update user
            <set>
                <if test="userName!=null">
                    username = #{userName},
                </if>
                <if test="userGender!=null">
                    gender = #{userGender},
                </if>
                <if test="userAge!=null">
                    age = #{userAge},
                </if>
            </set>
            <where>
                <if test="userId!=null">
                    id = #{userId}
                </if>
            </where>
    </update>

六:foreach标签
mybatis的foreach标签
        collection:配置的集合属性
        separator:分隔符号
        open:以什么样的sql语句开头
        close:以什么样的sql结尾
        item:循环中的变量名
 <select id="findUserByQueryVo" parameterType="queryvo" resultMap="baseMap">
    <include refid="mySql"></include>
        <where>
           <foreach collection="ids" separator="," open="id in(" close=")" item="myId">
               <!--和循环中的变量名一致-->
                    #{myId}
            </foreach>
        </where>
    </select>

public class QueryVo {
    private List<Integer> ids ; //list集合属性 属性名称ids
}

输出映射resultMap

数据库字段名和实体类字段名不一致

实体类的属性名和表字段不对应,只有字段名相同时自动映射,其他值为null

方式1:使用mybatis高级输出映射(结果映射)resultMap,它可以在里面配置实体类的属性名称和表的字段
<mapper namespace="com.qf.mapper.UserDao">
    <!--使用resultMap,先定义resultMap
            id,这个结果映射标识,必须唯一,
            type:结果映射的结果集的类型
    -->
<resultMap id="baseMap" type="user">
            <!--配置实体的属性和表字段的一一对应
               id指定主键字段和实体的属性名称
               result:指定其他字段和实体类属性名称对应
                    column:表的字段名称
                    property:实体的属性名称
            -->
        <id column="id" property="userId"></id>
        <result column="username" property="userName"></result>
        <result column="gender" property="userGender"></result>
        <result column="age" property="userAge"></result>
        <result column="address" property="userAddress"></result>
 </resultMap>
                        
<select id="findAll" resultMap="baseMap">
    SELECT u.*,a.id aid, a.`money`, a.uid FROM USER u, account a  WHERE u.id = a.uid ;
 </select>
     
     
 方式2:查询sql的时候,指定字段别名,和实体类的属性名称对应
     <select id="findAll" resultType="user">
        SELECT id userId,  username userName , gender userGender,  age userAge , address userAddress  FROM USER
     </select>

mybatis配置映射关系 (xml配置)

配置映射关系:
		mybatis的xml配置方式:
			一对多
				用户和账户
			多对多 
			   用户和角色
			   角色和权限
       u         

 一对多配置:一个用户,多个账户

<mapper namespace="com.qf.mapper.UserDao">
    <resultMap id="baseMap" type="user">
        <id column="id" property="userId"></id>
        <result column="username" property="userName"></result>
        <result column="gender" property="userGender"></result>
        <result column="age" property="userAge"></result>
        <result column="address" property="userAddress"></result>
        <!--一个用户多个账户,需要配置"多的一方",collection标签
            property:包含的集合属性的属性名称,  private List<Account> accounts ;
            javaType:包含集合属性的类型:ArrayList
                将数据最终查询出来存储在 accounts集合属性中,里面包含的javabean类型account
			 column="id"  通过id查询账户,用户的id,关联账户的uid
        -->
        <collection property="accounts" column="id"   javaType="ArrayList" ofType="account">
                <!--配置账户信息的一一对应-->
            <id property="id" column="aid"></id>
            <result property="money" column="money"></result>
            <result property="uid" column="uid"></result>
        </collection>
    </resultMap> 
                
<select id="findAll" resultMap="baseMap">
    SELECT u.*,a.id aid, a.`money`, a.uid FROM USER u, account a  WHERE u.id = a.uid ;
 </select>   
    
   当查询表起别名时,查询的表结果的字段名称对应 column的名称
   查询 a.id aid    column="aid"
    
    
 一对一:一个账户从属与一个用户
    
<mapper namespace="com.qf.mapper.AccountDao">
    <!--定义resultMap-->
    <resultMap id="accountUserMap" type="account">
        <!--配置账户实体和账户表中字段一一对应
                账户表的主键字段id起的别名它和user表的id一致
        -->
        <id property="id" column="aid"></id>
        <result property="money" column="money"></result>
        <result property="uid" column="uid"></result>
        <!--配置映射一对一的映射关系
            配置"一的一方" 使用association标签
                    property:当前包含的实体属性
                    javaType:javabean的实体类型
                    column:关联查询的时候关联字段名称(账户的uid和用户表id一致),关联查询的时候通过uid查询出用户,账户的uid关联用户的id
        -->
        <association property="user" javaType="user" column="uid" >
            <!--用户信息-->
            <id property="userId" column="id"></id>
            <!--用户表的字段和实体属性对应-->
            <result property="userName" column="username"></result>
            <result property="userGender" column="gender"></result>
            <result property="userAge" column="age"></result>
            <result property="userAddress" column="address"></result>
        </association>
    </resultMap>

    <!--查询所有账户
            需要查询出来用户信息有哪些:多表关系(账户维度去用看用户,一对一)
            一的一方法,需要配置
    -->
    <!--<select id="findAllAccount" resultType="account">-->
<select id="findAllAccount" resultMap="accountUserMap">
        SELECT a.`id` aid,a.`money`,a.`uid`, u.`id`,u.`username`,u.`address` , u.`gender` , u.`age` FROM  account a, USER u WHERE a.`uid` = u.`id` ;
    </select>
</mapper>
    

mybatis延迟加载

在这里插入图片描述

mybatis延迟加载的处理方案1:单独处理

 <!--查询所有用户-->
    <select id="findAll" resultMap="baseMap">
        select * from user
    </select>


<!--   延迟加载的处理方案1 单独处理,开启延迟加载,里面不能在配置账户信息
     		 fetchType="lazy" 开启延迟加载
             fetchType="eager" 不配置就是默认值,不开启延迟加载
             select属性="查询账户接口里面的通过账户id获取账户信息"
-->
 <resultMap id="baseMap" type="user">
        <id column="id" property="userId"></id>
        <result column="username" property="userName"></result>
        <result column="gender" property="userGender"></result>
        <result column="age" property="userAge"></result>
        <result column="address" property="userAddress"></result>
     
        <collection property="accounts" column="id"  fetchType="lazy"
                     select="com.qf.mapper.AccountDao.findAccountById"    javaType="ArrayList" ofType="account">      column="id" 用户id,关联账户
        </collection>
    </resultMap> 

 select="com.qf.mapper.AccountDao.findAccountById" ----- <select id="findAccountById"...

AccountDao中:
 /**
     * 通过账户id获取账户信息
     * @param id 账户id
     * @return 返回账户实体
     */
    Account findAccountById(Integer id) ;
}

AccountDao.xml中:
    <!--通过账户id查询账户信息-->
    <select id="findAccountById" parameterType="java.lang.Integer" resultType="account">
        select * from account
        <where>
            id = #{id}
        </where>
    </select>

测试:
   public void testFindAll(){
        List<User> all = userDao.findAll();
        if(all!=null || all.size()>0){
            System.out.println("用户信息是---->");
            for(User user:all){
                System.out.println(user);
                List<Account> accounts = user.getAccounts();
                for(Account account:accounts){
                    System.out.println("包含的账户信息是--->"+account);
                }
            }
        }

延迟加载的处理方案2:xml全局配置

 延迟加载的处理方案2:这块不指定 fetchType="lazy"
            在mybatis-config.xml核心配置文件中配置全局加载开关("侵入式延迟加载/深度延迟加载")

    <settings>
        <!--开启延迟加载开关-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--aggressiveLazyLoading	开启时,任一方法的调用都会加载该对象的所有延迟加载属性
            mybatis3.4.1以前:true/现在必须为false
        -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>


开启延迟加载方式:注解

开启延迟加载方式:注解
    
      //配置多的一方法的信息,通过账户id查询账户信息,开启懒加载
 @Result(property = "accounts",javaType = List.class,column = "id",
                        //配置多的一方法的信息,通过账户id查询账户信息,开启懒加载
                      many = @Many(select = "com.qf.dao.AccountDao.selectAccountById",
                                    fetchType = FetchType.LAZY))}

mybatis的多对多配置

public class User {
    private  Integer id ; //用户id
    private String username ;
    private String gender ;
    private String address ;
    //一个用户包含多个角色信息
    private List<Role> roles;
    }
    
    public class Role {
    private  Integer roleId ;
    private String roleName ; // 角色名称
    private  String roleDesc ; //描述
    //包含多个用户
    private List<User> users ;
    }
    
    
<mapper namespace="com.qf.dao.UserDao">
    <resultMap id="userRoleMap" type="user">
        <!--关联配置用户信息-->
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="gender" column="gender"></result>
        <result property="address" column="address"></result>

        <collection property="roles"
                    javaType="ArrayList" column="id" ofType="role">
           
            <id column="rid" property="roleId"></id>
            <result column="role_name" property="roleName"></result>
            <result column="role_desc" property="roleDesc"></result>
       
        </collection>
    </resultMap>
   <!--
    查询所有用户,同时关联查询角色信息,根据中间表user_role建立多对多关系
   -->
	 <select id="findAllUser" resultMap="userRoleMap">
        SELECT u.*, r.id rid ,r.role_name, r.role_desc FROM user u,  user_role ur, role r
        WHERE  u.id = ur.uid  AND  ur.`rid` = r.`id`
    </select>
</mapper>

mybatis注解配置

mybatis注解开发,不需要使用接口映射文件,直接在接口上声明直接,里面指定sql语句
	@Select:查询注解 代表映射文件中select标签
	@Results注解       --xml里面reusltMap
 		id属性-->代表resultMap标签里面id属性
           value属性的--->返回值是 注解类型Result[]
                  @Result(id = true,column = "id")  在resultMap标签定义的id标签
                  @Result(column = "",property = ) 在resultMap标签定义result标签
            Many many() :many属性,配置"多的关系",---代表xml配置reusltMap里面的collection标签
              它的返回结果@Many注解
              One one():one属性,配置"一个的一方"---代表xml配置resultMap的assoaction标签
 @ResultMap(values="上面注解的id属性内容") 引入上上面的每一个配置信息,单独可以不写value

        
 Select一对多 many      
 /**
     * 查询所用用户
     * @return 返回用户列表
     */
    @Results(id = "userMap",
            value =
                 {   @Result(id = true,column = "id",property = "userId"),
                     @Result(column = "username",property ="userName" ),
                     @Result(column = "gender",property = "userGender"),
                     @Result(column = "age",property = "userAge"),
                     @Result(column = "address",property = "userAddress"),
                              //集合属性
                     @Result(property = "accounts",javaType = List.class,column = "id",
                        //配置多的一方法的信息,通过账户id查询账户信息,开启懒加载
                      many = @Many(select = "com.qf.dao.AccountDao.selectAccountById",
                                    fetchType = FetchType.LAZY))}
          )
    @Select(value = "select * from user") //xml文件指定reulsetMap
    List<User> findAll() ;

  /**
     * 通过账户id查询账户实体
     * @param id 账户id
     * @return
     */
    @Select("select * from account where id = #{id}")
    Account selectAccountById(Integer id);

 /**
     * 模糊搜索
     * @param username
     * @return
     */
    @Select("select * from user where username like #{userName}")
    //引用上面的配置,让实体的属性和表的字段一一对应
    @ResultMap("userMap")
    List<User> selectUserByUsername(@Param(("userName")) String username) ;


select 一对一
    
    @Results(
            id = "accountMap",value = {
                    @Result(id = true,column = "id",property = "id"),
                    @Result(column = "uid",property = "uid"),
                    @Result(column = "money",property = "money"),
                        //包含用户属性user
                    @Result(property ="user",column = "uid",
                            one = @One(select = "com.qf.dao.UserDao.findUserById",fetchType = FetchType.LAZY))
    }
    )
    
     @Select("select * from user where id = #{userid}")
    User selectUserById(@Param("userid") Integer id) ;

mybatis和servlet整合

1.MyBatisUtil工具类

public class MyBatisUtil {
    private MyBatisUtil(){}
    //声明一个静态变量
    private static SqlSession sqlSession ;
    private static SqlSessionFactory sqlSessionFactory ;
    //创建一个静态实例
    //每一个线程使用自己的SqlSession,连接数据库进行操作
    private static ThreadLocal<SqlSession> tl = new ThreadLocal<>() ;
    //静态代码块---获取到SqlSession (mybatis一级缓存:默认就是sqlSession)
    static{
        //1)读取mybatis-config.xml文件
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            //创建SqlSessionFactoryBuilder---它创建工厂对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder() ;
             sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream) ;
            //创建SqlSession
            sqlSession = sqlSessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //2)定义一个获取SqlSession
    public  static SqlSession openSession(){
        //从当前线程先获取
        SqlSession sqlSession = tl.get();
        if(sqlSession==null){
            //说明当前正在执行的线程没有SqlSession
            //从连接池获取SqlSession(SqlSessionFactory获取sqlSession)
            sqlSession = sqlSessionFactory.openSession();
            //将当前这个sqlSession绑定到线程上
            tl.set(sqlSession) ;
        }
        return sqlSession;
    }
    //3)提交事务
    public static void commitAndClose(){
        SqlSession sqlSession = openSession();
        sqlSession.commit();
        sqlSession.close() ;
    }
    //4)事务回滚
    public static void rollbackAndClose(){
        SqlSession sqlSession = openSession();
        sqlSession.rollback();
        sqlSession.close();
    }

    //5)定义一个方法:获取任意接口类型的子实现类对象(mybatis动态代理实现)
    //将泛型定义在方法上 -->方法返回值上<T>
    //方法的形式参数:任意java类型的字节码文件对象
    public  static <T extends  Object> T getMapper(Class<T> clazz){
        return sqlSession.getMapper(clazz) ;
    }
}

2.业务接口实现

public class UserServiceImpl  implements UserService {
    //声明UserDao类型变量
    private UserDao userDao ;
    @Override
    public BaseResult checkUser(String username) {
        //调用dao层接口---mybatis实现
        SqlSession sqlSession = MyBatisUtil.openSession() ;
        userDao = sqlSession.getMapper(UserDao.class);
        User user = userDao.selectUserByUsername(username);
        //封装BaseResult对象
        BaseResult reuslt ;
        if(user!=null){
            //存在,找到了
          return   reuslt = new BaseResult(0,"用户名太受欢迎,请更换",null,null) ;
        }
        return  reuslt = new BaseResult(1,"恭喜您,可用",null,null) ;

    }
}

3.servlet

@WebServlet("/checkUser")
public class CheckUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //mybatis_02_war_exploded/checkUser?username="+username
        //接收参数
        String username = request.getParameter("username") ;
        //调用业务接口
        UserService userService = new UserServiceImpl() ;
        BaseResult baseResult = userService.checkUser(username) ;
        //通过fastjson解析工具解析json
        JSONObject jsonObject = new JSONObject() ;
        String jsonString = jsonObject.toJSONString(baseResult);
        //设置解决响应json的中文乱码
        response.setContentType("application/json;charset=utf-8");
        System.out.println(jsonString);
        //响应
        response.getWriter().write(jsonString);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

4.druid配置

 <environments default="mysql">
        <!--可以配置多个环境-->
        <environment id="mysql">

            <transactionManager type="JDBC"/>
            <!--启用mybatis自带的连接池-->
            <!--
                启用druid连接池
            -->
<!--            <dataSource type="POOLED">-->
            <dataSource type="com.qf.datasource.MyDruidDataSourceFactory">

                <property name="driverClassName" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <!--登录密码-->
                <property name="password" value="${jdbc.password}"/>
               <!-- <property name="maxActive" value="${jdbc.maxActive}"/>-->
            </dataSource>
        </environment>
    </environments>


public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
    public MyDruidDataSourceFactory(){
        this.dataSource = new DruidDataSource() ;
    }

5.前端页面

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <script src="/mybatis_02_war_exploded/js/jquery-3.4.1.min.js"></script>
    <script>
            //Jqeury的页面载入事件
            $(function(){
                //用户名失去焦点事件
                $("#username").blur(function(){
                    //通过jquery的方式获取用户名的内容
                    var username = $("#username").val() ;
                    alert(username) ;
                    //获取id="tip"的jq标签对象
                    var span = $("#tip") ;
                    //发送ajax
                    $.ajax({
                        url:"/mybatis_02_war_exploded/checkUser?username="+username+"",
                        type: "get",
                        success:function (data){ //服务器响应成功的回调函数
                            if(data.code==0){ //{"code":1,"msg":"消息内容"}
                                //不可用
                                //span标签设置文本
                                span.html(data.msg) ;
                                span.css("color","red") ;
                            }
                            if(data.code==1){ //{"code":0,"msg":"消息内容"}
                                //不可用
                                //span标签设置文本
                                span.html(data.msg) ;
                                span.css("color","green") ;
                            }
                        },
                        dataType:"json"
                    }) ;
                }) ;
            }) ;
    </script>
</head>
<body>
    <form>
        用户名:<input type="text" id="username" placeholder="请输入用户名"/>
        <span id="tip"></span><br/>
        密码:<input type="password" placeholder="请输入密码"/><br/>
        邮箱:<input type="text" placeholder="请输入邮箱"/><br/>
        <input type="submit" value="注册"/>
    </form>
</body>
</html>

mybatis逆序工程

<!--在依赖下面加入指定的插件配置-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                  <!--覆盖工程并配置指定的逆向工程配置文件-->
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                    <configurationFile>${project.basedir}/src/main/resources/generator-config.xml</configurationFile>
                    <!--文件/src/main/resources/下生成generator-config.xml文件-->
                </configuration>
                <dependencies>
                    <!--引入mysql驱动,版本不能太高-->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.25</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

配置好jdbc.properties文件内容(driverClassName,url,username,password)
添加 mybatis-generator 配置文件 generatorCong.xml文件

mybatis逆序工程xxxExample的使用

public class MyBatisTest {
    private UserMapper userMapper ;
    private SqlSession sqlSession ;
    // private AccountDao accountDao ;
    @Before//执行单元测试方法之前执行
    public void init() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //2)创建一个对象SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder() ;
        //3)创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载流对象 获取到工厂对象
        //4)创建 SqlSession---就是执行对象--底层就是PreparedStatement
        sqlSession = sqlSessionFactory.openSession(true);//自动提交
        
        userMapper = sqlSession.getMapper(UserMapper.class) ;
        // accountDao = sqlSession.getMapper(AccountDao.class) ;
    }

    
    @Test
    public void test1(){
        //逆序工程生成实体类中xxxExample都是设置设置条件参数,相当于where后面的哪些
        //创建user条件对象 UserExample
        UserExample userExample  = new UserExample() ;
        //创建实际条件的参数--->xxExample里面的方法
        //public Criteria createCriteria()
        //通过id查询 :设置id是某个值
        //Criteria是xxxExample的内部类
        
        //通过id查询∶设置id是某个值
       //userExample.createCriteria().andIdEqualTo( value: 2) ;

        UserExample.Criteria criteria = userExample.createCriteria();
         criteria.andUsernameEqualTo("张三丰") ;
        //创建User对象
        User user  = new User() ;
        user.setUsername("李国栋") ;
        user.setAge(23);
        //update  user set username = "值",age= 23 where  username =  "张三丰" ;
        //逆序工程里面的自带的api方法
        int count = userMapper.updateByExampleSelective(user, userExample);
        System.out.println(count);
    }
    
    
    @Test
    public void test2(){
        //通过主键,不需要设置条件xxxExample进行修改
        //int updateByPrimaryKey(User user):自己设置你的参数信息
        //int updateByPrimaryKeySelective(User record); 通过主键修改,自定义参数
        User user = new User() ;
        user.setUsername("李四") ;
        user.setAge(25) ;
        user.setGender("女") ;
        user.setId(4);
        int count = userMapper.updateByPrimaryKey(user);
        System.out.println(count);
    }
}

自定义工厂_解析xml文件

在这里插入图片描述

1.导包

  <!--dom4j解析xml文件的-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!--dom4j里面依赖包-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1-beta-6</version>
        </dependency>

2.自定义工厂

public class BeanFactory {
    private BeanFactory(){}//外界不能new
    //对外提供公共的访问方法
    /**
     * 解析bean.xml文件的方法
     * @param id bean标签里面 id标识
     * @return 返回实例对象
     */
    public static Object getBean(String id)  {
        Object obj = null;
        try {
            //设置工厂实现类(dom4j的版本原因)
            System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
                   "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");

            //解析xml文件
            //使用dom4j--pom文件中引入 核心的dom4j的jar包
            //创建dom4j解析器 SAXReader
            SAXReader saxReader  = new SAXReader() ;
            //读取文件
            InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.xml");
            //bean.xml文档对象Document
            Document doc = saxReader.read(inputStream);
            //获取到根标签 beans标签对象
            Element beansElement = doc.getRootElement();
            System.out.println(beansElement );
            //使用dom4j里面技术---xpath技术:快递定位到某个标签
            //不分层级选中bena标签--指定id属性的标签
            //      xpath表达式 "//bean[@id='"+id+"']" //里面id传进去的变量
            Element beanElem = (Element) doc.selectSingleNode("//bean[@id='" + id + "']"); //Node节点对象--->指定Element对象
            //通过bena标签对象获取class属性的内容
            String className = beanElem.attributeValue("class");
            System.out.println(className) ;//接口实现类的完全限定名称
            //通过反射:创建这个类的实例
            Class clazz = Class.forName(className);
            //直接创建实例
            obj = clazz.newInstance();
            return  obj ;
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return  null ;
    }
    public static void main(String[] args) throws
            DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        UserService userService = (UserService) BeanFactory.getBean("userService");
        System.out.println(userService) ;
    }
}

3.bean.xml文件

<beans>
    <!--
        管理service层:业务层
    定义子标签bean
        id标签:代表当前唯一标识 起名字:"业务层接口名,首字母小写"
        class标签:指定接口实现类的完全限定名称
    -->
    <bean id="userService" class="com.qf.service.impl.UserServiceImpl"></bean>
    <bean id="userDao" class="com.qf.dao.impl.UserDaoImpl"></bean>
    <!--很多很多bean标签-->
    <!--<bean id="ProductService" class="com.qf.service.impl.UserServiceImpl"></bean>
    <bean id="userService" class="com.qf.service.impl.UserServiceImpl"></bean>
</beans>


4.service层实现

public class UserServiceImpl  implements UserService {
    //声明UserDao类型 变量
    private UserDao userDao ;
    @Override
    public BaseResult checkUser(String username) {
        //调用dao层接口---mybatis实现
        SqlSession sqlSession = MyBatisUtil.openSession() ;
        userDao = sqlSession.getMapper(UserDao.class);
        User user = userDao.selectUserByUsername(username);
        //封装BaseResult对象
        BaseResult reuslt ;
        if(user!=null){
            //存在,找到了
          return   reuslt = new BaseResult(0,"用户名太受欢迎,请更换",null,null) ;
        }
        return  reuslt = new BaseResult(1,"恭喜您,可用",null,null) ;
    }
}

5.servlet层实现

@WebServlet("/checkUser")
public class CheckUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //mybatis_02_war_exploded/checkUser?username="+username
        //接收参数
        String username = request.getParameter("username") ;
        //调用业务接口
        //存在耦合性(开发原则:低耦合,高内均)
        //UserService userService = new UserServiceImpl() ;
        //自定义工厂,解析bean.xml --解耦
        UserService userService = (UserService) BeanFactory.getBean("userService");
        BaseResult baseResult = userService.checkUser(username) ;
        //通过fastjson解析工具解析json
        JSONObject jsonObject = new JSONObject() ;
        String jsonString = jsonObject.toJSONString(baseResult);
        //设置解决响应json的中文乱码
        response.setContentType("application/json;charset=utf-8");
        System.out.println(jsonString);
        //响应
        response.getWriter().write(jsonString);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }
}

Spring

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

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

导包
        <!--spring的全局的jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

spring-congig配置
<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:p="http://www.springframework.org/schema/p"                     p标签使用
       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">  注解开启
    <bean>xxxx</bean>
    <bean>xxxx</bean>
    <bean>xxxx</bean>
</beans>

依赖注入xml配置方式

1.set方法

  <!--通过引入的spring配置文件,通过bean标签管理指定的类
   id="这个类(bean)唯一标识",你自己可以定义,默认当前这个类或者接口名的首字母小写
   class="这个类的完全限定名称 包名.类名"
 
   SpringIOC:控制反转 ,通过spring容器管理多个bean,以及管理bean的一些数据的注入
   (依赖注入DI:Dependency Injection)
   给com.qf.pojo.TabUser注入它的属性数据 -->

实体类
public class TabUser {
    private int id      ; //用户编号
    private String name ; //用户名
    private int age     ;//年龄
    private String gender ;//性别
    public void setTabUserInfo(TabUserInfo tabUserInfo) { //另一个引用类型
        this.tabUserInfo = tabUserInfo;
    }
    //包含另一个用户详情属性
    private TabUserInfo tabUserInfo ;
    public TabUser() {
    }
    //有参构造方法
    public TabUser(int id, String name, int age, String gender,TabUserInfo tabUserInfo) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.tabUserInfo = tabUserInfo ;
    }
    //    private TabUserInfo tabUserInfo ;
    //提供set方法
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }

实体类关联
public class TabUserInfo {
    private String address ; //用户家庭住址
    private String  cardId    ;// 用户身份id
    private String hobby ; //爱好

    public void setAddress(String address) {
        this.address = address;
    }
    public void setCardId(String cardId) {
        this.cardId = cardId;
    }
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
    public TabUserInfo() {
    }
    public TabUserInfo(String address, String cardId, String hobby) {
        this.address = address;
        this.cardId = cardId;
        this.hobby = hobby;
    }



方式1:setXXX注入(set方法注入)
     bean标签
       property标签:
          name:属性名
          value:属性值 (属性的类型都是基本类型或者是String)
          ref:关联另一个引用数据类型的id值(bean的id)
 <bean id="tabUser" class="com.qf.pojo.TabUser">
      <property name="id" value="1"></property>
      <property name="name" value="高圆圆"></property>
      <property name="age" value="44"></property>
 	  <property name="gender" value=""></property>
      <!--日期格式:  value="xxxx/xx/xx"-->
     <!--关联另一个引用数据类型-->
     <property name="tabUserInfo" ref="tabUserInfo"></property>
 </bean>

  <bean id="tabUserInfo" class="com.qf.pojo.TabUserInfo">
      <property name="address" value="南窑国际92排"></property>
      <property name="cardId" value="61012519980707007X"></property>
      <property name="hobby" value="跑步"></property>
  </bean>


 //使用spring方式给tabUser进行数据的注入
        //1)创建Spring容器
        //public ClassPathXmlApplicationContext(String configLocation) :读取spring的核心配置文件

	ClassPathXmlApplicationContext applicationContext =  new ClassPathXmlApplicationContext("spring-config.xml") ;
       
//直接从类路径上读取配置文件(resource目录)
        //获取bean的实例
        //getBean(当前类的字节码文件/字符串标识),返回任意java对象Object
        TabUser mytabuser = (TabUser) applicationContext.getBean("tabUser");//参数:是spring核心配置文件中的bean的id
     System.out.println(mytabuser);

2.构造器注入

当前类中有构造方法
<!--springIOC依赖注入方式2:构造器注入
            constructor-arg
                   name:属性名称
                   value:基本数据类型或者String类型:实际值
                   ref:关联另一个引用类型的bean标签id值
    -->
    <bean id="tabUser" class="com.qf.pojo.TabUser">
        <constructor-arg name="id" value="2"></constructor-arg>
        <constructor-arg name="name" value="宜三宝"></constructor-arg>
        <constructor-arg name="age" value="24"></constructor-arg>
        <constructor-arg name="gender" value=""></constructor-arg>
     
  <!--构造器注入:关联另一个引用数据类型 -->
        <constructor-arg name="tabUserInfo" ref="tabUserInfo"></constructor-arg>
    </bean>

3.p标签

前提:实体类中有set方法

 xmlns:p="http://www.springframework.org/schema/p"     p标签使用
  <!--依赖注入的第三种方式:p标签注入
            1)需要配置文件中引入约束文件 p标签
            xmlns:p="http://www.springframework.org/schema/p"放在头文件上
            2)在当前类中必须有set方法...
                        p:属性名称= 值  除过String特殊引用类型/基本类型
                        p:属性名称-ref="当前这个属性的返回值是其他引用类型"
    -->

  <bean id="tabUser" class="com.qf.pojo.TabUser" p:id="3" p:name="张三丰" p:age="50" p:gender=""   p:tabUserInfo-ref="tabUserInfo" >
    </bean>

  <bean id="tabUserInfo" class="com.qf.pojo.TabUserInfo" p:address="西安市丈八四路陕西大会堂"   p:cardId="61012519980707009X" p:hobby="马拉松"></bean>-->

依赖注入: 数组\set集合\map集合\Properties:属性集合列表\list集合

@Data//setXXX/getxXX()/toString()
@NoArgsConstructor//Student()
@AllArgsConstructor //Student(所有参数)
public class Student {
    //private int sId ; //sid
    //private String sName ; //sname
    //属性名字母小写
    private int sid ;
    private String sname;
    private String sgender ;
    private int sage  ;
    private Date sbirthDay ;
    //数组类型
    private String hobby[] ;
    
    //set集合集合类型
    private Set<String> addresses ;
    
    //Map集合
    private Map<String,String> map ;
    
    //属性列表java.util.Properties 没有泛型,本质是map ,键和值都是String
    private Properties properties;
    private List<String> list ;
}

        
        
 <bean id="student" class="com.qf.pojo.Student">
        <property name="sid" value="5"></property>
        <property name="sname" value="李国栋"></property>
        <property name="sgender" value=""></property>
        <property name="sage" value="25"></property>
        <property name="sbirthDay" value="1994/05/30"></property>

        <!--数组类型-->
        <property name="hobby">
            <array>
                    <value>跑步</value>
                    <value>健身</value>
                    <value>敲代码</value>
                    <value>看电影</value>
            </array>
        </property>

        <!--set集合类型-->
        <property name="addresses">
            <set>
                <value>立人科技B座</value>
                <value>南窑国际</value>
            </set>
        </property>

        <!--map集合类型-->
        <property name="map">
            <map>
                <!--指定键值对的内容-->
                <entry key="id" value="1"></entry>
                <entry key="name" value="王五"></entry>
                <entry key="gender" value=""></entry>
            </map>
        </property>

        <!--java.util.Properties:属性集合列表-->
        <property name="properties">
            <!--存储多个属性名称和内容-->
            <props>
                <prop key="zhangsan" >30</prop>
                <prop key="lisi" >40</prop>
                <prop key="wangwu" >25</prop>
            </props>
        </property>


        <!--list集合类型-->
        <property name="list">
            <list>
                <value>hello</value>
                <value>world</value>
                <value>javaee</value>
                <value>Spring</value>
            </list>
        </property>
    </bean>

依赖注入:注解方式

Spring开启注解

<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:p="http://www.springframework.org/schema/p"                     p标签使用
       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">  注解开启
    
     <!--上面引入约束文件
 spring-beans.xsd约束文件
 开启spring的注解:在配置文件配置注解的开启
 -->
      <!--扫描com.qf包下的所有的注解 -->
    <context:component-scan base-package="com.qf"/>  

注解的使用

 Spring提供很多注解
一.创建对象的注解: Spring通过解析xml文件,通过class属性内容创建对象
               @Component:通用的注解:  <bean id="标识" class="完全限定名称"></bean>
               @Service :在业务接口实现中使用的,管理业务层对象(xxxServceImpl...)
               @Controller:在Servlet里面创建对象,交给spring来创建
               @Repository:在dao层实现类出创建对象,交个Spring
   
   
二.注入的注解      
         @AutoWired:自动装配:默认是按照类型注入(如果注入的这个类型只有一个类型,可以直接自动注入)
                        如果注入的类型:有多个(举例:UserDaoImpl2/UserDaoImpl都是实现同一个接口);
                            不能使用@AutoWired:,必须结合下面这个注解Qualifier
               @Qualifier("指定注入的名称") ---类似于bean的id (注入的名称:默认当前类名首字母小写)
               
          //单独使用
               @Resource:name属性
                         type属性,当前内名.class字节码文件
 
 
1.创建对象的注解: 
 当接口只有一个实现类时,在对应实现类上注解@Service 或者@Repository ,可以通过接口的字节码文件直接获取接口的实现子类
 
 applicationContext.getBean(接口的字节码文件,接口名.class)
 
 @Service
public class UserServiceImpl  implements UserService {
public UserDaoImpl({
System.out.println( "UserService层对象被创建了");
	}
}

@Repository("userDao")
public class UserDaoImpl  implements UserDao{
public UserDaoImpl({
System.out.println( "dao层对象被创建了");
}


   @Test
    public void testUserService(){
        //测试dao层
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");//通过标识获取
        System.out.println(userDao);
        System.out.println("--------------------------");
        UserService userService2 = applicationContext.getBean(UserService.class);//直接指定接口字节码文件
        System.out.println(userService2);  //获取到UserServiceImpl对象
    }

2.注入的注解    
1) @Autowired
	private UserDao userDao ;   自动装配:默认是按照类型注入(如果注入的这个类型只有一个类型,可以直接自动注入)
	
2) @Resource(name=“userDAO”,type=UserDaoImpl.class)
    private UserDao userDao ;
    
3) 	@Autowired
    @Qualifier(value = "userDaoImpl")   如果当前接口有两个实现类注解均没写标识,则默认使用当前类名首字母小写注入,进行区分
    private UserDao userDao;
    
    @Repository          没写标识,则默认使用当前类名首字母小写userDaoImpl
    public class UserDaoImpl  implements UserDao{
    
    @Repository           没写标识,则默认使用当前类名首字母小写userDaoImpl2
    public class UserDaoImpl2 implements UserDao{
    
   

Spring整合juint

Spring整合junit单元测试
1)导包:spring-test.jar包(版本必须和spring-context.jar包版本一致/或者比它的版本低)
2)使用spring-test注解:读取到类路径下的spring-config.xml文件
      @ContextConfiguration:              location :指定资源文件
3)单元测试类上面加入@RunWith:启用Spring单元测试的启动器    SpringJUnit4ClassRunner这个类
            Class<? extends Runner> value(); value属性返回就是指定spring启动类       
            
            
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config.xml") //这个过程---加载spring核心配置文件,创建Srping容器了
public class MyTest {
    //注入XxxService
    @Autowired //自动注入
    private UserService userService ; //声明变量
 
   @Test//junit的单元测试
    public void test1(){
        String message = userService.getMessage();
        System.out.println(message);

    }
    
    
    
   1. xml配置文件方式注入:
   <bean id="userSerivce"   class="com.qf.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
    <bean id="userDao" class="com.qf.dao.impl.UserDaoImpl"></bean>   
   
   
    public class UserServiceImpl  implements UserService {
       //set注入
    private UserDao userDao ;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
         public String getMessage() {
        //调用dao层
        return userDao.selectMesage();
    	}
   }
    
    public class UserDaoImpl  implements UserDao {
    @Override
    public String selectMesage() {
        return "hello,SpringIOC!!" ;
    }
    
        
        
    2.注解方式
        @Service //<bean id="userSerivce"   class="com.qf.service.impl.UserServiceImpl">
public class UserServiceImpl  implements UserService {
        //自动装配
    @Autowired
    private  UserDao userDao ;

    @Override
    public String getMessage() {
        //调用dao层
        return userDao.selectMesage();
    }
}
        
      @Repository
    public class UserDaoImpl  implements UserDao {
        @Override
        public String selectMesage() {
            return "hello,SpringIOC!!" ;
        }
    }      

SpringIOC管理bean对象的生命周期

spring生命周期
        bean标签提供一些属性
                init-method:指定初始化方法(对象的初始化操作)
                destroy-method:指定销毁方法
                scope="singleton",bean的依赖范围:默认的单例 singleton
                        (在内存中始终只有一个对象-关联到单例设计模式:饿汉/懒汉式)
                       prototype:多例模式 (多线程环境下,每一个用户都要发送请求)
                        内存中创建多个对象,地址值不一样
               lazy-init:指定true/false,是否懒加载初始化

  <bean id="tabUser"
          init-method="init"
          scope="singleton"
          destroy-method="destroy"   //容器关闭后执行
          class="com.qf.pojo.TabUser "/>



//给类配置@Scope依赖范围,
@Scope(value = "singleton")//默认单例
@Component//通用的spring创建对象的注解
public class TabUser {
        //无参构造方法
        public TabUser(){
            System.out.println("tabUser被Spring容器创建了");
        }
        //初始化方法
        public void init(){
            System.out.println("init方法被调用了...");
        }
        //销毁方法
        public void destroy(){
            System.out.println("destroy方法被调用了...");
        }
}


  @Test
    public void test2(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "spring-config.xml");
        TabUser tabUser = (TabUser) applicationContext.getBean("tabUser") ;
        System.out.println(tabUser) ;

        //第二次获取
        TabUser tabUser2= (TabUser) applicationContext.getBean("tabUser")  ;
        System.out.println(tabUser2) ;
        System.out.println(tabUser==tabUser2) ;

        applicationContext.close(); //关闭容器了
    }



注解方式使用Spring生命周期
@Scope(value = "singleton")//默认单例
@Component//通用的spring创建对象的注解
public class TabUser {
        //无参构造方法

        public TabUser(){
            System.out.println("tabUser被Spring容器创建了");
        }

        //初始化方法
       @PostConstruct
        public void init(){
            System.out.println("init方法被调用了...");
        }

        //销毁方法
    @PreDestroy
        public void destroy(){
            System.out.println("destroy方法被调用了...");
        }

Spring_mybatis_servlet整合

1.spring整合包

 <!--spring-context的核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

        <!--mybatis整合spring的jar包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--spring-jdbc.jar包 配置数据源,代替mybatis事务管理器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <!--spring里面的单元测试:和junit进行整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

2.spring_config配置

      <!--开启spring注解,扫描指定包下下的spring注解-->
    <context:component-scan base-package="com.qf"/>

    <!--配置数据源来自于 Spring-jdbc.jar包
        DriverManagerDataSource:驱动管理器,可以配置数据库连接信息
     -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!--set注入连接信息-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/myee2302_db_2"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

    <!--mybatis和spring整合包提供,配置SqlSessionFactoryBean-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--配置数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--配置实体类的包名,实体类的别名就是当前类名,不区分大小写-->
        <property name="typeAliasesPackage" value="com.qf.pojo"></property>
        <!--配置dao层映射文件的加载-->
        <property name="mapperLocations"  value="classpath:mapper/*Mapper.xml"></property>
    </bean>

    <!--mybatis和spring整合包里面,配置mapper/dao层的包扫描
        id名称必须="mapperScannerConfigurer"
    -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <!--配置basepackage,扫描dao层接口的包-->
        <property name="basePackage" value="com.qf.mapper"></property>
        <!--配置指定sqlSessionFactoryBeanName,指定上面org.mybatis.spring.SqlSessionFactoryBean它的id-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
    </bean>

</beans>

3.servlet

@WebServlet("/findAll")
public class FindAllServlet extends HttpServlet {
    private ProductService productService ;
    //当前在访问"/findAll"通过web容器创建Servlet对象
    //执行无参构造方法
    public FindAllServlet(){
        //读取spring-config.xml核心配置文件
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");

        productService = applicationContext.getBean(ProductService.class);

    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {



        //调用业务接口
        List<Product> allProducts = productService.getAllProducts();

        //Fastjson
        JSONObject object = new JSONObject() ;
        String str = object.toJSONString(allProducts);

        //设置响应乱码
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(str);

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }
}

4.service
@Service
public class ProductServiceImpl  implements ProductService {
    //注入ProductMapper
    @Autowired
    private ProductMapper productMapper ;
    @Override
    public List<Product> getAllProducts() {
        List<Product> products = productMapper.selectAllProducts();
        if(products!=null || products.size()>0){
            return products ;
        }
        return null ;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值