SSM整合
- 项目整体架构说明
- [1. 创建Maven项目](#1. 创建Maven项目)
- [2. 配置web.xml](#2. 配置web.xml)
- [4. 配置springmvc.xml](#4. 配置springmvc.xml)
- [5. 配置spring.xml](#5. 配置spring.xml)
- [6. 配置mybatis-config.xml以及创建mapper接口和mapper配置文件](#6. 配置mybatis-config.xml以及创建mapper接口和mapper配置文件)
- [7. 配置log4j.xml](#7. 配置log4j.xml)
- [8. 后端CURD测试](#8. 后端CURD测试)
-
- [8.1 在数据库中插入数据](#8.1 在数据库中插入数据)
- [8.2 pojo中的实体类Employee](#8.2 pojo中的实体类Employee)
- [8.3 mapper层的EmployMapper接口](#8.3 mapper层的EmployMapper接口)
- [8.4 mapper层的EmployeeMapper.xml配置文件(resources目录下)](#8.4 mapper层的EmployeeMapper.xml配置文件(resources目录下))
- [8.5 service层的EmployeeService接口 和 service.impl层的EmployeeServiceImpl类](#8.5 service层的EmployeeService接口 和 service.impl层的EmployeeServiceImpl类)
- [8.6 统一返回结果Result以及响应码Code](#8.6 统一返回结果Result以及响应码Code)
- [8.7 controller层的EmployeeController](#8.7 controller层的EmployeeController)
- [8.8 postman测试](#8.8 postman测试)
项目整体架构说明
1. 创建Maven项目
网上创建Maven的教程有很多,在这里就不再累赘了,有以下几个注意点:
pom.xml
中的打包方式一定要为war
包,不配置默认是jar
包,在后面配置tomcat
的时候会找不到Artifacts
情况;- 创建新的
Maven
项目是没有web.xml
的,需要进入Project Structure
进行配置,如下图所示;
pom.xml
依赖如下所示,如果有需要可以直接copy
使用:
注意 : 如果在项目启动过程中出现:validateConnection false
等错误,通常原因是因为druid
数据源的版本与MySql 8.0
版本不匹配导致的,可以参考文章:MySQL 8.0 驱动与阿里druid版本兼容操作
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>day25_ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.3.1</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--mybatis和spring的整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
</project>
2. 配置web.xml
web.xml
配置的文件内容:
- 配置Spring的编码过滤器
CharacterEncodingFilter
; - 配置处理请求方式
PUT
和DELETE
的过滤器HiddenHttpMethodFilter
; - 配置SpringMVC的前端控制器
DispatcherServlet
; - 设置Spring的配置文件的位置和名称;
- 配置Spring监听器
ContextLoaderListener
;
1、2、3
点都很容易理解,在SpringMVC配置中都需要,那么整合的时候也必须可少。那下面就分析一下为什么还需要4、5
点。一个web
项目启动起来至少有两个IOC
容器:一个是SpringMVC管理的IOC
容器,一个是Spring管理的IOC
容器。这两个容器有什么关系吗?
答案是肯定的,根据MVC
三层架构知,controller层依赖service层,service层依赖mapper层;而SpringMVC管理的IOC
容器只管理controller层组件bean,Spring管理的组件IOC
容器管理除controler层的所有组件bean。
所以这两个容器之间肯定是存在关系的,Spring管理的IOC
容器必须要早于SpringMVC管理的IOC
容器生成。并结合官方文档可知:SpringMVC管理的IOC
容器是一个父容器,Spring管理的IOC
容器是一个子容器,所以Spring管理的IOC
容器必须早于SpringMVC管理的IOC
容器生成,所以就设置了4、5
条内容。
Spring提供了监听器ContextLoaderListener
,实现ServletContextListener
接口,可监听ServletContext
的状态,在web服务器的启动,读取Spring的配置文件,创建Spring的IOC
容器。web
应用中必须在web.xm
l中配置
xml
<!--自定义Spring配置文件的位置和名称-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<!--
配置Spring的监听器,在服务器启动时加载Spring的配置文件
Spring配置文件默认位置和名称:/WEB-INF/applicationContext.xml
可通过上下文参数自定义Spring配置文件的位置和名称
-->
<listenerclass>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
web.xml
全部内容:
xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置Spring的编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--请求编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--相应编码-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--PUT、DELETE请求-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置SpringMVC的前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--设置SpringMVC配置文件的位置和名称-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--设置Spring的配置文件的位置和名称-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<!--配置Spring监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
4. 配置springmvc.xml
springmvc.xml
可以配置的文件内容:
- 扫描controller层的包;
- 配置Thymeleaf视图解析器;
- 配置文件上传解析器
multipartResolver
;(multipartResolver
是一个接口,实现类为CommonsMultipartResolver
) - 配置访问首页的试图控制;(需要再
webapp/WEB-INF/templates
目录下创建 一个index.html
页面) - 配置默认的servlet处理静态资源;
- 开启MVC的注解驱动;
- 拦截器和异常解析器也在该配置文件里面配置,这里就不展示了;
springmvc.xml
全部内容,可以直接copy使用:
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描controller层的包-->
<context:component-scan base-package="qc.lsm.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!--/WEB-INF/templates/xxx.html-->
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
<!--配置访问首页的试图控制-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--配置默认的servlet处理静态资源-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--开启MVC的注解驱动 -->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
5. 配置spring.xml
Spring配置文件中的内容
- 扫描除了controller层的所有组件;
- 配置Druid数据源并引入外部文件jdbc.properties;
- 配置JdbcTemplate;
- 配置事务管理器组件
DataSourceTransactionManager
; - 开启事务的注解驱动;
- 开启aop自动代理;
- 配置用于创建
SqlSessionFactory
的工程bean,这样就可以简化mybatis配置文件; - 配置mapper接口的扫描配置:由
mybatis-spring
提供,可以将指定包下所有的mapper接口创建动态代理并将这些代理动态作为IOC容器的bean管理;
在SSM整合的时候添加了7-8
的原因在于简化mybatis
, 之前学习mybaits的时候很麻烦,要先加载mybaits-config.xml
配置文件,然后创建SqlSessionFactory
,获取Session
以及对应的mapper
等。
在SSM整合的时候进行了简化,第7项:可以直接在spring.xml
配置文件里面进行创建SqlSessionFactory
的工程bean,该组件里面的属性包括加载mybatis配置文件的路径,设置数据源,设置类型别名所对应的包以及映射文件的路径等,大大简化的mybatis-config.xml
的配置。在spring.xml
中进行配置后就不需要再mybatis-config.xml
中进行配置了。
xml
<!--配置用于创建SqlSessionFactory的工程bean,这样就可以简化mybatis配置文件-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--设置MyBatis配置文件的路径-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--设置数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--设置类型别名所对应的包-->
<property name="typeAliasesPackage" value="qc.lsm.pojo"></property>
<!--设置映射文件的路径,若映射文件所在路径和mapper接口所在路径一致,则不需要设置-->
<!-- <property name="mapperLocations" value="classpath:mapper/*.xml"></property>-->
</bean>
第8项个人感觉非常牛皮,配置之后可以将指定包下所有的mapper接口创建动态代理并将这些代理动态作为IOC容器的bean管理。
xml
<!--配置mapper接口的扫描配置:由mybatis-spring提供,可以将指定包下所有的mapper接口创建动态代理并将这些代理动态作为IOC容器的bean管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="qc.lsm.mapper"></property>
</bean>
spring.xml
全部内容,可以直接copy使用:
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描除了controller层的所有组件;-->
<context:component-scan base-package="qc.lsm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--引入外部文件jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--配置Druid数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器组件DataSourceTransactionManager-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<!--开启aop自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--配置用于创建SqlSessionFactory的工程bean,这样就可以简化mybatis配置文件-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!--设置MyBatis配置文件的路径-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--设置数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--设置类型别名所对应的包-->
<property name="typeAliasesPackage" value="qc.lsm.pojo"></property>
<!--设置映射文件的路径,若映射文件所在路径和mapper接口所在路径一致,则不需要设置-->
<!-- <property name="mapperLocations" value="classpath:mapper/*.xml"></property>-->
</bean>
<!--配置mapper接口的扫描配置:由mybatis-spring提供,可以将指定包下所有的mapper接口创建动态代理并将这些代理动态作为IOC容器的bean管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="qc.lsm.mapper"></property>
</bean>
</beans>
6. 配置mybatis-config.xml以及创建mapper接口和mapper配置文件
在学习mybatis的时候,mybatis-config.xml
配置文件内容如下:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//MyBatis.org//DTD Config 3.0//EN"
"http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration>
<!--引入properties文件,此时就可以${属性名}的方式访问属性值-->
<properties resource="jdbc.properties"></properties>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/><!--将表中字段的下划线自动转换为驼峰-->
<setting name="lazyLoadingEnabled" value="true"/><!--开启延迟加载-->
</settings>
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<typeAliases>
<!--
typeAlias:设置某个具体的类型的别名
属性:type:需要设置别名的类型的全类名
alias:设置此类型的别名,且别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名
-->
<!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>-->
<!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="user"> </typeAlias>-->
<!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写-->
<package name="com.atguigu.bean"/>
</typeAliases>
<!--
environments:设置多个连接数据库的环境
属性:default:设置默认使用的环境的id
-->
<environments default="mysql_test">
<!--
environment:设置具体的连接数据库的环境信息
属性:id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,表示默认使用的环境
-->
<environment id="mysql_test">
<!--
transactionManager:设置事务管理方式
属性:
type:设置事务管理方式,type="JDBC|MANAGED"
type="JDBC":设置当前环境的事务管理都必须手动处理
type="MANAGED":设置事务被管理,例如spring中的AOP
-->
<transactionManager type="JDBC"/>
<!--
dataSource:设置数据源
属性:
type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"
type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建
type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建
type="JNDI":调用上下文中的数据源
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/><!--设置驱动类的全类名-->
<property name="url" value="${jdbc.url}"/> <!--设置连接数据库的连接地址-->
<property name="username" value="${jdbc.username}"/><!--设置连接数据库的用户名-->
<property name="password" value="${jdbc.password}"/><!--设置连接数据库的密码-->
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<!-- <mapper resource="UserMapper.xml"/> 这样需要每一个文件都需要一个resource-->
<!--
以包为单位,将包下所有的映射文件引入核心配置文件
注意:1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下
2. mapper接口要和mapper映射文件的名字一致
-->
<package name="com.atguigu.mapper"/>
</mappers>
</configuration>
但是为了简化mybaits,咱们在spring.xml
配置文件里面设置了SqlSessionFactory
的工厂bean,并在里面配置了下面的内容:
- 设置mybatis配置文件的路径;
- 设立数据源;
- 设置类型别名所对应的包;
- 设置映射文件路径,若映射文件所在路径和mapper接口所在路径一致,则不需要设置;
所以mybatis-config.xml
中的内容如下所示:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//MyBatis.org//DTD Config 3.0//EN"
"http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/><!--将表中字段的下划线自动转换为驼峰-->
<setting name="lazyLoadingEnabled" value="true"/><!--开启延迟加载-->
</settings>
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
7. 配置log4j.xml
log4j 8种日志级别:
- All: 最低等级的,用于打开所有日志记录.
- Trace: 是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,我们可以设置最低日志级别不让他输出.
- Debug: 指出细粒度信息事件对调试应用程序是非常有帮助的.
- Info: 消息在粗粒度级别上突出强调应用程序的运行过程.
- Warn: 输出警告及warn以下级别的日志.
- Error: 输出错误信息日志.
- Fatal: 输出每个严重的错误事件将会导致应用程序的退出的日志.
- OFF: 最高等级的,用于关闭所有日志记录.
日志级别等级按照从低到高为 :All < Trace < Debug < Info < Warn < Error < Fatal < OFF
Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}%m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
8. 后端CURD测试
8.1 在数据库中插入数据
8.2 pojo中的实体类Employee
java
public class Employee {
private Integer empId;
private String empName;
private Integer age;
private String sex;
private String email;
// 无参构造器,有参构造器,set/get方法,toString方法...
}
8.3 mapper层的EmployMapper接口
java
package qc.lsm.mapper;
import qc.lsm.pojo.Employee;
import java.util.List;
public interface EmployeeMapper {
/**
* 根据id查询单个员工的信息
* @param id
* @return
*/
Employee selectEmployeeById(Integer id);
/**
* 查询所有员工的信息
* @return
*/
List<Employee> selectAllEmployee();
/**
* 添加员工信息
* @param employee
* @return
*/
int addEmployee(Employee employee);
/**
* 根据员工id删除员工信息
* @param empId
* @return
*/
int deleteEmployee(Integer empId);
/**
* 根据员工id修改员工信息
* @param employee
* @return
*/
int updateEmployee(Employee employee);
}
8.4 mapper层的EmployeeMapper.xml配置文件(resources目录下)
注意 :由于表t_emp
的字段名与类Employee
中的属性名不一致,所以在查询的时候使用了resultMap
标签;
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="qc.lsm.mapper.EmployeeMapper">
<!--
1. 查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系
- resultType:自动映射,用于 ====属性名和表中字段名一致===== 的情况
- resultMap:自定义映射,用于 ====一对多或多对一或字段名和属性名不一致===== 的情况
2. 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常TooManyResultsException;
但是若查询的数据只有一条,可以使用实体类或集合作为返回值-->
<resultMap id="employeeResultMap" type="Employee">
<id property="empId" column="emp_id"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<!--Employee selectEmployeeById(Integer id);-->
<select id="selectEmployeeById" resultMap="employeeResultMap">
select * from t_emp where emp_id = #{id};
</select>
<!-- List<Employee> selectAllEmployee();-->
<select id="selectAllEmployee" resultMap="employeeResultMap">
select * from t_emp;
</select>
<!--
useGeneratedKeys:设置当前标签中的sql使用了自增的主键
keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数User对象的某个属性中
-->
<!--int addEmployee(Employee employee);-->
<insert id="addEmployee" parameterType="qc.lsm.pojo.Employee">
insert into t_emp values(null, #{empName}, #{age}, #{sex},#{email})
</insert>
<!--int deleteEmployee(Integer empId);-->
<delete id="deleteEmployee" parameterType="Integer">
delete from t_emp where emp_id = #{id}
</delete>
<!--int updateEmployee(Employee employee);-->
<update id="updateEmployee" parameterType="Employee">
update t_emp set emp_name = #{empName}, age = #{age}, sex = #{sex}, email = #{email} where emp_id = #{empId};
</update>
</mapper>
8.5 service层的EmployeeService接口 和 service.impl层的EmployeeServiceImpl类
EmployeeService接口
java
public interface EmployeeService {
/**
* 根据id查询单个员工的信息
* @param id
* @return
*/
Employee selectEmployeeById(Integer id);
/**
* 查询所有员工的信息
* @return
*/
List<Employee> selectAllEmployee();
/**
* 添加员工信息
* @param employee
* @return
*/
int addEmployee(Employee employee);
/**
* 根据员工id删除员工信息
* @param empId
* @return
*/
int deleteEmployee(Integer empId);
/**
* 根据员工id修改员工信息
* @param employee
* @return
*/
int updateEmployee( Employee employee);
}
EmployeeService接口的实现类EmployeeServiceImpl
java
package qc.lsm.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.lsm.mapper.EmployeeMapper;
import qc.lsm.pojo.Employee;
import qc.lsm.service.EmployeeService;
import java.util.List;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
public Employee selectEmployeeById(Integer id) {
System.out.println("employeeMapper: " + employeeMapper);
return employeeMapper.selectEmployeeById(id);
}
@Override
public List<Employee> selectAllEmployee() {
System.out.println("employeeMapper: " + employeeMapper);
return employeeMapper.selectAllEmployee();
}
@Override
public int addEmployee(Employee employee) {
return employeeMapper.addEmployee(employee);
}
@Override
public int deleteEmployee(Integer empId) {
return employeeMapper.deleteEmployee(empId);
}
@Override
public int updateEmployee(Employee employee) {
return employeeMapper.updateEmployee(employee);
}
}
8.6 统一返回结果Result以及响应码Code
响应码Code类
java
package qc.lsm.utils;
public class Code {
public static final Integer ADD_OK = 10001;
public static final Integer ADD_ERROR = 10000;
public static final Integer SELETE_OK = 20001;
public static final Integer SELETE_ERROR = 20000;
public static final Integer UPDATE_OK = 30001;
public static final Integer UPDATE_ERROR = 30000;
public static final Integer DELETE_OK = 40001;
public static final Integer DELETE_ERROR = 40000;
}
统一返回结果类Result
java
package qc.lsm.controller;
/**
* 定义统一返回格式类
*/
public class Result {
// 描述统一格式中的数据
private Object data;
// 描述统计格式中的编码,用于区分操作,可以简化配置0/1表示成功失败
private Integer code;
// 描述统一格式中的消息,可选属性
private String msg;
public Result() {
}
public Result(Object data, Integer code) {
this.data = data;
this.code = code;
}
public Result(Object data, Integer code, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
// set/get方法
@Override
public String toString() {
return "Result{" +
"data=" + data +
", code=" + code +
", msg='" + msg + '\'' +
'}';
}
}
8.7 controller层的EmployeeController
java
package qc.lsm.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import qc.lsm.pojo.Employee;
import qc.lsm.service.EmployeeService;
import qc.lsm.utils.Code;
import java.util.List;
/**
* @author Mr.Lu
* @version 1.0
* @date 2023-09-08 20:13
*/
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/selectEmployeeById/{id}")
public Result selectEmployeeById(@PathVariable("id") Integer id){
Employee employee = employeeService.selectEmployeeById(id);
if(employee == null){
return new Result(null, Code.SELETE_ERROR, "查询失败");
}
return new Result(employee,Code.SELETE_OK, "查询成功");
}
@RequestMapping("/selectAll")
public Result selectAllEmployee(){
List<Employee> employees = employeeService.selectAllEmployee();
if(employees == null){
return new Result(null, Code.SELETE_ERROR, "查询失败");
}
return new Result(employees, Code.SELETE_OK, "查询成功");
}
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public Result addEmployee(@RequestBody Employee employee){
System.out.println("employee: " + employee);
int count = employeeService.addEmployee(employee);
if(count > 0) {
List<Employee> employees = employeeService.selectAllEmployee();
return new Result(employees, Code.ADD_OK, "添加成功");
}
return new Result(null, Code.ADD_ERROR, "添加失败");
}
@RequestMapping("/deleteEmployeeById/{id}")
public Result deleteEmployeeById(@PathVariable("id") Integer id){
int count = employeeService.deleteEmployee(id);
if(count > 0){
List<Employee> employees = employeeService.selectAllEmployee();
return new Result(employees, Code.DELETE_OK, "删除成功");
}
return new Result(null, Code.DELETE_ERROR, "删除失败");
}
@RequestMapping("/updateEmployee")
public Result updateEmployee(@RequestBody Employee employee){
int count = employeeService.updateEmployee(employee);
if(count > 0){
return new Result(employeeService.selectEmployeeById(employee.getEmpId()), Code.UPDATE_OK, "更新成功"); }
return new Result(null, Code.UPDATE_ERROR, "更新失败");
}
}
8.8 postman测试
测试1:根据id
查询员工信息http://localhost/ssm/employee/selectEmployeeById/2
java
@RequestMapping("/selectEmployeeById/{id}")
public Result selectEmployeeById(@PathVariable("id") Integer id){
Employee employee = employeeService.selectEmployeeById(id);
if(employee == null){
return new Result(null, Code.SELETE_ERROR, "查询失败");
}
return new Result(employee,Code.SELETE_OK, "查询成功");
}
测试2:查询所有员工信息http://localhost/ssm/employee/selectAll
java
@RequestMapping("/selectAll")
public Result selectAllEmployee(){
List<Employee> employees = employeeService.selectAllEmployee();
if(employees == null){
return new Result(null, Code.SELETE_ERROR, "查询失败");
}
return new Result(employees, Code.SELETE_OK, "查询成功");
}
测试3:添加员工http://localhost/ssm/employee/addEmployee
java
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public Result addEmployee(@RequestBody Employee employee){
System.out.println("employee: " + employee);
int count = employeeService.addEmployee(employee);
if(count > 0) {
List<Employee> employees = employeeService.selectAllEmployee();
return new Result(employees, Code.ADD_OK, "添加成功");
}
return new Result(null, Code.ADD_ERROR, "添加失败");
}
测试4:根据id删除员工信息http://localhost/ssm/employee/deleteEmployeeById/2
java
@RequestMapping("/deleteEmployeeById/{id}")
public Result deleteEmployeeById(@PathVariable("id") Integer id){
int count = employeeService.deleteEmployee(id);
if(count > 0){
List<Employee> employees = employeeService.selectAllEmployee();
return new Result(employees, Code.DELETE_OK, "删除成功");
}
return new Result(null, Code.DELETE_ERROR, "删除失败");
}
测试5:更新员工信息http://localhost/ssm/employee/updateEmployee
java
@RequestMapping("/updateEmployee")
public Result updateEmployee(@RequestBody Employee employee){
int count = employeeService.updateEmployee(employee);
if(count > 0){
return new Result(employeeService.selectEmployeeById(employee.getEmpId()), Code.UPDATE_OK, "更新成功"); }
return new Result(null, Code.UPDATE_ERROR, "更新失败");
}