18.JAVA之三大框架Spring、IOC和DI、拦截器、MVC项目、Mybatis持久层、动态SQL、SSM

news2025/1/20 19:10:55

一、Spring框架

1.1概述

其中最核心的是:IoC控制反转、DI依赖注入、Bean工厂、SpringAOP面向切面编程、事务控制。

Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。

SpringMVC框架用来接受浏览器的请求和给浏览器做出响应
Mybatis框架用来和数据库交互
Spring框架主要用来完成中间的业务,主要的功能包括:IOC / DI

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

1.   

核心容器Spring Core

核心容器提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC)模式,将应用程序的配置和依赖性规范与实际的应用程序代码分开。

2.   

Spring上下文

Spring Context

Spring上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDIEJB、电子邮件、国际化、校验和调度功能。

3.   

Spring AOP

通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。可以很容易地使 Spring框架管理的任何对象支持AOPSpring AOP模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

4.   

Spring DAO

JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

5.   

Spring ORM

Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括JDOHibernateiBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

6.   

Spring Web

Web上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以Spring 框架支持与 Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

7.   

Spring MVC框架

MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSPVelocityTilesiText  POI

Spring 框架的功能可以用在任何J2EE服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定J2EE服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同J2EE环境(Web或EJB)、独立应用程序、测试环境之间重用。

Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring ,但这点越来越模糊。

核心概念

模块

说明

1.   

BeanFactory

Spring内部使用,创建bean的工厂

2.   

ApplicationContext

外部应用程序调用,也成为spring容器

3.   

IoC控制反转

Inversion of Control

开发者在无需自己new对象,无需关心对象的创建过程

User user = new User();             手动创建对象

User user = context.getBean(user); 容器创建对象

4.   

DI依赖注入

Dependency Injection

松耦合方式实现对象直接的依赖

5.   

AOP面向切面编程

补充java面向对象的不足

1.2 三大核心组件的关系

Bean、Context、Core三大核心组件的关系:

Bean 包装的是 Object,而 Object 必然有数据,如何给这些数据提供生存环境就是 Context要解决的问题,对 Context 来说它就是要发现每个 Bean 之间的关系,为它们建立这种关系并且要维护好这种关系。所以 Context 就是一个Bean关系的集合,这个关系集合又叫 Ioc 容器,一旦建立起这个 Ioc 容器后 Spring 就可以为你工作了。Core 组件就是发现、建立和维护每个 Bean 之间的关系所需要的一些类的工具,从这个角度看来,Core 这个组件叫 Util 更能让你理解。

把Bean 比作一场演出中的演员的话,那 Context 就是这场演出的舞台背景,而 Core应该就是演出的道具了。只有他们在一起才能具备能演出一场好戏的最基本的条件。当然有最基本的条件还不能使这场演出脱颖而出,还要他表演的节目足够的精彩,这些节目就是 Spring 能提供的特色功能了。

主要jar组成

模块

说明

1.   

org.springframework.core

核心工具包,其他包依赖此包

2.   

org.springframework.beans

核心,包括:配置文件,创建和管理bean

3.   

org.springframework.aop

面向切面编程,提供AOP的实现

4.   

org.springframework.context

提供IoC功能上的扩展服务,此外还提供许多企业级服务的支持,邮件、任务调度、JNDI定位、EJB集成、远程访问、缓存以及多种视图层框架的支持

5.   

org.springframework.web.mvc

包含SpringMVC应用开发时所需的核心类

6.   

org.springframework.transaction

JDBCHibernateJDOJPA提供一致的声明式和编程式事务管理

7.   

org.springframework.web

包含Web应用开发时所需支持类

8.   

org.springframework.aspects

提供对AspectJ框架的支持

9.   

org.springframework.test

junit等测试框架的简单封装

10.  

org.springframework.asm

3.0后提供自己独立的,反编译

11.  

org.springframework.context.support

Context的扩展支持,用于mvc方面

12.  

org.springframework.expression

Spring表达式语言

13.  

org.springframework.instument

对服务器的代理接口

14.  

org.springframework.jdbc

jdbc的简单封装

15.  

org.springframework.jms

为简化jms api的使用而做的简单封装

16.  

org.springframework.orm

整合第三方orm,如hibernate/mybatis

17.  

org.springframework.web.servlet

增强servlet

二、Spring框架两大核心:IoC和DI

2.1概述

1、IoC(Inversion of Control)简单来说就是将对象Object的创建的权力及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不在需要关注对象的创建和生命周期的管理,而是在需要的时候由Spring框架提供,这个由Spring框架管理对象创建和生命周期的机制称之为控制反转。

2、DI(Dependency Injection)在创建对象的过程中Spring可以依据对象的关系,自动把其它对象注入(无需创建对象,直接拿着使用)进来,这个过程称之为DI(Dependency Injection)依赖注入。

总结下Spring核心就干了两件事:

1.   创建对象

2.   设置对象的关联关系

2.2IOC(控制反转)

IOC(Inversion of Control),控制反转。

就是指将对象的创建,对象的存储(map),对象的管理(依赖查找,依赖注入)交给了spring容器。

--是指把new的过程交给Spring框架做  User u = 从框架里取
--创建新的maven的Module

2.2.1用xml实现IOC(知道不推荐使用)

--创建一个类
				package cn.tedu.spring;
				public class Hello {
				    public void get(){
				        System.out.println(123);
				    }
				}
			--创建一个xml,就是配置类的信息
				--选中src里的resources-右键-new-xml configuration file-spring config-ok
				--代码
					<?xml version="1.0" encoding="UTF-8"?>
					<beans xmlns="http://www.springframework.org/schema/beans"
					       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
					       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

					    <!-- 这个文件是,spring的核心配置文件 -->
					    <!-- 把Hello类,交给spring容器来管理.IOC DI-->
					    <bean class="cn.tedu.spring.Hello" id="hello"></bean>

					</beans>
			--测试
				--让框架帮我们new,我们直接从框架获取就行了
				--代码
					package cn.tedu.spring;
					import org.springframework.context.support.ClassPathXmlApplicationContext;
					//用来测试
					public class TestIOC {
					    public static void main(String[] args) {
					        //1,加载spring的核心配置文件--参数是xml文件的名字(xml在resources目录里)
					        ClassPathXmlApplicationContext spring =
					                new ClassPathXmlApplicationContext(
					                        "spring-config.xml");
					        //2,从框架里获取对象--参数是xml文件里的bean标签的id值
					        //好处:spring容器里的bean都是默认单例的,只有一个实例
					        Object h = spring.getBean("hello");
					        //cn.tedu.spring.Hello@6950e31
					        System.out.println(h);

					        Hello hh = (Hello) h ; //用子类的扩展功能
       						hh.get();
					    }
					}

这就是spring框架的IoC,控制反转。之前我们自己new出新类。new User();变成由一个初始化的xml配置文件来创建,也就是由spring容器来创建。遍历xml配置文件,读取到<bean>,获取到class属性的类的全路径,利用反射创建这个类。

在java范畴中万物皆Object,在Spring中万物皆Bean。Bean是Spring的核心、基础、根源。

2.2.2用注解实现IOC(重点)

--创建类(@Component)

package cn.tedu.spring;

import org.springframework.stereotype.Component;

@Component//交给spring框架管理(new)
public class Show {
    public void get(){
        System.out.println(456);
    }
}

--创建核心配置文件spring-config.xml,让扫描所有的类

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="cn.tedu.spring"/>
</beans>
package cn.tedu.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext spring =
                new ClassPathXmlApplicationContext(
                        "spring-config.xml");

        Show a = (Show) spring.getBean("show");//注解实现IOC方法必须小写,规定。
        System.out.println(a);//cn.tedu.spring.Animal2@1df82230
        a.get();

        //报错NoSuchBeanDefinitionException
        //Hello类上没有使用@Component注解,spring容器不会new不会管理这个类
        Demo a2 = (Demo) spring.getBean("demo");
        System.out.println(a2);
    }
}

 2.2.3自己实现IOC

 --封装Bean类,两个属性beanId(类名)+属性beanPath(类的全路径)

package cn.tedu.IOC;

public class Bean {
    private String beanId;
    private String beanPath;

    public Bean(String beanId, String beanPath) {
        this.beanId = beanId;
        this.beanPath = beanPath;
    }

    public Bean() { }

    public String getBeanId() {
        return beanId;
    }

    public void setBeanId(String beanId) {
        this.beanId = beanId;
    }

    public String getBeanPath() {
        return beanPath;
    }

    public void setBeanPath(String beanPath) {
        this.beanPath = beanPath;
    }
}

--IOC的核心实现,new对象 - Map<类名,类的对象>

package cn.tedu.IOC;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MyIOC {
    List<Bean> beans = new ArrayList<>();
    public MyIOC() throws Exception {
        //1,有哪些bean--工程里有很多类,spring都当做bean看待,都存入list查询效率要高
        List<Bean> beans = new ArrayList<>();
        //1.1,对象的初始化 -- 要创建对象时,早都准备好了很多bean
        Bean b1 = new Bean("user","cn.tedu.IOC.User");
        Bean b2 = new Bean("dept","cn.tedu.IOC.Dept");
        Bean b3 = new Bean("order","cn.tedu.IOC.Order");
        //1.2,把准备好的bean存入list,方便后面查的快
        Collections.addAll(beans,b1,b2,b3);
        //1.3,完成ioc的过程
        init();
    }
    //2,给bean们创建对象--控制反转IOC
    //准备map,存数据 -- key是类的名字 value是这个类的对象
    Map<String,Object> map = new ConcurrentHashMap<>();
    public void init() throws Exception {
        //2.1,遍历list,获取每个bean
        for (Bean b : beans) {
            //2.2,获取每个bean身上的beanId作为key存入map
            String key = b.getBeanId();
            //2.3,获取每个bean身上的beanPath进行反射创建对象,作为value存入map
            Object value = Class.forName(b.getBeanPath()).newInstance();
            map.put(key,value);//{"user"=new User(),"dept"=new Dept()}
        }
    }
    //3.getBean()获取对象
    public Object getBean(String leiming){
        return map.get(leiming);
    }
}

--测试 - getBean("类名")去map里找value

package cn.tedu.Myioc;

public class TestMyIoc {
    public static void main(String[] args) throws Exception {
        MyIoc mine = new MyIoc();
        Object o1 = mine.getBean("user");
        System.out.println(o1);//cn.tedu.myioc.User@54bedef2

        Object o2 = mine.getBean("dept");
        System.out.println(o2);//cn.tedu.myioc.Dept@5caf905d

        Object o3 = mine.getBean("order");
        System.out.println(o3);// cn.tedu.myioc.Order@27716f4
    }
}

2.2.4总结

--用Spring框架的IOC,只要把类上加@Component注解+配置扫描器
--我们模拟Spring的过程(4,自己实现IOC)多理解

2.3DI(依赖注入)

DI(Dependency Injection)依赖注入 。

相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

基于IOC的控制反转的功能,又提供了DI依赖注入.使用注解@Autowired

用法
        --用@Autowired注解实现对象间的依赖关系

2.3.1测试

--创建Student类

package cn.tedu.DI;

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

@Component
public class Student {
    String name = "王林";
    
    @Autowired//相当于底层帮你给属性提供了get/set--自动装配
    private Teacher teacher;

//    public Teacher getTeacher() {
//        return teacher;
//    }
不加注解要get和set自己实现
//    public void setTeacher(Teacher teacher) {
//        this.teacher = teacher;
//    }

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

--创建Teacher类

package cn.tedu.DI;

import org.springframework.stereotype.Component;

@Component
public class Teacher {
    String name = "白小纯";

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

--测试类

package cn.tedu.DI;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestDI {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext i = new
                ClassPathXmlApplicationContext("spring-config.xml");
        Student s = (Student)i.getBean("student");
//        Teacher t1 = new Teacher();//不加注解自己实现的
//        t1.name="苏铭";
//        s.setTeacher(t1);
//        System.out.println(s.getTeacher());
        System.out.println(s);//加注解实现
        Teacher t = (Teacher) i.getBean("teacher");
        System.out.println(s);
        System.out.println(t);
    }
}

自己实现DI

package cn.tedu.DI;


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

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws Exception {
        Class c = Class.forName("cn.tedu.di.Student");
        Field[] fields =  c.getDeclaredFields();//暴力反射方法
        for (Field f:fields) {
            Autowired a = f.getAnnotation(Autowired.class);
            if (a!=null){//有注解
                Object o = c.newInstance();//暴力反射提供new对象
                f.setAccessible(true);//开启私有也可以访问的权限
                f.set(o,new Teacher());//给属性设置值
            }
        }
    }
}

2.3.2总结

面试IOC和DI

在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时可能需要多个对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。

所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

IoC是设计思想,IoC有三个核心:BeanFactory、反射、DI。BeanFactory利用反射实现对象的创建,DI实现对象关系管理。

自动装配

利用注解方式,我们只需要写@Autowired注解,底层就会去容器中找对应的对象,如果有获取到,反射调用其对应的set方法,设置。而这个调用过程都是自动,我们没有手工去写set方法。所以这个过程也称为自动装配。

三、拦截器Interceptor(注解@Configuration)

3.1概述

Springmvc提供的, 主要用于拦截用户请求并在方法执行前后添加功能.本质上也是AOP的思想. SpringMVC框架自动将配置的拦截器注入到所有的mapping中.

应用场景:

1、日志记录:可以记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等等。

2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。

3、性能监控:可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间;

4、事务控制:对事务的提交回滚等,与业务无关的代码。

让程序员更关注业务代码,事务的处理/性能监测的代码 ,不必关心直接让拦截器配置就可以了.

3.2步骤加测试

步骤
        --implements HandlerInterceptor
        --方法执行前就调用的preHandle
        --方法执行后就调用的postHandle
        --方法都执行完后就调用的afterCompletion

package cn.tedu.controller;
//自定义拦截器
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component//交给spring进行ioc
public class MyInterceptor implements HandlerInterceptor {
    long start;
    @Override//执行前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        start = System.currentTimeMillis();//计时开始
        System.out.println("开始准备执行功能~~");
        return true;//放行,继续执行后面的功能
    }

    @Override//执行后
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        long end = System.currentTimeMillis();//计时结束
        System.out.println("方法执行了:"+(end-start)+"ms");
    }

    @Override//全部执行结束
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("资源已释放...");
    }
}

--implements WebMvcConfigurer
            --添加自定义的拦截器addInterceptors

package cn.tedu.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//把自定义的拦截器配置在容器中
@Configuration
public class Myconfig implements WebMvcConfigurer {

    @Autowired//spring提供的注解,用来完成di--自动装配
    private MyInterceptor myInterceptor;
    @Override//重写接口里的方法,添加自定义拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
    }
}

--测试
            加拦截器前,只执行了业务代码
            加拦截器后,在执行业务代码的前后加了一段特定的业务

package cn.tedu.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/con")
public class Controller {
    @RequestMapping("/save")
    public void save(){
        System.out.println("save方法正在执行");
    }
    @RequestMapping("/get")
    public void get(){
        for (int i=0;i<10;i++){
            System.out.print("save方法正在执行");
        }
    }
}

四、MVC项目

4.1项目结构

Spring用来管理项目中的所有Bean,需要使用注解@Component @Autowired @Service @Component等

Springmvc用来管理Controller层,需要使用的注解有@RestController @RequestMapping等。

 4.2概述

Controller        ->        Service        ->        Dao
CarController           CarService
                               CarServiceImpl
Car                                Car

4.3测试

创建Car类

package cn.tedu.pojo;

import org.springframework.stereotype.Component;

@Component//spring框架提供,用来ioc
public class Car {
    private String name;
    private String color;
    private double price;

    public Car(String name, String color, double price) {
        this.name = name;
        this.color = color;
        this.price = price;
    }

    public Car() {
    }

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", price=" + price +
                '}';
    }
}

创建CarService接口

package cn.tedu.service;

import cn.tedu.pojo.Car;
import org.springframework.stereotype.Component;
//用来实现mvc里的c层的优化
@Component
public interface CarService {
    //接口里的方法都是抽象方法,而且都是public的
    //会为简写的方法自动拼接public abstract
    Car get();
}

创建CarServiceImpl实现类

package cn.tedu.service;

import cn.tedu.pojo.Car;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//实现接口后,要重写接口里的抽象方法
@Service//作用和Component注解作用一样
public class CarServiceImpl implements CarService{
    @Override
    public Car get() {
        Car c = new Car();
        c.setName("jeep");
        c.setColor("黑色");
        c.setPrice(90.1);
        return c;
    }
}

创建CarController类

package cn.tedu.controller;

import cn.tedu.pojo.Car;
import cn.tedu.service.CarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController//接受请求做出响应
@RequestMapping("/car2")
public class CarContorller2 {

    @Autowired
    private CarService carService;
    @RequestMapping("/get")
    public Car get(){
        return carService.get();
    }
}

MVC调用流程
        请求的过程:从浏览器的地址栏敲了回车之后,直接访问了Controller层,Controller层会调用Service层,获取数据
        响应的过程:把Service层return的数据返回给Controller层,Controller层再return给了浏览器展示

五、MyBatis持久层框架

5.1概述

MyBatis的前身就是iBatis,iBatis本是apache的一个开源项目,2010年5月这个项目由apahce sofeware foundation 迁移到了google code,并且改名为MyBatis。

MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。

1、 简化JDBC的开发

2、 能够更好的完成ORM(对象关系映射)

是用来操作数据库的框架,是一个优秀的持久层框架
简化了JDBC的开发步骤,自动完成ORM映射(类里的属性值 和 表里的字段值 自动映射)

5.2内部组件结构图

 --mybatis-config.xml 是mybatis的核心配置文件,用来配置事务,数据库的连接信息
--UserMapper.xml 是用来存储操作User表的大量的SQL

--SqlSessionFactory 是会话工厂,创建会话
--SqlSession 是会话,用来执行SQL(select()/insert()....)

5.3开发步骤

--准备数据库,准备表,和表里的记录
		--添加mybatis的依赖jar包
		--创建mybatis-config.xml
			<?xml version="1.0" encoding="UTF-8"?>
			<!DOCTYPE configuration
			        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
			        "http://mybatis.org/dtd/mybatis-3-config.dtd">

			<!-- mybatis的核心配置文件 配置了数据源,事务,... -->
			<configuration>
			    <environments default="test">
			        <environment id="test">
			            <transactionManager type="JDBC"></transactionManager>
			            <dataSource type="POOLED">
			                <!--数据库的驱动-->
			                <property name="driver" value="com.mysql.jdbc.Driver"/>
			                <!--数据库的url-->
			                <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai" />
			                <!--数据库的用户名-->
			                <property name="username" value="root"/>
			                <!--数据库的密码-->
			                <property name="password" value="root"/>
			            </dataSource>
			        </environment>
			    </environments>
			</configuration>

创建User类

package cn.tedu.pojo;

public class User {
    private Integer id;
    private String name;
    private String addr;
    private Integer age;

    public User(Integer id, String name, String addr, Integer age) {
        this.id = id;
        this.name = name;
        this.addr = addr;
        this.age = age;
    }

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", addr='" + addr + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public Integer getAge() {
        return age;
    }

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

--创建UserMapper.xml

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

<!-- 是mybatis框架用来写SQL语句的文件,namespace用来作为文件的唯一标识-->
<mapper namespace="demons1">
    <!--select用来表示要执行查询语句,
			        id属性是当前SQL的唯一标识.
			        resultType属性用来完成ORM映射,把查到的结果和指定类里的属性映射值
			    -->
    <select id="getAll" resultType="cn.tedu.pojo.User">
        select * from user
    </select>
</mapper>

--修改核心配置文件mybatis-config.xml

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

<!-- mybatis的核心配置文件 -->

<configuration>
    <environments default="test">
        <environment id="test">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai" />
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入UserMapper.xml文件-->
    <mappers>
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>

</configuration>

--测试
            --加载核心配置文件mybatis-config.xml
            --创建会话工厂
            --创建会话
            --执行SQL
            --处理返回值

package cn.tedu.mybatis;

import cn.tedu.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

//测试mybatis
public class Test {
    public static void main(String[] args) throws IOException {
        //        加载核心配置文件mybatis-config.xml
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //        创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //        创建会话
        SqlSession session = factory.openSession();
        //        执行SQL
        //        session.selectList(namespace的值.sql的id);
        List<User> list = session.selectList("demons1.getAll");
        //        处理返回值
        for (User u : list) {
            System.out.println(u);
        }
    }
}

六、Mybatis的接口开发

6.1概述

比XML的开发方式要好: sqlSession.selectList("hello.get");
用接口开发,SQL的定位不必拼串.

6.2步骤及测试

--准备核心配置文件mybatis-config.xml

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

<!-- mybatis的核心配置文件 -->

<configuration>
    <environments default="test">
        <environment id="test">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/
                mybatisdb?characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai" />
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入DeptMapper.xml文件-->
    <mappers>
        <mapper resource="DeptMapper.xml"></mapper>
    </mappers>
</configuration>

--创建Dept类

package cn.tedu.pojo;

import org.springframework.stereotype.Component;

public class Dept {
    private int id;
    private String name;
    private String loc;

//准备get和set,重写,无参、含参构造
   }

--准备DeptMapper.xml

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

<!-- 这是映射文件。用来存大量的sql
是mybatis框架用来写SQL语句的文件,namespace用来作为文件的唯一标识
namespace的值=接口的全路径-->
<mapper namespace="cn.tedu.dao.DeptDao">
    <!--select用来表示要执行查询语句,
			        id是接口里的方法名称,属性是当前SQL的唯一标识.
			        resultType属性用来完成ORM映射,把查到的结果和指定类里的属性映射值
			    -->
    <select id="getAll" resultType="cn.tedu.pojo.Dept">
        select * from dept
    </select>
</mapper>

--准备DeptDao接口,提供方法

package cn.tedu.dao;

import cn.tedu.pojo.Dept;

import java.util.List;
//接口的全路径 = DeptMapper.xml里 namespace的值
//接口里的方法名 = DeptMapper.xml里 SQL的id值
public interface DeptDao {
    List<Dept> getAll();//查询dept表的所有数据
    Dept getOne();
    Dept getTwo();
    List<Dept> getLoc(String loc);
    Dept getId(int id);
}

--测试

package cn.tedu.test;

			import cn.tedu.dao.DeptDao;
			import cn.tedu.pojo.Dept;
			import org.apache.ibatis.io.Resources;
			import org.apache.ibatis.session.SqlSession;
			import org.apache.ibatis.session.SqlSessionFactory;
			import org.apache.ibatis.session.SqlSessionFactoryBuilder;
			import org.springframework.transaction.support.ResourceTransactionDefinition;

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

			//测试类
			public class TestDept {
			    public static void main(String[] args) throws IOException {
			        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
			//        会话工厂SQLSessionFactory
			        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
			//        会话SQLSession
			        SqlSession session = factory.openSession();
			        //获取DeptDao接口
			        DeptDao dao = session.getMapper(DeptDao.class);
			        List<Dept> list = dao.getAll();
			//        解析结果集ORM(类和表  / 类里的属性和表里的字段)
			        for (Dept d : list) {
			            System.out.println(d);
			        }
                    System.out.println("***********************************************");
        Dept d = dao.getOne();
        System.out.println(d);
        System.out.println("***********************************************");
        Dept d1 = dao.getTwo();
        System.out.println(d1);
        System.out.println("***********************************************");
        List<Dept> list1 = dao.getLoc("二区");
        for (Dept pp1 : list1) {
            System.out.println(pp1);
        }
        System.out.println("***********************************************");
        Dept d2 = dao.getId(5);
        System.out.println(d2);
			    }
			}

6.3总结

mybatis-config.xml 要引入DeptMapper.xml
DeptMapper.xml  的namespace的值  =  接口的全路径
                            的SQL的id值   =  接口里方法的名字
DeptDao接口 的全路径 决定了 DeptMapper.xml  的namespace的值
                      里的方法名 决定了 DeptMapper.xml 的SQL的id值

6.4具体使用

6.4.1  别名:alias

在sqlMapConfig.xml配置,在映射文件中直接写对象名称即可

<typeAliases>

<typeAlias type="cn.mybatis.pojo.User" alias="User"/>

</typeAliases>

6.4.2  参数值:paramterType

指定参数类型,通常制定一个对象类型。

6.4.3  返回值:resultType

非常重要的东西,即完成ORM的映射关系所在。这里指定的cd.tedu.mybatis.domain.User代表把结果集转换成一个User对象实例。

6.4.4  返回值:resultMap

resultMap 用于对复杂对象结构时,对应的ResultMap结构名称

6.4.5  集合:List

在MyBatis中,大多默认采用List集合,声明集合参数或者返回值时,都有个奇怪的写法,本应写List<String>,但习惯只写集合元素的类型:String,大家切记。

6.4.6 #和$的区别

如果是整数都行,如果是字符串,#可以自动拼接字符串'',$只拼接值本身。

从安全性上考虑,能使用#尽量使用#来传参,因为这样可以有效防止SQL注入的问题。

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

<!-- 这是映射文件。用来存大量的sql
是mybatis框架用来写SQL语句的文件,namespace用来作为文件的唯一标识
namespace的值=接口的全路径-->
<mapper namespace="cn.tedu.dao.DeptDao">
    <!--select用来表示要执行查询语句,
			        id是接口里的方法名称,属性是当前SQL的唯一标识.
			        resultType属性用来完成ORM映射,把查到的结果和指定类里的属性映射值
			    -->
    <select id="getAll" resultType="cn.tedu.pojo.Dept">
        select * from dept
    </select>

    <!--mybatis练习查询id=100的,解析SQL需要的参数::: #{参数}
		#和$的区别?如果是整数都行,如果是字符串,#可以自动拼接字符串'',$只拼接值本身
				    -->
    <select id="getId" resultType="cn.tedu.pojo.Dept">
        select * from dept where id = ${id}
    </select>

    <!--mybatis练习根据loc查,解析SQL需要的参数::: #{参数}-->
    <select id="getLoc" resultType="cn.tedu.pojo.Dept">
        select * from dept where loc = #{loc}
    </select>

    <!--mybatis练习根据dname查-->
    <select id="getTwo" resultType="cn.tedu.pojo.Dept">
        select * from dept where dname='开发'
    </select>

    <!--mybatis练习根据id查,getOne是接口里的方法名 -->
    <select id="getOne" resultType="cn.tedu.pojo.Dept">
        select * from dept where id=10
    </select>
</mapper>

七、动态SQL

7.1概述

使用mybatis提供的各种标签实现SQL动态拼接

7.2分类

<sql> <include> sql标签用来提取SQL片段 ,include标签用来引用指定片段
<if> 判断
<where> 拼接过滤条件
<foreach> 循环

7.3测试

--创建Emp类

//封装emp表里 每个字段的值
public class Emp {
    //属性类型必须和数据库里字段类型一致,属性名称必须和数据库里字段名称一致
    private int id;
    private String ename;
    private String job;
    private double mgr;
    private Date hiredate;
    private double sal;
    private double comm;
    private int deptno;
//准备get和set,tostring重写,无参、含参构造方法
}

--创建EmpMapper.xml文件,写SQL

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

<mapper namespace="cn.tedu.dao.EmpDao">
    <!--提取SQL片段,复用性高-->
    <sql id="cols">
			        id,ename,job,mgr,sal,comm,hiredate,deptno
			    </sql>
    <!--查询id是100的 或者200的 或者502 的记录-->
    <select id="getIds" resultType="cn.tedu.pojo.Emp">
        select  <include refid="cols"/>
        from emp
        where id in(
    <!-- /*foreach标签完成遍历,
     collection值是固定写法,
     separator数据间的分隔符,
     item是取到的数据
     */-->
     <foreach collection="demons" separator="," item="i">
         #{i}
     </foreach>
     )
 </select>

 <!--查询id=200 ename=tony的记录 /*
 去除多余的and 当<if test="id != 0">时,当前=null*/-->
    <select id="getIdName" resultType="cn.tedu.pojo.Emp">
        select  <include refid="cols"/>
        from emp
        <where>
            <if test="id != null">
                id = #{id}
            </if>
            <if test="ename!=null">
                and ename= #{ename}
            </if>
        </where>
    </select>
    <!--根据id获取数据-->
    <select id="getId" resultType="cn.tedu.pojo.Emp">
    <!-- /* include引用了指定的SQL片段 */-->
    select  <include refid="cols"/>
    from emp where
    <if test="id != null"><!-- /*用来判断*/-->
        id=#{id}
    </if>
</select>
<!--获取所有数据-->
    <select id="getAll" resultType="cn.tedu.pojo.Emp">
        select <include refid="cols"/> from emp
    </select>

</mapper>

--创建EmpDao接口,写方法

package cn.tedu.dao;

import cn.tedu.pojo.Emp;

import java.util.List;

public interface EmpDao {
    List<Emp> getAll();
    Emp getId(int id);
//    Emp getIdName(int id,String ename);
    List<Emp> getIdName(Emp emp);
    List<Emp> getIds(List demons);
}

--创建测试类

package cn.tedu.dao;

import cn.tedu.pojo.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class TestEmp {
    public static void main(String[] args) throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = factory.openSession();
        EmpDao emp = session.getMapper(EmpDao.class);
        List<Emp> list = emp.getAll();
        for (Emp e : list) {
            System.out.println(e);
        }
        System.out.println("*********************************************");
        Emp id = emp.getId(100);
        System.out.println(id);
        System.out.println("*********************************************");
//        Emp IdName = emp.getIdName(200,"tony");
//        System.out.println(IdName);
        Emp IdName = new Emp();
        IdName.setId(200);
        IdName.setEname("tony");
        List<Emp> list1 = emp.getIdName(IdName);
        for(Emp f:list1){
            System.out.println(f);
        }
        System.out.println("*********************************************");
        List list2 = new ArrayList();
        Collections.addAll(list2,100,200,502);
        List<Emp> list3 = emp.getIds(list2);
        for (Emp f2 : list3) {
            System.out.println(f2);
        }
    }
}

八、ResultMap(不常用)

8.1概述

当发起一条查询的SQL语句时,通常都会查出结果,
结果想要和哪个类做ORM映射,直接给
select标签配置resultType属性就可以了.

当出现了特殊情况时(当表里的字段名和类里的属性名不一样),select标签配置resultMap属性。

8.2步骤

--创建UserInfo类

public class UserInfo {
    private int id;
    private String userName;
    private String userAddr;
    private int userAge;
//get和set,tostring,无参、含参构造方法
}

--创建UserInfoMapper.xml,写SQL

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

<mapper namespace="cn.tedu.dao.UserInfoDao">
    <!--resultType只能完成简单的ORM(表里的字段名和类里的属性名一样)
			        UserInfo{id=1, userName='null', userAddr='null', userAge=0}
			        <select id="getAll" resultType="cn.tedu.pojo.UserInfo">
			    -->
    <!-- 用来解决  属性名和字段名 不一样
        id 是唯一标识
        type 想要把结果封装给哪个类
   UserInfo{id=1, userName='韩梅梅', userAddr='上海', userAge=20}
    -->
    <resultMap id="userInfoRM" type="cn.tedu.pojo.UserInfo">
        <!-- id是专门用来描述表里的主键信息 result描述表里的普通字段
            column用来指定表里的字段名
            property用来指定类中的属性名
        -->
        <id property="id" column="id"></id>
        <result property="userName" column="user_name"></result>
        <result property="userAddr" column="user_addr"></result>
        <result property="userAge" column="user_age"></result>
    </resultMap>
    <!--resultMap 用来完成特殊情况的处理-->
    <select id="getAll" resultMap="userInfoRM">
			        select * from user_info
			    </select>

</mapper>

--创建UserInfoDao接口,写方法

package cn.tedu.dao;

import cn.tedu.pojo.UserInfo;

import java.util.List;

public interface UserInfoDao {
    List<UserInfo> getAll();
}

--创建测试类

package cn.tedu.dao;

import cn.tedu.pojo.UserInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class TestUserInfo {
    public static void main(String[] args) throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = factory.openSession();
        UserInfoDao info = session.getMapper(UserInfoDao.class);
        List<UserInfo> list = info.getAll();
        for (UserInfo all : list) {
            System.out.println(all);
        }
    }
}

8.3优化ResultMap

8.3.1开启自动映射

--在核心配置文件中mybatis-config.xml文件中加一个配置信息(放在最上面)
        <settings>
            <!--开启驼峰规则-->
            <setting name="mapUnderscoreToCamelCase" value="true" />
        </settings>

--在指定的resultMap标签中,添加autoMapping属性
                <resultMap id="userInfoRM" type="cn.tedu.pojo.UserInfo"  autoMapping="true">

九、利用SpringBoot整合SSM

9.1项目结构

 9.2代码SSM

十、拓展

10.1.SpringMVC源码分析

--前端控制器DispatcherServlet:接受请求(url和方法的匹配规则)和做出响应
--处理器映射器HandlerMapping:就是根据url找到对应的类对应的方法
--处理器适配器HandlerAdaptor:就是干活的(Controller-Service-Dao-db)
--视图解析器ViewResolver:就是准备网页上要展示数据的格式
--视图渲染View:给浏览器响应,在浏览器上做展示

10.2.前后端访问流程图

 10.3.JDBC和MyBatis的区别

JDBC是java提供了一套专门用于和数据库对接的api,java.sql.*,其规范了如何和数据库进行对接,实现由各数据库厂商进行各自的实现和扩展。学习JDBC重点在学习如何使用其api。

MyBatis框架是轻量级封装了JDBC,我们已经看不到这些api,连接connection、语句preparedstatement、结果集ResultSet,而关注的是mybatis框架体系如何去使用,一旦写好,我们关注的是java对象。

10.4.XML和接口方式的区别

MyBatis提供了两种操作数据库的方式,一种是通过xml映射文件,一种是通过java的接口类。按面向对象方式更加推荐接口方式,但如果复杂的多表映射,仍然需要使用xml映射文件的ResultMap方式实现。

接口只是假象,其底层仍然是通过xml实现,好不容易实现了一套方式,怎忍丢掉呢?可以做个测试就知道它底层怎么实现的?把xml中的sql删除,它就玩不转了。

10.5. 接口方式怎么找到xml执行的

SqlSession的getMapper方法找到类,通过反射可以获取到类的全路径(包名.类名),相加后就定位到某个xml的命名空间namespace,在根据调用的方法去找到xml中某个标签的id属性。从而实现价值接口,调用接口的方法而间接找到xml中的标签,通过解析xml获取这个标签的内容,从而获取到sql语句。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/522846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++:设计一个线程安全的队列

文章目录 1. 目的2. 实现&#xff1f;验证&#xff01;makefileQueue 类的 public 成员单元测试 3. 实现 Queue 类的方案 1. 目的 串行的程序只用到单个 CPU 核心&#xff0c; 希望加速整个程序&#xff0c; 考虑使用多线程加速。典型情况下可以找到生产者、消费者&#xff0c…

基于ESP或ESP8266 单通道Lorawan网关硬件制作

软件代码设计资料下载链接》》 基于 Comresult PCB 的单通道网关 介绍 这是 ESP8266 LoRa 网关的最新版本。基于 ESP8266 mcu 的 LoRa 网关在过去几年里有了很大的发展。您想构建一个小型网关并保持尽可能多的 GPIO 引脚可用&#xff0c;Hallard 板是无与伦比的。另一种解决…

C++多态练习题

文章目录 1.虚函数的调用过程2.虚函数例题例题一例题二例题三例题四例题四 1.虚函数的调用过程 从汇编上面来看&#xff1a; []代表指针解引用操作 1.op指向test对象的首地址&#xff08;存放vptr&#xff09;&#xff0c;并存放在eax里面&#xff1b; 2.将eax所指之物(虚表…

使用不同的梯度下降法优化算法

本篇将使用以下几个梯度下降算法进行对比&#xff1a; 不使用任何的优化算法&#xff08;即整批数据集作为一次迭代更新梯度&#xff0c;也叫batch梯度下降&#xff0c;BGD&#xff09; mini-batch梯度下降法&#xff08;Mini-batchGD&#xff09; 使用具有动量的梯度下降算法&…

无标签背景图(负样本)的拼图代码

训练目标检测模型有个很令人头疼的问题&#xff0c;就是有些特征与要训练的特征较为相似的背景区域也被误检出来&#xff08;作为本应不该检测出来的负样本却被误检出为正样本的FP&#xff09;。 根据这一问题的解决办法&#xff0c;除了可以对正样本特征较为模糊或者有歧义的样…

Intel SGX学习笔记(2):用数组向Enclave传递5个数实现自增操作

写在前面 1、实现一个简单的Intel SGX的应用&#xff1a;非安全区定义初始化一个数组&#xff0c;数组里面存储5个数&#xff0c;然后向安全区&#xff08;enclave&#xff09;传入&#xff0c;在安全区中进行加减乘除&#xff0c;然后返回。 2、Intel SGX开发初学整体思路&a…

代码随想录算法训练营day39 | 62.不同路径,63. 不同路径 II

代码随想录算法训练营day39 | 62.不同路径&#xff0c;63. 不同路径 II 62.不同路径解法一&#xff1a;动态规划解法二&#xff1a;深度搜索&#xff08;明天补充&#xff09;解法三&#xff1a;数论&#xff08;明天补充&#xff09; 63. 不同路径 II解法一&#xff1a;动态规…

RuoYi-Vue下载与运行

一、源码下载 若依官网&#xff1a;RuoYi 若依官方网站 鼠标放到"源码地址"上&#xff0c;点击"RuoYi-Vue 前端分离版"。 跳转至Gitee页面&#xff0c;点击"克隆/下载"&#xff0c;复制HTTPS链接即可。 源码地址为&#xff1a;https://gitee.…

左值引用、右值引用,std::move() 的汇编解释

1&#xff1a;左值引用 引用其实还是指针&#xff0c;但回避了指针这个名字。由编译器完成从地址中取值。以vs2019反汇编&#xff1a; 如图&#xff0c;指针和引用的汇编代码完全一样。但引用在高级语言层面更友好&#xff0c;对人脑。比如可以少写一个 * 号和 -> 。 &…

F280049C实现Simulink调制,以及多个PWM实例之间的同步

文章目录 前言基本概念调制发波载波同步问题 前言 最近作实验碰到了载波不同步的问题&#xff0c;以前也有碰到过这个问题&#xff0c;现在终于解决了&#xff0c;做个记录。 为了以示区分&#xff0c;实例指ePWMx&#xff0c;x1,2,3,4,5,6,7,8&#xff1b;通道指ePWMxA/B&am…

如何使用jmeter进行压测

目录 1.概述 2.测试计划、线程组、取样器 3.调试运行 4.请求默认值 5.流量录制 6.模拟时间间隔 7.压力测试 8.报表 1.概述 一款工具&#xff0c;功能往往是很多的&#xff0c;细枝末节的地方也很多&#xff0c;实际的测试工作中&#xff0c;绝大多数场景会用到的也就是…

看大老如何用Postman+Jmeter实现接口实例

一、接口基础 为什么要单独测试接口&#xff1f; 1. 程序是分开开发的&#xff0c;前端还没有开发&#xff0c;后端已经开发完了&#xff0c;可以提前进入测试 2. 接口直接返回的数据------越底层发现bug&#xff0c;修复成本是越低的 3. 接口测试能模拟功能测试不能测到的异常…

数十位高级测工联合讲解Selenium自动化测试框架工作原理

一、Selenium是什么&#xff1f;   用官网的一句话来讲&#xff1a;Selenium automates browsers. Thats it&#xff01;简单来讲&#xff0c;Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作浏览器一样。支持…

uvm寄存器模型

一、基础知识 前门访问与后门访问是两种寄存器的访问方式。 所谓前门访问, 指的是通过模拟cpu在总线上发出读指令, 进行读写操作。 在这个过程中, 仿真时间( $time函数得到的时间) 是一直往前走的。而后门访问是与前门访问相对的概念。 它并不通过总线进行读写操作, 而是…

2023/5/14周报

目录 摘要 论文阅读 1、标题和现存问题 2、准备知识 3、模型结构 4、实验准备 5、实验结果 深度学习 1、大气数据和水质数据 2、数据清洗 3、项目框架设定 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇时空图卷积网络:交通预测的深度学习框架的论文。文章的时…

oracle使用with as创建临时表

一、业务需求 在oracle项目的开发过程中&#xff0c;使用sql编写好对应的分析报表内容后&#xff0c;由于sql分析报表涉及到的一些线别丢失&#xff0c;导致呈现的报表分类统计时固定用醒目颜色标识的统计行数据显示错位&#xff1b;因此需要修复分析报表填充完整的线别。 二、…

LeetCode 62 不同路径

题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#…

云上高校导航 小程序 开发教程

Gitee仓库&#xff1a;云上高校导航 GitHub仓库&#xff1a;云上高校导航 “云上高校导航”是一套基于小程序云开发的校园导航类系统开发方案&#xff0c;该开发方案可供开发者进行二次开发&#xff0c;用于解决师生和访客的校园出行需求。 项目优势及创新&#xff1a; 使…

Flink 常用API(2)——转换算子+聚合算子

转换算子&#xff08;Transformation&#xff09; 映射&#xff08;map&#xff09; 用于将数据流中的数据进行转换&#xff0c;形成新的数据流 “一一映射”&#xff0c;消费一个元素就产出一个元素 参数&#xff1a;接口 MapFunction 的实现 方法&#xff1a;map 返回值…

C#串口通信从入门到精通(13)——多个串口发送数据

文章目录 前言1、多串口数据的发送2、源码前言 我们在开发串口通信程序时,有时候会需要连接不止一个串口,这时候该怎么写程序呢?本文就来介绍多个串口数据的发送 1、多串口数据的发送 我们在之前的专栏中介绍了串口数据的发送,当时有提到过,我们是通过创建一个SerialPo…