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客户端工具连接时,没有反应,连接不上。 如图所示: 解决步骤: 步骤一&…...
今天开始学爬虫1
1.1:import urllib错误 module urllib has no attribute request应该import urllib.requestimport urllib.requesturlhttp://www.baidu.com/ responseurllib.request.urlopen(url) contentresponse.read().decode(utf-8) print(content)2.1#返回字节 contentrespons…...
MiniMax Agent 正式更名 Mavis 上线多智能体协作
如果你用过AI助手,大概都有过这种感受:一个AI同时干太多事,要么顾此失彼,要么卡在某个环节原地转圈。 MiniMax显然也看到了这个问题。 5 月 13 日,他们正式宣布旗下Agent产品全面升级,并给它起了个新名字—…...
保姆级教程:解决PyTorchViz安装报错,手把手教你用AlexNet模型可视化
PyTorch模型可视化实战:从安装报错到AlexNet结构解析全指南 在深度学习模型开发过程中,可视化工具如同开发者的"第二双眼睛"。PyTorchViz作为PyTorch生态中轻量级但功能强大的可视化工具,能直观展示模型的计算图结构,帮…...
机器学习中的过拟合与欠拟合:如何解决模型泛化问题
在人工智能技术飞速发展的当下,机器学习模型在软件测试领域的应用愈发广泛,从自动化测试用例生成到缺陷预测,再到性能瓶颈分析,都离不开机器学习的助力。然而,模型的泛化能力始终是制约其在实际测试场景中发挥作用的关…...
AzurLaneAutoScript:解放双手的碧蓝航线智能自动化脚本
AzurLaneAutoScript:解放双手的碧蓝航线智能自动化脚本 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研,全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 还在为《…...
观察使用Token Plan套餐前后月度AI调用成本的变化趋势
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 观察使用Token Plan套餐前后月度AI调用成本的变化趋势 对于频繁调用大模型API的开发者或团队而言,成本的可预测性与可控…...
别再乱用sudo了!麒麟KYLINOS下用ACL实现安全的精细化权限控制
麒麟KYLINOS权限管理革命:用ACL替代sudo的精细化控制实战 在麒麟KYLINOS操作系统中,许多管理员习惯性地使用sudo或简单粗暴的chmod 777来解决权限问题,这种"一刀切"的做法实际上为系统安全埋下了重大隐患。想象一下这样的场景&…...
告别Nginx配置!用miniserve在Windows/Mac/Linux三分钟内搞定文件共享
告别Nginx配置!用miniserve在Windows/Mac/Linux三分钟内搞定文件共享 你是否曾在团队协作时,为了快速分享一个安装包或设计稿,不得不忍受FTP的繁琐配置?或是被Nginx的虚拟主机设置搞得头晕目眩?现在,这一切…...
光学萌新看过来:用Lighttools 8.4.0配合Solidworks做光机设计,第一步安装和环境配置怎么做?
光学与机械协同设计:Lighttools 8.4.0与Solidworks环境配置全指南 在光机一体化设计领域,光学仿真软件与机械建模工具的协同工作已成为行业标配。对于刚接触光学设计的机械工程师,或是需要将光学分析融入机械设计流程的团队而言,掌…...
从标签页混乱到高效工作流:Tabee如何彻底改变我的浏览器体验
从标签页混乱到高效工作流:Tabee如何彻底改变我的浏览器体验 【免费下载链接】chrome-tab-modifier Take control of your tabs 项目地址: https://gitcode.com/gh_mirrors/ch/chrome-tab-modifier 你是否曾经在几十个标签页中迷失方向?每个标签页…...
