Spring+SprinMVC+MyBatis注解方式简易模板

news2024/9/30 9:21:21

Spring+SprinMVC+MyBatis注解方式简易模板代码Demo GitHub访问 ssm-tpl-anno

一、数据准备

创建数据库test,执行下方SQL创建表ssm-tpl-cfg

/*
 Navicat Premium Data Transfer

 Source Server         : 127.0.0.1
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : 127.0.0.1:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 80030
 File Encoding         : 65001

 Date: 17/10/2022 00:52:07
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for ssm-tpl-cfg
-- ----------------------------
DROP TABLE IF EXISTS `ssm-tpl-cfg`;
CREATE TABLE `ssm-tpl-cfg` (
  `id` bigint NOT NULL COMMENT '主键编号',
  `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '测试名称',
  PRIMARY KEY (`id`)
) COMMENT '初始SSM表结构数据' ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- ----------------------------
-- Records of ssm-tpl-cfg
-- ----------------------------
BEGIN;
INSERT INTO `ssm-tpl-cfg` (`id`, `name`) VALUES (2210162246100000, '左翰林');
INSERT INTO `ssm-tpl-cfg` (`id`, `name`) VALUES (2210162257100000, '刘卓神');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

二、代码实现

2.1 pom.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.tpl.ssm.anno</groupId>
    <artifactId>ssm-tpl-anno</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <spring_version>5.1.18.RELEASE</spring_version>
        <jackson_version>2.9.7</jackson_version>
    </properties>

    <dependencies>
        <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-aop</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-beans</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</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-messaging</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.15.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.15.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.7</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.7</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.findbugs</groupId>
            <artifactId>annotations</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.25</version>
        </dependency>
    </dependencies>
</project>

2.2 Spring和Mybatis配置

package com.tpl.ssm.anno.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
 * Spring配置类
 *
 * <!-- 扫描service -->
 * <context:component-scan base-package="com.tpl.ssm.cfg.service"/>
 */
@ComponentScan(basePackages = {"com.tpl.ssm.anno.service"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = org.springframework.stereotype.Controller.class)
})
@EnableTransactionManagement
@Configuration
public class SpringConfig {

    private static final Logger logger = LoggerFactory.getLogger(SpringConfig.class);

    /*
     * <!-- 配置数据库连接池 -->
     * <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
     *     <!-- 四大连接参数 -->
     *     <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="initialSize" value="${jdbc.initialSize}"/>
     *     <property name="minIdle" value="${jdbc.minIdle}"/>
     *     <property name="maxActive" value="${jdbc.maxActive}"/>
     *     <property name="maxWait" value="${jdbc.maxWait}"/>
     *     <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
     *     <property name="timeBetweenEvictionRunsMillis" value="60000"/>
     *     <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
     *     <property name="minEvictableIdleTimeMillis" value="300000" />
     *     <!-- Druid用来测试连接是否可用的SQL语句,默认值每种数据库都不相同-->
     *     <property name="validationQuery" value="SELECT 'x'" />
     *     <!-- 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除. -->
     *     <property name="testWhileIdle" value="true" />
     *     <!-- 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 -->
     *     <property name="testOnBorrow" value="false" />
     *     <!-- 指明是否在归还到池中前进行检验 -->
     *     <property name="testOnReturn" value="false" />
     *     <!-- 配置监控统计拦截的filters -->
     *     <property name="filters" value="wall,stat" />
     * </bean>
     */
    @Bean(name = "dataSource")
    public DruidDataSource druidDataSource() {
        // 基本属性 url、user、password
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");

        // 配置初始化大小、最小、最大
        druidDataSource.setInitialSize(10);
        druidDataSource.setMinIdle(10);
        druidDataSource.setMaxActive(50);

        // 配置获取连接等待超时的时间
        druidDataSource.setMaxWait(60000);
        // 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        druidDataSource.setTimeBetweenEvictionRunsMillis(60000);

        // 配置一个连接在池中最小生存的时间,单位是毫秒
        druidDataSource.setMinEvictableIdleTimeMillis(300000);

        druidDataSource.setValidationQuery("SELECT 1");
        druidDataSource.setTestWhileIdle(true);
        druidDataSource.setTestOnBorrow(false);
        druidDataSource.setTestOnReturn(false);

        // 打开PSCache,并且指定每个连接上PSCache的大小
        // 如果用Oracle,则把poolPreparedStatements配置为true,
        // mysql可以配置为false。
        druidDataSource.setPoolPreparedStatements(true);
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(20);

        // 配置监控统计拦截的filters
        try {
            druidDataSource.setFilters("wall,stat");
        } catch (SQLException e) {
            logger.error("配置监控统计拦截的filters error: ", e);
        }
        return druidDataSource;
    }

    /*
     * <!-- 配置sessionFactory -->
     * <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
     *     <!-- 注入数据源 -->
     *     <property name="dataSource" ref="dataSource"/>
     *     <!-- mapper文件位置 -->
     *     <property name="mapperLocations" value="classpath:mapper/*DAO.xml"/>
     *     <!-- mybatis核心配置文件位置 -->
     *     <property name="configLocation" value="classpath:config/mybatis-config.xml"/>
     * </bean>
     */
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactoryBean() {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setMapperLocations(resolveMapperLocations());
        sqlSessionFactory.setDataSource(druidDataSource());
        /*
         * <?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="cacheEnabled" value="true"/>
         *         <!-- 开启控制台打印SQL -->
         *         <setting name="logImpl" value="STDOUT_LOGGING"/>
         *     </settings>
         *
         *     <!-- 别名 -->
         *     <typeAliases>
         *         <package name="com.tpl.ssm.cfg.entity"/>
         *     </typeAliases>
         * </configuration>
         */
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        mybatisConfiguration.setMapUnderscoreToCamelCase(true);
        mybatisConfiguration.setCacheEnabled(true);
        mybatisConfiguration.setLogImpl(StdOutImpl.class);
        mybatisConfiguration.getTypeAliasRegistry().registerAliases("com.tpl.ssm.anno.entity");

        sqlSessionFactory.setConfiguration(mybatisConfiguration);
        return sqlSessionFactory;
    }

    // https://wenku.baidu.com/view/1b9ade1640323968011ca300a6c30c225901f0c2.html
    public Resource[] resolveMapperLocations() {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        List<String> mapperLocations = new ArrayList<>();
        mapperLocations.add("classpath:mapper/*DAO.xml");
        List<Resource> resources = new ArrayList<>();
        for (String mapperLocation : mapperLocations) {
            Resource[] mappers = new Resource[0];
            try {
                mappers = resolver.getResources(mapperLocation);
            } catch (IOException e) {
                e.printStackTrace();
            }
            resources.addAll(Arrays.asList(mappers));
        }
        return resources.toArray(new Resource[0]);
    }

    /*
     * <!-- 配置扫描mapper生成代理对象 -->
     * <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     *     <property name="basePackage" value="com.tpl.ssm.cfg.dao"/>
     *     <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
     * </bean>
     */
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.tpl.ssm.anno.dao");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer;
    }

    /* 事务管理器配置
     * <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     *     <property name="dataSource" ref="dataSourceProxy"/>
     * </bean>
     */
    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

}

2.3 SpringMVC配置

package com.tpl.ssm.anno.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

/* 开启controller注解支持
 * 注意事项请参考:http://jinnianshilongnian.iteye.com/blog/1762632
 *
 * <context:component-scan base-package="com.tpl.ssm.cfg.controller"/>
 */
@ComponentScan(basePackages = {
        "com.tpl.ssm.anno.controller"
}, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = org.springframework.stereotype.Controller.class),
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = org.springframework.web.bind.annotation.ControllerAdvice.class)
}, useDefaultFilters = false)
@EnableWebMvc
@Configuration
// <import resource="spring-mvc-xxx.xml"/>
// @Import(value = {SpringMvcXxxConfig.class})
public class SpringMVCConfig implements WebMvcConfigurer {

    /* <!-- 配置SpringMVC视图解析器 -->
     * <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     *     <property name="prefix" value="/pages/"/>
     *     <property name="suffix" value=".jsp"/>
     * </bean>
     */
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        resolver.setPrefix("/pages/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    /* <!-- 释放静态资源文件 -->
     * <mvc:resources mapping="/js/" location="/js/**"/>
     * <mvc:resources mapping="/css/" location="/css/**"/>
     * <mvc:resources mapping="/images/" location="/images/**"/>
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/").addResourceLocations("/js/**");
        registry.addResourceHandler("/css/").addResourceLocations("/css/**");
        registry.addResourceHandler("/images/").addResourceLocations("/images/**");
    }

    // 文件解析器
    @Bean
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        // maxUploadSizePerFile:单个文件大小限制(byte)
        // maxUploadSize:整个请求大小限制(byte)
        commonsMultipartResolver.setMaxUploadSizePerFile(10 * 1024 * 1024); // 10M
        commonsMultipartResolver.setMaxUploadSize(100 * 1024 * 1024); // 100M
        return commonsMultipartResolver;
    }

}

2.4 web.xml配置

package com.tpl.ssm.anno.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * Web应用启动入口
 * <p/>
 * <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 * xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 * xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
 * http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
 * </web-app>
 */
public class WebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 父容器配置
        AnnotationConfigWebApplicationContext springCtx = new AnnotationConfigWebApplicationContext();
        springCtx.setDisplayName("ssm-tpl-anno"); // 部署应用的名称 <display-name>ssm-tpl-anno</display-name>

        /*
         * <!-- Spring配置文件开始  -->
         * <context-param>
         *     <param-name>contextConfigLocation</param-name>
         *     <param-value>
         *         classpath:spring-config.xml
         *     </param-value>
         * </context-param>
         * <listener>
         *     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
         * </listener>
         * <!-- Spring配置文件结束 -->
         */
        springCtx.register(SpringConfig.class);
        // 通过监听器加载配置信息
        servletContext.addListener(new ContextLoaderListener(springCtx));

        /* 可以使用RequestContextHolder.currentRequestAttributes() 获取到请求的attr
         * <listener>
         *     <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
         * </listener>
         */
        servletContext.addListener(org.springframework.web.context.request.RequestContextListener.class);

        // 子容器配置
        AnnotationConfigWebApplicationContext mvcCtx = new AnnotationConfigWebApplicationContext();
        /*
         * <!-- SpringMVC配置文件开始  -->
         * <servlet>
         *     <servlet-name>springMVC</servlet-name>
         *     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         *     <init-param>
         *         <param-name>contextConfigLocation</param-name>
         *         <param-value>classpath:spring-mvc.xml</param-value>
         *     </init-param>
         *     <load-on-startup>1</load-on-startup>
         *     <async-supported>true</async-supported>
         * </servlet>
         * <servlet-mapping>
         *     <servlet-name>springMVC</servlet-name>
         *     <url-pattern>/</url-pattern>
         * </servlet-mapping>
         * <!-- SpringMVC配置文件结束  -->
         */
        mvcCtx.register(SpringMVCConfig.class);
        ServletRegistration.Dynamic servlet = servletContext.addServlet(
                "DispatcherServlet",
                new DispatcherServlet(mvcCtx));
        servlet.setLoadOnStartup(1);
        servlet.setAsyncSupported(true);
        servlet.addMapping("/");

        /*
         * <!-- 设置servlet编码开始 -->
         * <filter>
         *     <filter-name>CharacterEncodingFilter</filter-name>
         *     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
         *     <async-supported>true</async-supported>
         *     <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>
         * <!-- 设置servlet编码结束 -->
         */
        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter(
                "CharacterEncodingFilter",
                new CharacterEncodingFilter("UTF-8", true));
        encodingFilter.setAsyncSupported(true);
        encodingFilter.addMappingForUrlPatterns(null, false, "/*");
    }
}

2.5 Entity

package com.tpl.ssm.anno.entity;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 测试实体
 */
public class TestEntity {

    /**
     * 主键编号
     */
    private Long id;

    /**
     * 测试名称
     */
    private String name;

    private JSONObject flowImg;
    private String flowImgStr;


    /**
     * 扩展字段
     */
    @JsonIgnore
    @TableField(exist = false)
    private Map<String, Object> ext = new LinkedHashMap<>(5);

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Map<String, Object> getExt() {
        return ext;
    }

    public void setExt(Map<String, Object> ext) {
        this.ext = ext;
    }

    public JSONObject getFlowImg() {
        return flowImg;
    }

    public void setFlowImg(JSONObject flowImg) {
        this.flowImg = flowImg;
    }

    public String getFlowImgStr() {
        return flowImgStr;
    }

    public void setFlowImgStr(String flowImgStr) {
        this.flowImgStr = flowImgStr;
    }
}

2.6 Controller

package com.tpl.ssm.anno.controller;

import com.tpl.ssm.anno.entity.TestEntity;
import com.tpl.ssm.anno.service.TestService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/**
 * 1. Spring5.1.x -> jackson2.9.x
 * 2.The origin server did not find a current representation for the target resource
 * 原因是WEB-INF只能转发进去, 重定向是进不去的
 */
@Controller
@RequestMapping("/test")
public class TestController {

    private final TestService testService;

    public TestController(TestService testService) {
        this.testService = testService;
    }

    @GetMapping("/")
    public String listTests(TestEntity test, Model model) {
        List<TestEntity> tests = testService.listTests(test);
        model.addAttribute("tests", tests);
        return "test";
    }

    @PostMapping("/save")
    public String saveTest(@RequestBody TestEntity test) {
        testService.saveTest(test);
        return "redirect:/test/";
    }

    @PostMapping("/modify")
    public String modifyTest(TestEntity test) {
        testService.modifyTest(test);
        return "redirect:/test/";
    }

    @RequestMapping("/remove")
    public String removeTest(TestEntity test) {
        testService.removeTest(test);
        return "redirect:/test/";
    }

}

2.7 Service

package com.tpl.ssm.anno.service;

import com.tpl.ssm.anno.entity.TestEntity;

import java.util.List;

public interface TestService {

    /**
     * 测试集
     *
     * @param cond 查询条件
     * @return 测试集
     */
    public List<TestEntity> listTests(TestEntity cond);

    /**
     * 单一测试实体
     *
     * @param cond 查询条件
     * @return 测试实体
     */
    public TestEntity singleTest(TestEntity cond);

    /**
     * 新增测试记录
     *
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public boolean saveTest(TestEntity cond);

    /**
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public boolean modifyTest(TestEntity cond);

    /**
     * 删除一条测试记录
     *
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public boolean removeTest(TestEntity cond);

    /**
     * 删除多条测试记录
     *
     * @param testIds 测试实体主键集
     * @return 受影响的条数
     */
    public boolean removeTests(List<Long> testIds);

}
package com.tpl.ssm.anno.service.impl;

import com.tpl.ssm.anno.dao.TestDAO;
import com.tpl.ssm.anno.entity.TestEntity;
import com.tpl.ssm.anno.service.TestService;
import com.tpl.ssm.anno.util.MajorKeyUtil;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class TestServiceImpl implements TestService {

    private final TestDAO testDAO;

    public TestServiceImpl(TestDAO testDAO) {
        this.testDAO = testDAO;
    }

    @Override
    public List<TestEntity> listTests(TestEntity cond) {
        return testDAO.listTests(cond);
    }

    @Override
    public TestEntity singleTest(TestEntity cond) {
        return testDAO.singleTest(cond);
    }

    @Override
    public boolean saveTest(TestEntity cond) {
        cond.setId(MajorKeyUtil.idSeq());
        cond.setFlowImgStr(cond.getFlowImg().toString());
        return testDAO.insertTest(cond) > 0;
    }

    @Override
    public boolean modifyTest(TestEntity cond) {
        return testDAO.updateTest(cond) > 0;
    }

    @Override
    public boolean removeTest(TestEntity cond) {
        return testDAO.deleteTest(cond) > 0;
    }

    @Override
    public boolean removeTests(List<Long> testIds) {
        return testDAO.deleteTests(testIds) > 0;
    }
}

2.8 DAO

package com.tpl.ssm.anno.dao;

import com.tpl.ssm.anno.entity.TestEntity;

import java.util.List;

/**
 * 测试DAO
 * <p>
 * 1.查询测试记录列表 - listTests
 * 2.查询单个测试记录 - singleTest
 * 3.新增测试记录 - insertTest
 * 4.修改测试记录 - updateTest
 * 5.删除测试记录 - deleteTest
 * 6.根据主键集删除测试记录 - deleteTests
 */
public interface TestDAO {

    /**
     * 测试集
     *
     * @param cond 查询条件
     * @return 测试集
     */
    public List<TestEntity> listTests(TestEntity cond);

    /**
     * 单一测试实体
     *
     * @param cond 查询条件
     * @return 测试实体
     */
    public TestEntity singleTest(TestEntity cond);

    /**
     * 新增测试记录
     *
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public int insertTest(TestEntity cond);

    /**
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public int updateTest(TestEntity cond);

    /**
     * 删除一条测试记录
     *
     * @param cond 查询条件
     * @return 受影响的条数
     */
    public int deleteTest(TestEntity cond);

    /**
     * 删除多条测试记录
     *
     * @param testIds 测试实体主键集
     * @return 受影响的条数
     */
    public int deleteTests(List<Long> testIds);

}
<?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="com.tpl.ssm.anno.dao.TestDAO">

    <!-- 基础查询 sql 片段 -->
    <sql id="baseSelect">
        SELECT id, name
    </sql>

    <!-- 基础查询 where 片段 -->
    <sql id="baseWhere">
        <if test="id != null">
            AND id = #{id}
        </if>
        <if test="name != null and name != ''">
            AND name like CONCAT('%', #{name})
        </if>
    </sql>

    <!-- 查询测试记录列表 -->
    <select id="listTests" parameterType="com.tpl.ssm.anno.entity.TestEntity" resultType="com.tpl.ssm.anno.entity.TestEntity">
        <include refid="baseSelect"/>
        FROM `ssm-tpl-cfg`
        WHERE
        1 = 1
        <include refid="baseWhere"/>
    </select>

    <!-- 查询单个测试记录 -->
    <select id="singleTest" parameterType="com.tpl.ssm.anno.entity.TestEntity" resultType="com.tpl.ssm.anno.entity.TestEntity">
        <include refid="baseSelect"/>
        FROM `ssm-tpl-cfg`
        WHERE
        1 = 1
        <include refid="baseWhere"/>
        limit 1
    </select>

    <!-- 新增测试记录 -->
    <insert id="insertTest" parameterType="com.tpl.ssm.anno.entity.TestEntity">
        INSERT INTO `ssm-tpl-cfg`(id, name, flow_img)
        VALUES (#{id}, #{name}, #{flowImgStr})
    </insert>

    <!-- 修改测试记录 -->
    <update id="updateTest" parameterType="com.tpl.ssm.anno.entity.TestEntity">
        UPDATE `ssm-tpl-cfg`
        SET
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        WHERE id = #{id}
    </update>

    <!-- 删除测试记录 -->
    <delete id="deleteTest" parameterType="com.tpl.ssm.anno.entity.TestEntity">
        DELETE
        FROM `ssm-tpl-cfg`
        WHERE 1 = 1
        <include refid="baseWhere"/>
    </delete>

    <!-- 根据主键集删除测试记录 -->
    <delete id="deleteTests" parameterType="long">
        DELETE
        FROM `ssm-tpl-cfg`
        WHERE id in
        <foreach collection="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </delete>
</mapper>

2.9 webapps/pages/test.jsp

<%--
  Created by IntelliJ IDEA.
  User: wangfeihu
  Date: 2022/10/16
  Time: 18:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>CRUD TEST</title>
</head>
<body>
<table>
    <c:forEach items="${tests}" var="test">
        <tr>
            <td>${test.id}</td>
            <td>${test.name}</td>
            <td>
                <button onclick="let modifyForms = document.getElementsByName('modifyForm'); modifyForms.forEach(item => item.style.display = 'none'); document.getElementById('form${test.id}').style.display = 'inline'">修改</button>
                <button onclick="location.href='${pageContext.request.contextPath}/test/remove?id=${test.id}'">删除</button>
            </td>
            <td>
                <form id="form${test.id}" name="modifyForm" action="${pageContext.request.contextPath}/test/modify" method="post" style="display: none">
                    <input hidden name="id" value="${test.id}">
                    <input name="name" value="${test.name}">
                    <button type="submit">确认修改</button>
                </form>
            </td>
        </tr>
    </c:forEach>
</table>

<form action="${pageContext.request.contextPath}/test/save" method="post">
    <label>
        <input name="name" id="name" placeholder="请输入测试名称~">
    </label>
    <button type="submit">提交</button>
</form>
</body>
</html>

2.10 配置项目访问路径

配置项目访问路径

三、访问测试

访问测试

一个简单的基于注解的增删改查就实现了

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

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

相关文章

使用 OpenCV 添加(混合)两个图像

目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是线性混合以及为什么它有用;如何使用 addWeighted&#xff08;&#xff09; 添加两个图像 理论 注意 下面的解释属于Richard Szeliski的《计算机视觉&#xff1a;算法和应用》一书 从我们之前的教程中&#xff0c;…

Github 无法正常访问?一招解决

查询IP网址: https://ip.chinaz.com/ 主页如下&#xff1a; 分别查询以下三个网址的IP&#xff1a; github.com github.global.ssl.fastly.net assets-cdn.github.com 修改 hosts 文件&#xff1a; 将 /etc/hosts 复制到 home 下 sudo cp /etc/hosts ./ gedit hosts 在底下…

K8s知识点总结_part2

为什么我们会需要 Pod&#xff1f; 容器的本质是一种特殊的进程&#xff0c;如果映射到系统中&#xff0c;容器镜像就是这个系统里的“.exe”安装包。 那么 Kubernetes 呢&#xff1f;Kubernetes 就是操作系统 在一个真正的操作系统里&#xff0c;进程并不是“孤苦伶仃”地独…

vue3-组件通信

1. 父传子-defineProps 父组件&#xff1a; <script setup> import { ref } from vueimport SonCom from /components/Son-com.vueconst message ref(parent)</script><template><div></div><SonCom car"沃尔沃" :message"…

【linux基础】linux root用户密码忘记解决方式

方式一&#xff1a;进入单用户模式 1.开启虚拟机的时候&#xff0c;按下“e”健进入用户引导界面 2.再按下“e”&#xff0c;进入内核的编辑 3.找到kernel开头的选项&#xff0c;再次按下“e” 4. 输入 5. 按下“b”&#xff0c;启动 6. 启动后&#xff0c;输入passwd&#xf…

【网站项目】基于springboot与vue的电子商城项目

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

LC 对角线遍历

LC 对角线遍历 题目描述&#xff1a; 给你一个大小为 m x n 的矩阵 mat &#xff0c;请以对角线遍历的顺序&#xff0c;用一个数组返回这个矩阵中的所有元素。 题目实例&#xff1a; 示例一&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[…

解决Windows下Goland的Terminal设置为Git Bash失败

路径不要选错了&#xff1a; 如果还是不行&#xff1a; 把bash路径加进去试试 goland设置Terminal

华为欧拉操作系统结合内网穿透实现固定公网地址SSH远程连接

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

2.机器学习-K最近邻(k-Nearest Neighbor,KNN)分类算法原理讲解

2️⃣机器学习-K最近邻&#xff08;k-Nearest Neighbor&#xff0c;KNN&#xff09;分类算法原理讲解 个人简介一算法概述二算法思想2.1 KNN的优缺点 三实例演示3.1电影分类3.2使用KNN算法预测 鸢(yuan)尾花 的种类3.3 预测年收入是否大于50K美元 个人简介 &#x1f3d8;️&…

解开缺省参数与函数重载的衣裳

解开缺省参数与函数重载的衣裳 代码是如何由编译器变为可执行文件&#xff1f;预处理 ->编译->汇编->链接预处理编译汇编链接 语法了解缺省参数语法实践语法探究函数重载语法实践语法探究结语 本期和大家一起探究C中的缺省函数与重载函数的语法说明与汇编过程代码是如…

Packet Tracer - 配置第 3 层交换和VLAN间路由

地址分配表 设备 接口 IP 地址/前缀 MLS VLAN 10 192.168.10.254 /24 MLS VLAN 10 2001:db8:acad:10::1/64 MLS VLAN 20 192.168.20.254 /24 MLS VLAN 20 2001:db8:acad:20::1/64 MLS VLAN 30 192.168.30.254/24 MLS VLAN 30 2001:db8:acad:30::1/64 MLS …

某瓜数据app 获取达人直播商品信息接口 Sign

文章目录 声明指定直播间获取商品信息达人主页所有的商品列表接口声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请私信我立即删除! 之前写过:某瓜数据app Sign 具体算法分析请看上一篇,这次看一下不同…

深度学习与大数据在自然语言处理中的应用与进展

引言 在当今社会&#xff0c;深度学习和大数据技术的快速发展为自然语言处理&#xff08;NLP&#xff09;领域带来了显著的进步。这种技术能够使计算机更好地理解和生成人类语言&#xff0c;从而推动了搜索引擎、语音助手、机器翻译等领域的创新和改进。 NLP的发展与技术进步…

golang学习笔记——http.Handle和http.HandleFunc的区别与type func巧妙运用

文章目录 http.Handle和http.HandleFunc的区别http.Handle分析type func巧妙运用 http.HandleFunc分析总结参考资料 http.Handle和http.HandleFunc的区别 http.Handle和http.HandleFunc的区别体现了Go语言接口的巧妙运用 下面代码启动了一个 http 服务器&#xff0c;监听 808…

怎么使用AI人工智能抠图?不妨试试这样做

在数字时代的浪潮中&#xff0c;人工智能技术如春雨般悄然渗透到各个领域&#xff0c;其中尤以图像处理领域为甚。在这场技术的革新中&#xff0c;AI抠图应运而生&#xff0c;它凭借自动识别和提取图像中目标物体的神奇能力&#xff0c;成为图像处理领域的璀璨新星。通过背景与…

编程和数值计算平台:MATLAB R2023a(Win/Mac)激活版

MATLAB R2023a是一款强大的数值计算和科学编程软件&#xff0c;广泛应用于工程、科学和数学领域。 win版&#xff1a;https://soft.macxf.com/soft/3541.html?idMzE5MTM%3D mac版&#xff1a;https://www.macz.com/mac/9321.html?idOTI2NjQ5Jl8mMjcuMTg2LjkuOTg%3D 以下是MAT…

EtherNet/IP开发:C++开发CIP源代码

① 介绍一下CIP CIP是一种考虑到自动化行业而设计的通用协议。然而&#xff0c;由于其开放性&#xff0c;它可以并且已经应用于更多的领域。CIP网络库包含若干卷&#xff1a; 第1卷介绍了适用于所有网络自适应的CIP的常见方面。本卷包含通用对象库和设备配置文件库&#xff0…

Linux与windows互相传输文件之rzsz命令

文章目录 关于rzsz安装软件使用命令方法一&#xff1a;直接拖拽方法二&#xff1a;直接在终端输入rz 关于rzsz 这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件 安装完毕之后可以通过拖拽的方式将文件上传过去 首先看一下我们的机器可以使用网络吗&#xff…

Spring Boot 4.0:构建云原生Java应用的前沿工具

目录 前言 Spring Boot简介 Spring Boot 的新特性 1. 支持JDK 17 2. 集成云原生组件 3. 响应式编程支持 4. 更强大的安全性 5. 更简化的配置 Spring Boot 的应用场景 1. 云原生应用开发 2. 响应式应用程序 3. 安全性要求高的应用 4. JDK 17的应用 总结 作…