SSM 架构基础

一、简介

Spring 框架是 Java 应用最广的框架,它的成功来源于理念,而不是技术本身,spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。

spring主要的核心依赖有 beans,code, context,spel 这是spring里最基本的也是最核心的jar包(或者说是依赖)

spring有两个核心思想:IOC (控制反转) , AOP(面向切面编程)

spring容器可以理解为生产对象(OBJECT)的地方,在这里容器不只是帮我们创建了对象那么简单,它负责了对象的整个生命周期--创建、装配、销毁。

而这里对象的创建管理的控制权都交给了Spring容器,所以这是一种控制权的反转,称为IOC容器,而这里IOC容器不只是Spring才有,很多框架也都有该技术。

springmvc是spring的子框架,继承于spring框架 , 在ssm框架环境中,springmvc可以向上的扫描去用spring的东西,但是spring却不能扫描到springmvc里面去。

springmvc也是接收请求,返回响应 ,实际上也是一个servlet ,dispatchServlet。

springmvc和servlet的流程是差不多的,都是接受请求,返回响应,和 Sping 无缝结合

mybatis是目前非常流行的持久层框架,功能很强大,然而其实现却比较简单、优雅。mybatis是一个半自动的orm框架,也还是需要自己去写sql语句

mybatis是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情:

  • 封装JDBC操作
  • 利用反射打通Java类与SQL语句之间的相互转换

mybatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便,所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。

mybatis和大部分框架一样需要一个配置文件,如果是和spring整合的话则不怎么需要,当然如果要开启缓存的话还是需要

然后需要mapper映射文件和dao层的类和方法所对应 , 在mapper里面写sql语句

单独的mybatis使用需要解析配置文件,然后去调用mapper里的sql语句

二、Spring

2.1 Spring xml写法

原始类:

public class Source {  
    private String property01; 
    private String property02; 
    /* setter and getter */
}

bean.xml 文件:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="source" class="pojo.Source">
        <property name="property01" value="v01"/>
        <property name="property02" value="v02"/>
    </bean>
</beans>  
  

测试类

public class TestSpring {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"applicationContext.xml"}
        );
        Source source = (Source) context.getBean("source");
        System.out.println(source.property01());
        System.out.println(source.property02());
    }
}

ApplicationContext 是 BeanFactory 的子接口之一,换句话说:BeanFactory 是 Spring IoC 容器所定义的最底层接口,而 ApplicationContext 是其最高级接口之一,并对 BeanFactory 功能做了许多的扩展,所以在绝大部分的工作场景下,都会使用 ApplicationContext 作为 Spring IoC 容器。

如果说BeanFactory是Sping的心脏,那么ApplicationContext就是完整的身躯了

2.2 通过注解装配 Bean

传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:

  • 如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低
  • 在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率

为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。

@Component(value = "source1")
public class Source {

    @Value("1")
    int id;

    @Value("student_name_1")
    String name;

    // getter and setter
}

@Component

把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>

@Component是一个元注解,意思是可以注解其他类注解,如@Controller @Service @Repository @Aspect。

官方的原话是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化

其他类级别的注解也可以被认定为是一种特殊类型的组件,比如@Repository @Aspect。所以,@Component可以注解其他类注解。

@Autowired (自动装配)注释可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。@Autowired 根据类型(type)进行自动注入,默认注入单例(SingleTon)的bean。就是一个。

如果发现找到有很多bean,则按照byName方式对比获取,若有名称一样的则可以加上@Qualifier("XXX")配置使用。若非必须装配则可以设置required=false。

@Component("studentService")
public class StudentServiceImp implements StudentService {

    @Autowired
    private Student source = null;

    public void printStudentInfo() {
        System.out.println(source.getName());
    }
}

@Configuration @Bean 注解

@Bean 注解 可以标记在方法和注解上面,主要标记在方法上.被标记的方法的返回值会被加入到springIOC容器之中

使用 @Bean 注解的好处就是能够动态获取一个 Bean 对象,能够根据环境不同得到不同的 Bean 对象。或者说将 Spring 和其他组件分离(其他组件不依赖 Spring,但是又想 Spring 管理生成的 Bean)

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}

这个配置就等同于之前在xml里的配置

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

2.3 AOP

AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

第一步:选择连接点
Spring 是方法级别的 AOP 框架,我们主要也是以某个类额某个方法作为连接点,另一种说法就是:选择哪一个类的哪一方法用以增强功能。

public void service() {
        // 核心的业务功能
        System.out.println("签合同");
        System.out.println("收房租");
    }

第二步:创建切面

@Component
@Aspect
class Broker {

    @Before("execution(* pojo.Landlord.service())")
    public void before(){
        System.out.println("带租客看房");
        System.out.println("谈价格");
    }

    @After("execution(* pojo.Landlord.service())")
    public void after(){
        System.out.println("交钥匙");
    }
}

第三步:定义切点

@Component
@Aspect
class Broker {

    @Pointcut("execution(* pojo.Landlord.service())")
    public void lService() {
    }

    @Before("lService()")
    public void before() {
        System.out.println("带租客看房");
        System.out.println("谈价格");
    }

    @After("lService()")
    public void after() {
        System.out.println("交钥匙");
    }
}

第四步:测试 AOP

三、SpringMVC

3.1 运行原理:

(1) Http请求:客户端请求提交到DispatcherServlet。
(2) 寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。
(3) 调用处理器:DispatcherServlet将请求提交到Controller。
(4)(5)调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView。
(6)(7)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定视图
(8) Http响应:视图负责将结果显示到客户端。

接口:
(1)DispatcherServlet接口:
Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。

(2)HandlerMapping接口:
能够完成客户请求到Controller映射。

(3)Controller接口:
需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。
Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

(4)ViewResolver接口:
Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

DispatcherServlet:
整个Spring MVC的核心。它负责接收HTTP请求组织协调Spring MVC的各个组成部分。其主要工作有以下三项:

  • 截获符合特定格式的URL请求。
  • 初始化DispatcherServlet上下文对应WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。
  • 初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中。

3.2 传统方式:

dispatcher-servlet.xml

    <bean id="simpleUrlHandlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <!-- /hello 路径的请求交给 id 为 helloController 的控制器处理-->
                <prop key="/hello">helloController</prop>
            </props>
        </property>
    </bean>
    <bean id="helloController" class="controller.HelloController"></bean>
</beans>   
    

Controller:

public class HelloController implements Controller {
    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mav = new ModelAndView("index.jsp");
        mav.addObject("message", "Hello Spring MVC");
        return mav;
    }
}

View: index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<h1>${message}</h1>

3.3 使用注解配置 Spring MVC

Controller:

@Controller
public class HelloController{

    @RequestMapping("/hello")
    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mav = new ModelAndView("index.jsp");
        mav.addObject("message", "Hello Spring MVC");
        return mav;
    }
}

使用 @Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面
若返回json等内容到页面,则需要加@ResponseBody注解,@RestController注解相当于@ResponseBody + @Controller合在一起的作用

使用@RequestMapping 注解映射请求路径,@RequestMapping 既可以定义在类上,也可以定义方法上

dispatcher-servlet.xml :

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 扫描controller下的组件 -->
    <context:component-scan base-package="controller"/>
</beans>

<!-- 配置视图解析器 -->
<bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/page/" />
    <property name="suffix" value=".jsp" />
</bean>

数据显示

@RequestMapping("hello")
public String testVelocity(Model model,String name){
    model.addAttribute("name",name);
    return "hello";
}

@RequestMapping("model")
public ModelAndView testModel(String name) {
    //构建ModelAndView实例,并设置跳转地址
    ModelAndView view = new ModelAndView("test");
    //将数据放置到ModelAndView对象view中,第二个参数可以是任何java类型
    view.addObject("name",name);
    //返回ModelAndView对象view
    return view;
}

跳转:

@RequestMapping("/jump")
public String jump() {
    return "redirect: ./hello";
}

四、MyBatis

4.1 基本配置

数据库配置文件:mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 别名 -->
    <typeAliases>
        <package name="pojo"/>
    </typeAliases>
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 映射文件 -->
    <mappers>
        <mapper resource="pojo/Student.xml"/>
    </mappers>
</configuration>

Mapper 文件:StudentMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pojo">
    <select id="listStudent" resultType="Student">
        select * from  student
    </select>

    <insert id="addStudent" parameterType="Student">
        insert into student (id, studentID, name) values (#{id},#{studentID},#{name})
    </insert>

    <delete id="deleteStudent" parameterType="Student">
        delete from student where id = #{id}
    </delete>

    <select id="getStudent" parameterType="_int" resultType="Student">
        select * from student where id= #{id}
    </select>

    <update id="updateStudent" parameterType="Student">
        update student set name=#{name} where id=#{id}
    </update>
</mapper>

测试类

public class TestMyBatis {
    public static void main(String[] args) throws IOException {
        // 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 然后根据 sqlSessionFactory 得到 session
        SqlSession session = sqlSessionFactory.openSession();

        // 增加学生
        Student student1 = new Student();
        student1.setId(4);
        student1.setStudentID(4);
        student1.setName("新增加的学生");
        session.insert("addStudent", student1);

        // 删除学生
        Student student2 = new Student();
        student2.setId(1);
        session.delete("deleteStudent", student2);

        // 获取学生
        Student student3 = session.selectOne("getStudent", 2);

        // 修改学生
        student3.setName("修改的学生");
        session.update("updateStudent", student3);

        // 最后通过 session 的 selectList() 方法调用 sql 语句 listStudent
        List listStudent = session.selectList("listStudent");
        for (Student student : listStudent) {
            System.out.println("ID:" + student.getId() + ",NAME:" + student.getName());
        }
        // 提交修改
        session.commit();
        // 关闭 session
        session.close();
    }
}

应用程序找 MyBatis 要数据 MyBatis 从数据库中找来数据

1.通过 mybatis-config.xml 定位哪个数据库
2.通过 Student.xml 执行对应的 sql 语句
3.基于 Student.xml 把返回的数据库封装在 Student 对象中
4.把多个 Student 对象装载一个 Student 集合中

4.2 使用注解开发 MyBatis

为 Mapper 增加注解:

public interface StudentMapper {

	// 根据 id 查询学生信息
	@Select("SELECT * FROM student WHERE student_id = #{id}")
	public Student findStudentById(int id) throws Exception;

	// 添加学生信息
	@Insert("INSERT INTO student(student_id, name) VALUES(#{id}, #{name})")
	public void insertStudent(Student student) throws Exception;

	// 删除学生信息
	@Delete("DELETE FROM student WHERE student_id = #{id}")
	public void deleteStudent(int id) throws Exception;

	// 修改学生信息
	@Update("UPDATE student SET name = #{name} WHERE student_id = #{id}")
	public void updateStudent(Student student) throws Exception;
}

mybatis-config.xml:

<mappers>
    <!--<mapper resource="pojo/StudentMapper.xml"/>-->
    <mapper class="mapper.StudentMapper"/>
</mappers>

四、Spring+SpringMVC+MyBatis (Maven)

4.1  创建SqlMapperContext.xml全局配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://www.mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
       <package name="com.fjm.ssm.po"/>
   </typeAliases> 

</configuration>

4.2 Spring 和 Mybatis 配置:

spring-mybatis.xml

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

    <!-- 配置数据库相关参数properties的属性:${url} -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        <property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/>
        <property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
        <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/>
    </bean>

    <!-- 配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 扫描entity包 使用别名 -->
        <property name="typeAliasesPackage" value="cn.wmyskxz.entity"/>
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!-- 配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="cn.wmyskxz.dao"/>
    </bean>
</beans>

4.3 Spring Service 配置:

spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd
       ">
     <!-- 扫描service包下所有使用注解的类型 --> 
     <context:component-scan base-package="cn.wmyskxz.service"/>
   
    <!--配置事务管理器  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"></property>
    </bean>
        
    <!--配置通知  -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播特性 -->
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="query*" read-only="true" />
            <tx:method name="select*" read-only="true" />
            <tx:method name="get*" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!--配置切面  -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.fjm.ssm.service.*.*(..))"/>
    </aop:config>
 </beans>

4.4 Spring MVC 的相关配置

spring-mvc.xml

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

    <!-- 扫描web相关的bean -->
    <context:component-scan base-package="cn.wmyskxz.controller"/>

    <!-- 开启SpringMVC注解模式 -->
    <mvc:annotation-driven/>

    <!-- 静态资源默认servlet配置 -->
    <mvc:default-servlet-handler/>

    <!-- 配置jsp 显示ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

4.5 jdbc.properties 中配置数据库连接池
6

jdbc.driver=com.mysql.jdbc.Driver
#数据库地址
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8
#用户名
jdbc.username=root
#密码
jdbc.password=root
#最大连接数
c3p0.maxPoolSize=30
#最小连接数
c3p0.minPoolSize=10
#关闭连接后不自动commit
c3p0.autoCommitOnClose=false
#获取连接超时时间
c3p0.checkoutTimeout=10000
#当获取连接失败重试次数
c3p0.acquireRetryAttempts=2

4.6 创建接口和实现类,调用 mapper 接口实现数据调用

@Service
public class ItemsServiceImpl implements ItemsService {
    
    @Autowired
    private ItemsExtMapper mapper;
    @Override
    public List<Items> queryItemsByItemsQuery(ItemsQuery vo) {
        return mapper.ItemsQuery(vo);
    }
}


参考:
https://www.cnblogs.com/wmyskxz/p/8916365.html
https://www.cnblogs.com/fengjunming/p/7583229.html


Comments are closed.