项目结构
效果图
yml文件
server:
port: 8083
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/spring?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: root
#模板引擎
thymeleaf:
#禁用缓存 默认false
cache: false
mode: HTML5
prefix: classpath:/templates/
suffix: .html
#指定编码
encoding: utf-8
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
type-aliases-package: com.wang.pojo
configuration:
#驼峰命名规则
map-underscore-to-camel-case: true
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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wang</groupId>
<artifactId>springBoot-plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springBoot-plus</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
<scope>compile</scope>
</dependency>
<!-- 模板引擎 代码生成-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
数据库数据和表要的话私信
config
自动生成工具包,自动生成有个插件可以在idea插件搜索mybatisplus下载重启idea就行了
不会用可以私信
package com.wang.config;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* <p>
* mysql 代码生成器
* </p>
*/
public class Generator {
/**
* RUN THIS
*/
public static void main(String[] args) {
//获取控制台的数据
Scanner scanner = new Scanner(System.in);
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
System.out.println("请输入文件输出目录的模块或者项目的地址:");
String projectPath = scanner.nextLine();
gc.setOutputDir(projectPath + "/src/main/java"); //生成文件的输出目录
gc.setAuthor("jjh"); //作者
gc.setFileOverride(true); //是否覆蓋已有文件 默认值:false
gc.setOpen(false); //是否打开输出目录 默认值:true
gc.setBaseColumnList(true); //开启 baseColumnList 默认false
gc.setBaseResultMap(true); //开启 BaseResultMap 默认false
// gc.setEntityName("%sEntity"); //实体命名方式 默认值:null 例如:%sEntity 生成 UserEntity
gc.setMapperName("%sMapper"); //mapper 命名方式 默认值:null 例如:%sDao 生成 UserDao
gc.setXmlName("%sMapper"); //Mapper xml 命名方式 默认值:null 例如:%sDao 生成 UserDao.xml
gc.setServiceName("%sService"); //service 命名方式 默认值:null 例如:%sBusiness 生成 UserBusiness
gc.setServiceImplName("%sServiceImpl"); //service impl 命名方式 默认值:null 例如:%sBusinessImpl 生成 UserBusinessImpl
gc.setControllerName("%sController"); //controller 命名方式 默认值:null 例如:%sAction 生成 UserAction
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/spring?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
// pc.setModuleName(scanner("模块名"));
// pc.setParent("com.stu");
System.out.println("请输入模块名:");
String name = scanner.nextLine();
//自定义包配置
pc.setParent(name);
pc.setModuleName(null);
pc.setMapper("mapper");
pc.setEntity("pojo");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setController("controller");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return projectPath + "/src/main/resources/mapper/" + /*pc.getModuleName() + "/" +*/
tableInfo.getEntityName() + "Mapper" +
StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置 数据库表配置,通过该配置,可指定需要生成哪些表或者排除哪些表
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel); //表名生成策略
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略, 未指定按照 naming 执行
// strategy.setCapitalMode(true); // 全局大写命名 ORACLE 注意
// strategy.setTablePrefix("prefix"); //表前缀
// strategy.setSuperEntityClass("com.stu.domain"); //自定义继承的Entity类全称,带包名
// strategy.setSuperEntityColumns(new String[] { "test_id", "age" }); //自定义实体,公共字段
strategy.setEntityLombokModel(true); //【实体】是否为lombok模型(默认 false
strategy.setRestControllerStyle(true); //生成 @RestController 控制器
// strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController"); //自定义继承的Controller类全称,带包名
// strategy.setInclude(scanner("表名")); //需要包含的表名,允许正则表达式(与exclude二选一配置)
System.out.println("请输入映射的表名:");
String tables = scanner.nextLine();
String[] num = tables.split(",");
strategy.setInclude(num); // 需要生成的表可以多张表
// strategy.setExclude(new String[]{"test"}); // 排除生成的表
//如果数据库有前缀,生成文件时是否要前缀acl_
// strategy.setTablePrefix("bus_");
// strategy.setTablePrefix("sys_");
strategy.setControllerMappingHyphenStyle(true); //驼峰转连字符
strategy.setTablePrefix(pc.getModuleName() + "_"); //是否生成实体时,生成字段注解
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
首页访问
package com.wang.config;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import java.io.IOException;
@Configuration
public class MybatisConfig {
// @Bean
// public PageInterceptor pageInterceptor() {
// PageInterceptor pageInterceptor = new PageInterceptor();
// // 详见 com.github.pagehelper.page.PageParams
// Properties p = new Properties();
p.setProperty("offsetAsPageNum", "false");
p.setProperty("rowBoundsWithCount", "false");
p.setProperty("reasonable", "false");
// // 设置数据库方言 , 也可以不设置,会动态获取
// p.setProperty("helperDialect", "mysql");
// pageInterceptor.setProperties(p);
// return pageInterceptor;
// }
@EventListener({ApplicationReadyEvent.class})
void applicationReadyEvent() {
// System.out.println("应用已经准备就绪 ... 启动浏览器");
// 这里需要注url:端口号+测试类方法名
String url = "http://localhost:8083/goods/list";
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("rundll32 url.dll,FileProtocolHandler " + url);
} catch (IOException e) {
e.printStackTrace();
}
}
}
分页插件配置
package com.wang.config;
/*
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
*/
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*@Configuration用于定义配置类, 相当于 配置的头部
可替换xml配置文件,被注解的类内部包含有一个或多个被
@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext类进行扫描,
并用于构建bean定义,初始化Spring容器。 注意:@Configuration注解的配置类有如下要求:*/
@Configuration
public class MybatisPlusConfig {
//@Configuration启动容器+@Bean注册Bean
/**
* mybatis拦截器 注册插件
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// 初始化拦截器
MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/*@Configuation等价于<Beans></Beans>
@Bean等价于<Bean></Bean>
@ComponentScan等价于<context:component-scan base-package="com.xxx"/>*/
}
访问html工具包
package com.wang.config;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("{page}.html")
public String toPage(String page){
return page;
}
}
实体类
package com.wang.config;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("{page}.html")
public String toPage(String page){
return page;
}
}
package com.wang.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
*
* </p>
*
* @author jjh
* @since 2022-11-26
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class Type implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String typename;
}
controller层(因为用到插件,对于简单的查询不需要写sql语句,直接调用就行了,复杂的还是要手写)
package com.wang.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wang.pojo.Goods;
import com.wang.pojo.Type;
import com.wang.service.impl.GoodsServiceImpl;
import com.wang.service.impl.TypeServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author jjh
* @since 2022-11-26
*/
@Controller
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsServiceImpl goodsService;
@Autowired
private TypeServiceImpl typeService;
@RequestMapping("/list")
public String allList(@RequestParam(value = "pageSize", required = false, defaultValue = "1") Integer pageSize,
@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum, Model model,Goods goods){
//分页信息封装Page对象
Page<Goods> pages = new Page<>(pageNum,pageSize);
QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
//判断要模糊查询的数据是否为空,在放进条件控制器queryWrapper
if(!StringUtils.isBlank(goods.getName())){
queryWrapper.like("name","%"+goods.getName()+"%");
}
Page<Goods> page = goodsService.page(pages, queryWrapper);
long total = page.getTotal();
long size = page.getSize();
long countpage=total%size==0?total/size:total/size+1;
String name = goods.getName();
List<Type> list = typeService.list();
model.addAttribute("lists",list);
model.addAttribute("name",name);
model.addAttribute("countpage",countpage);
model.addAttribute("page",page);
return "allList";
}
@RequestMapping("/del")
public String del(Integer id){
goodsService.removeById(id);
return "redirect:/goods/list";
}
@RequestMapping("/upd")
public String upd(Integer id,Model model){
Goods byId = goodsService.getById(id);
List<Type> list = typeService.list();
model.addAttribute("type",list);
model.addAttribute("all",byId);
return "upd";
}
@RequestMapping("/upda")
public String upda(Goods goods){
goodsService.saveOrUpdate(goods);
return "redirect:/goods/list";
}
@RequestMapping("/add")
public String add(Model model){
List<Type> list = typeService.list();
model.addAttribute("type",list);
return "add";
}
@RequestMapping("/addG")
public String addG(Goods goods){
goodsService.save(goods);
return "redirect:/goods/list";
}
}
前端页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<body>
<div style="width: 680px;height:100%; margin:0px auto">
<!-- <p>-->
<form th:action="@{/goods/list}" method="post">
食品名称:<input name="name" type="text" th:value="${name}"/>
<input type="submit" value="查询">
</form>
<!-- </p>-->
<a type="button" th:href="@{/goods/add}" style="text-decoration: none">添加</a>
<!-- <span th:text="${session.msg}" style="color: aqua" id="mu"></span>-->
<table border="2px">
<thead>
<tr>
<th>食品名称</th>
<th>价格</th>
<th>库存</th>
<th>食品类型</th>
<th>相关操作</th>
</tr>
</thead>
<tbody>
<tr th:each="list:${page.records}">
<td th:text="${list.name}"></td>
<td th:text="${list.price}"></td>
<td th:text="${list.count}"></td>
<!-- <td th:text="${list.types.typename}"></td>-->
<td th:if="${t.id==list.type}" th:each="t:${lists}" th:text="${t.typename}" th:value="${t.id}"></td>
<td>
<a th:href="@{/goods/del/(id=${list.id})}">删除</a>
<a th:href="@{/goods/upd/(id=${list.id})}">编辑</a>
</td>
</tr>
<div th:if=" ${countpage>0}">
<div style="float: left">
当前第<span th:text="${page.current}"></span>页
共<span th:text="${countpage}"></span>页
总记录数<span th:text="${page.total}"></span>
</div>
<div style="float: right">
<a th:text="首页" th:if="${page.current>1}" th:href="@{/goods/list(pageNum=1,name=${name})}"></a>
<a th:text="上一页" th:if="${page.current>1}" th:href="@{/goods/list(pageNum=${page.current-1},name=${name})}"></a>
<!-- <a th:href="@{'pagelist?pageNum='+${i}}" th:each="i:${#numbers.sequence(1,countpage)}" th:text="${i}"-->
<!-- th:class="${page.current==i}? 'page active':'page'"></a>-->
<a th:text="下一页" th:if="${page.current<countpage}" th:href="@{/goods/list(pageNum=${page.current+1},name=${name})}"></a>
<a th:text="尾页" th:if="${page.current<countpage}" th:href="@{/goods/list(pageNum=${countpage},name=${name})}"></a>
</div>
</div>
</tbody>
</table>
</div>
</body>
<!--<script>-->
<!-- $(function (){-->
<!-- var hides= function (){-->
<!-- // $( "#mu" ).hide();-->
<!-- $("#mu").html("");-->
<!-- }-->
<!-- window.setTimeout(hides,1000);-->
<!-- })-->
<!--</script>-->
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:method="post" th:action="@{/goods/addG}">
<div style="width: 450px;height:100%; margin:0px auto">
<h1 style="color: aquamarine">新增</h1>
<table border="2px">
<tr>
<td>零食名称</td>
<td><input type="text" th:name="name" required></td>
</tr>
<tr>
<td>价格</td>
<td><input type="number" th:name="price" required></td>
</tr>
<tr>
<td>库存</td>
<td><input type="text" th:name="count" required></td>
</tr>
<tr>
<td>零食类型</td>
<td>
<select th:name="type">
<option th:value="${t.id}" th:each="t:${type}" th:text="${t.typename}"></option>
</select>
</td>
</tr>
<tr>
<td>相关操作</td>
<td><input th:type="submit" th:value="新增"/><a th:href="@{/goods/list}" style="text-decoration: none"> 返回</a></td>
</tr>
</table>
</div>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="@{/goods/upda}" th:method="post">
<div style="width: 450px;height:100%; margin:0px auto">
<h1 style="color:red">修改页面</h1>
<table border="2px">
<input type="hidden" th:name="id" th:value="${all.id}">
<tr>
<td>零食名称</td>
<td><input type="text" th:name="name" th:value="${all.name}" required ></td>
</tr>
<tr>
<td>价格</td>
<td><input type="text" th:name="price" th:value="${all.price}" required ></td>
</tr>
<tr>
<td>库存</td>
<td><input type="text" th:name="count" th:value="${all.count}" required ></td>
</tr>
<tr>
<td>食品类型</td>
<td>
<select th:name="type">
<option th:value="${t.id}" th:each="t:${type}" th:text="${t.typename}"></option>
</select>
</td>
</tr>
<td>操作</td>
<td><input th:type="submit" th:value="修改"><a th:href="@{/goods/list}" style="text-decoration: none"> 返回</a></td>
</tr>
</table>
</div>
</form>
</body>
</html>
mybatisplus大大简化了操作,对于简直的增删改查都进行了封装直接调用方法就行了