Spring+SprinMVC+MyBatis注解方式简易模板
Spring+SprinMVC+MyBatis注解方式简易模板代码Demo GitHub访问 ssm-tpl-anno
一、数据准备
创建数据库test,执行下方SQL创建表ssm-tpl-cfg
/*Navicat Premium Data TransferSource Server : 127.0.0.1Source Server Type : MySQLSource Server Version : 80030Source Host : 127.0.0.1:3306Source Schema : testTarget Server Type : MySQLTarget Server Version : 80030File Encoding : 65001Date: 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、passwordDruidDataSource 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);// 配置监控统计拦截的filterstry {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.htmlpublic 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>*/@Beanpublic 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>*/@Beanpublic 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/**"/>*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/js/").addResourceLocations("/js/**");registry.addResourceHandler("/css/").addResourceLocations("/css/**");registry.addResourceHandler("/images/").addResourceLocations("/images/**");}// 文件解析器@Beanpublic CommonsMultipartResolver multipartResolver() {CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();// maxUploadSizePerFile:单个文件大小限制(byte)// maxUploadSize:整个请求大小限制(byte)commonsMultipartResolver.setMaxUploadSizePerFile(10 * 1024 * 1024); // 10McommonsMultipartResolver.setMaxUploadSize(100 * 1024 * 1024); // 100Mreturn 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 {@Overridepublic 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;}@Overridepublic List<TestEntity> listTests(TestEntity cond) {return testDAO.listTests(cond);}@Overridepublic TestEntity singleTest(TestEntity cond) {return testDAO.singleTest(cond);}@Overridepublic boolean saveTest(TestEntity cond) {cond.setId(MajorKeyUtil.idSeq());cond.setFlowImgStr(cond.getFlowImg().toString());return testDAO.insertTest(cond) > 0;}@Overridepublic boolean modifyTest(TestEntity cond) {return testDAO.updateTest(cond) > 0;}@Overridepublic boolean removeTest(TestEntity cond) {return testDAO.deleteTest(cond) > 0;}@Overridepublic 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`WHERE1 = 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`WHERE1 = 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">DELETEFROM `ssm-tpl-cfg`WHERE 1 = 1<include refid="baseWhere"/></delete><!-- 根据主键集删除测试记录 --><delete id="deleteTests" parameterType="long">DELETEFROM `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: wangfeihuDate: 2022/10/16Time: 18:35To 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 配置项目访问路径

三、访问测试

一个简单的基于注解的增删改查就实现了
相关文章:
Spring+SprinMVC+MyBatis注解方式简易模板
SpringSprinMVCMyBatis注解方式简易模板代码Demo GitHub访问 ssm-tpl-anno 一、数据准备 创建数据库test,执行下方SQL创建表ssm-tpl-cfg /*Navicat Premium Data TransferSource Server : 127.0.0.1Source Server Type : MySQLSource Server Version :…...
Python基础第五篇(Python数据容器)
文章目录 一、数据容器入门二、数据容器 list 列表(1),list 列表定义(2),list列表的索引(3),list列表的常见操作(4),list列表的遍历 三、数据容器:tuple(元组)(1),tuple元组定义(2),tuple元组的索引(3),tuple元组的常见操作(4),tuple元组的遍…...
【H3C】配置AAA认证和Telnet远程登陆,S5130 Series交换机
AAA配置步骤为: 1.开启telent远程登陆服务 2.创建用户,设置用户名、密码、用户的服务类型 3.配置终端登录的数量 4.配置vlan-if的ip地址,用来远程登陆 5.允许对应的vlan通过 1.开启telent远程登陆服务 sys …...
GaussDB数据库中的MERGE INTO介绍
一、前言 二、GaussDB MERGE INTO 语句的原理概述 1、MERGE INTO 语句原理 2、MERGE INTO 的语法 3、语法解释 三、GaussDB MERGE INTO 语句的应用场景 四、GaussDB MERGE INTO 语句的示例 1、示例场景举例 2、示例实现过程 1)创建两个实验表,并…...
2024年上海高考数学最后四个多月的备考攻略,目标140+
亲爱的同学们,寒假已经来临,春节即将到来,距离2024年上海高考已经余额不足5个月了。作为让许多学子头疼,也是拉分大户的数学科目,你准备好了吗?今天,六分成长为您分享上海高考数学最后四个多月的…...
SSL证书自动化管理有什么好处?如何实现SSL证书自动化?
SSL证书是用于加密网站与用户之间传输数据的关键元素,在维护网络安全方面,管理SSL证书与部署SSL证书一样重要。定期更新、监测和更换SSL证书,可以确保网站的安全性和合规性。而自动化管理可以为此节省时间,并避免人为错误和不必要…...
路由器初始化配置、功能配置
实验环境 拓扑图 Ip规划表(各组使用自己的IP规划表) 部门 主机数量 网络地址 子网掩码 网关 可用ip Vlan 市场部 38 192.168.131.0 255.255.255.0 192.168.131.1 2-254 11 研发部 53 192.168.132.0 255.255.255.0 192.168.132.1 2-2…...
node介绍
1.node是什么 Node是一个基于Chrome V8引擎的JS运行环境。 Node不是一个独立的语言、node不是JS框架。 Node是一个除了浏览器之外的、可以让JS运行的环境 Node.js是一个让JS运行在服务端的开发平台,是使用事件驱动,异步非阻塞I/O,单线程&…...
海外抖音TikTok、正在内测 AI 生成歌曲功能,依靠大语言模型 Bloom 进行文本生成歌曲
近日,据外媒The Verge报道,TikTok正在测试一项新功能,利用大语言模型Bloom的AI能力,允许用户上传歌词文本,并使用AI为其添加声音。这一创新旨在为用户提供更多创作音乐的工具和选项。 Bloom 是由AI初创公司Hugging Fac…...
【ARM 嵌入式 编译系列 3.6 -- 删除lib中的某个文件】
请阅读【嵌入式开发学习必备专栏 之 ARM GCC 编译专栏】 文章目录 删除lib中的某个文件 删除lib中的某个文件 比如,如果要删除 libc.a 静态库中的特定对象文件并重新使用这个静态库,在终端中可以使用 ar 命令。ar 是一个归档工具,它可以创建…...
web架构师编辑器内容-图层拖动排序功能的开发
新的学习方法 用手写简单方法实现一个功能然后用比较成熟的第三方解决方案即能学习原理又能学习第三方库的使用 从两个DEMO开始 Vue Draggable Next: Vue Draggable NextReact Sortable HOC: React Sortable HOC 列表排序的三个阶段 拖动开始(dragstart&#x…...
3.RHCSA脚本配置及通过node2改密码
运行脚本发现node2不成功 脚本破解 选第二个 Ctrl x 换行 破解成功后做node2的改密码题 回到redhat, 发现检测程序检测密码题成功,得了8分....
AtCoder Regular Contest 170(A~B)
A - Yet Another AB Problem 给你两个字符串S和T,你可以对S执行操作,选择两个字符,将前面的改为A,后面的改为B,最少操作几次可以把S改成T。如果改不成就输出-1。 从左往右一个一个改过去,分类讨论&#x…...
rk1126, 实现 yolov8 目标检测
基于 RKNN 1126 实现 yolov8 目标检测 Ⓜ️ RKNN 模型转换 ONNX yolo export model./weights/yolov8s.pt formatonnx导出 RKNN 这里选择输出 concat 输入两个节点 onnx::Concat_425 和 onnx::Concat_426 from rknn.api import RKNNONNX_MODEL ./weights/yolov8s.onnxRKNN_MOD…...
【软件测试】学习笔记-网站可扩展性架构设计
可扩展性,指的是网站的架构设计能够快速适应需求的变化,当需要增加新的功能实现时,对原有架构不需要做修改或者做很少的修改就能够快速实现新的业务需求。 从这个定义中,我们很容易就可以得出衡量网站可扩展性设计优秀与否的主要标…...
深度学习常用代码总结(k-means, NMS)
目录 一、k-means 算法 二、NMS 一、k-means 算法 k-means 是一种无监督聚类算法,常用的聚类算法还有 DBSCAN。k-means 由于其原理简单,可解释强,实现方便,收敛速度快,在数据挖掘、数据分析、异常检测、模式识别、金…...
数据结构·顺序表应用
本节应用是要用顺序表实现一个通讯录,收录联系人的姓名、性别、电话号码、住址、年龄 顺序表的实现在上一节中已经完成了,本节的任务其实就是应用上节写出来的代码的那些接口函数功能,做出来一个好看的,可…...
第一个 OpenGL 程序:旋转的立方体(VS2022 / MFC)
文章目录 OpenGL API开发环境在 MFC 中使用 OpenGL初始化 OpenGL绘制图形重置视口大小 创建 MFC 对话框项目添加 OpenGL 头文件和库文件初始化 OpenGL画一个正方形OpenGL 坐标系改变默认颜色 重置视口大小绘制立方体使用箭头按键旋转立方体深度测试添加纹理应用纹理换一个纹理 …...
剩余银饰的重量 - 华为OD统一考试
OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 有N块二手市场收集的银饰,每块银饰的重量都是正整数,收集到的银饰会被熔化用于打造新的饰品。 每一回合,从中选出三块 最重的…...
redis远程连接不上解决办法
问题描述: redis远程服务端运行在192.168.3.90计算机上,客户端计算机(ip:192.168.3.110)通过redsi-cli.exe客户端工具连接时,没有反应,连接不上。 如图所示: 解决步骤: 步骤一&…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
