项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus

  • 各种 Object
  • Freemarker
    • 简单使用
    • 常用功能
    • 集成到 SpringBoot
  • MyBatis-Plus
    • 简单使用
    • 分页配置
    • MyBatis Generator - 配置文件、插件
    • 查询条件 Wrapper
    • MySQL 建议 - 数据类型的选择
    • Easy Code
    • 逻辑删除
  • 驾考(旧)知识点
    • 分页的类设计(包含关键字)
    • mybatis-plus 封装好的分页
    • 多表查询

Java 从 0 到架构师目录:【Java从0到架构师】学习记录

Gitee 代码:https://gitee.com/szluyu99/mj_java_frame/tree/master/05_Project/OldJiaKao


企业开发中常见的后台管理系统:

CRM (Customer Relationship Management):客户关系管理

  • 管理客户信息(个人信息、订单信息等)

OA (Office Automation):办公自动化

  • 基于工作流概念,使企业内部人员方便快捷地共享信息,高效协同工作

ERP (Office Automation):企业资源管理

  • 物资资源管理、人力资源管理、财务资源管理、信息资源管理等集成一体化

各种 Object

在阿里巴巴的开发手册,定义了各种 object,比如:PO,BO,DTO、VO,POJO、Query

PO (Persistent Object):持久化对象

  • 属性跟数据库表的字段对应,一个 PO 对象对应数据表的一条记录

BO (Business Object):业务对象

  • 一类业务就会对应一个 BO,除了 get \ set 方法以外,它有很多业务操作,比如针对自身数据进行计算的方法

PO 与 BO 示例1:

  • PO1 是教育经理,PO2 是工作经历,PO3 是项目经理
  • BO 是简历,包含 PO1 ~ PO3

PO 与 BO 示例2:

  • PO1 是交易记录,PO2 是登陆记录,PO3 是商品浏览记录,PO4 是购物车记录,PO5 是搜索记录
  • BO 是个人网站行为,包含 PO1 ~ PO5

DTO (Data Transfer Object):数据传输对象

  • 很多时候并不需要 PO 的所有属性(数据库表的所有字段)传输给客户端
  • 所以,可以根据客户端的业务需要对 PO、BO 的属性进行增删,重新组装成 DTO 对象

VO (View Object):视图对象

  • 传输给客户端的数据展示对象,通常对应一个页面
  • 在有些时候,业务字段的值和最终展示的值是不一样的,比如:DTO 中,sex 的值是:0、1
    页面 A 的 VO 中,sex 的值是:男生、女生
    页面 B 的 VO 中,sex 的值是:帅哥、美女

POJO (Plain Ordinary Java Object):简单的 Java 对象

  • 是 PO、BO、DTO、VO 的统称

Query:数据查询对象

Freemarker

Gitee 代码:驾考 - Freemarker

中文官网:http://freemarker.foofun.cn/

与 JSP、Thymeleaf 一样,Freemarker 也是一款优秀的模版引擎

  • 可以生成任意格式的文本文件(HTML、XML、Java 等),与 Web 环境无关,不依赖 Web 容器

Freemarker 是在公司中非常受欢迎的一款模板引擎

对比 JSP、Thymeleaf:

  • JSP:只能用在 Web 环境中,依赖于 Web 容器
  • Thymeleaf:虽然不依赖 Web 容器,但它只能生成 XML 规范的文本文件

XML 规范:比如 HTML、XML 等由标签对、单标签组成的文件格式

简单使用

引入依赖:

<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version>
</dependency>

准备一个模版文件,它的后缀名是:.ftl (FreeMarker Template Language)

<#-- test.ftl -->
<html><body><h2>${name}</h2><h3>${age}</h3></body>
</html>

在 Java 代码中给模版填充数据:

Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
cfg.setDefaultEncoding("UTF-8");// 模板文件的存放目录
cfg.setDirectoryForTemplateLoading(new File("F:/templates"));// 数据
Map<String, Object> data = new HashMap<>();
data.put("name", "MJ");
data.put("age", 10);try (FileWriter out = new FileWriter(new File("F:/templates/test.html"))) {// 获取模板文件Template tpl = cfg.getTemplate("mapper.ftl");// 合并数据到模版文件中tpl.process(data, out);
}

常用功能

Freemarker 中的注释,使用这种注释不会渲染 到 HTML中

<#-- -->

Freemarker 中抽取公共代码:

<#include "common/style.ftlh">

Freemarker 中默认渲染 Null 会报错,在后面加个 ! 则不可以渲染 Null 不报错

${query.keyword!}

集成到 SpringBoot

<!-- Freemarker -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

与之前学习的 Thymeleaf 一样:

  • 静态资源:可以放在 classpath:/static/ 目录下
  • 模版文件:可以放在 classpath:/templates/ 目录下

需要注意的是,在 SpringBoot 中:

  • freemarker 的模版文件拓展名要用 .ftlh,而不是 .ftl
  • 默认的视图解析器会增加前缀:classpath:/templates/;增加后缀:.ftlh

Freemarker 中获取项目路径的方法,建议写在 .ftlh 文件的第一行:

<#-- 获取context path, 赋值给ctx -->
<#assign ctx="${springMacroRequestContext.getContextPath()}">

MyBatis-Plus

MyBatis-Plus(简称 MP )是 MyBatis 的增强工具

  • 在 MyBatis 的基础上只做增强不做改名,为简化开发、提高效率而生
  • 官网:https://baomidou.com/

简单使用

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>
public interface DictTypeMapper extends BaseMapper<DicType> {}
public interface DicTypeService extends IService<DictType> {}
@Service
@Transactional
public class DictTypeServiceImplextends ServiceImpl<DictTypeMapper, DictTyp>implements DictTypeService {@Autowiredprivate DictTypeMapper mapper;
}

分页配置

Gitee 代码:分页配置

@Configuration
@MapperScan("com.mj.jk.mapper")
public class MyBatisPlusCfg {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);// 当页数超过总页数时,自动跳回到第1页innerInterceptor.setOverflow(true);interceptor.addInnerInterceptor(innerInterceptor);return interceptor;}@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> configuration.setUseDeprecatedExecutor(false);}
}

MyBatis Generator - 配置文件、插件

参考:http://mybatis.org/generator/

MyBatis Generator 是 MyBatis 官方提供的代码生成器

  • 可以根据数据库信息,逆向生成 Model 类,Mapper 类,Mapper 配置文件
  • 大大节省开发者的编码时间,提高开发效率

在 resources 目录下准备一个 generationConfig.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><context id="default" targetRuntime="MyBatis3Simple"><commentGenerator><!-- 去除所有注释 --><property name="suppressAllComments" value="true"/></commentGenerator><!-- 数据库连接 --><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/new_jiakao?serverTimezone=GMT%2B8"userId="root" password="root"/><!-- Model的位置 --><javaModelGenerator targetPackage="com.mj.jk.pojo.po"targetProject="src/test/java"/><!-- XML的位置 --><sqlMapGenerator targetPackage="com.mj.jk.mapper"targetProject="src/test/resources"/><!-- Mapper的位置  --><javaClientGenerator type="XMLMAPPER"targetPackage="com.mj.jk.mapper"targetProject="src/test/java"/><!-- %代表所有表 --><table tableName="%"/><!-- table tableName="dict_type"/> --></context>
</generatorConfiguration>

MyBatis Generator - 插件:

<plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version><configuration><configurationFile>src/test/resources/generatorConfig.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency></dependencies>
</plugin>

查询条件 Wrapper

// 查询条件
LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();wrapper.like(DictType::getName, keyword).or().like(DictType::getValue, keyword).or().like(DictType::getIntro, keyword);

MySQL 建议 - 数据类型的选择

优先使用符合需求的最小数据类型

  • 比如:非负数就是用 UNSIGNED、使用 INT UNSIGNED 存储 IP 地址
    INET_ATON (‘255.255.255.255’) = 4294967295
    INET_NTOA (4294967295) = ‘255.255.255.255’

固定长度的字符串就是用 CHAR

  • 比如手机号、身份证、MD5 密码

谨慎使用 TEXT、 ENUM

  • TEXT 在很多时候会降低数据库的性能
  • 当需要修改 ENUM 类型的待选值时,需要使用 ALTER 语句(需要锁表)

金钱相关的数据,必须使用 DECIMAL 类型


注意, Java 中的整数类型都是有符号的,与 MySQL 类型的正确映射关系如下:

Easy Code

一款国产的代码生成插件,参考文档:https://gitee.com/makejava/EasyCode/wikis/pages

逻辑删除

物理删除:真正从数据库中删除了,永久消失

逻辑删除(软删除):数据库还留在数据库中,只是对用户来说,数据被删掉了

逻辑删除实现方案:在数据表中增加一个字段标识数据是否被删除

id       name     deleted     age
1       jack     0           10
2       rose     1           10

编写 SQL 的时候需要指定 WHERE deleted = 0


实际上在 MyBatisPlus 中实现逻辑删除特别简单

逻辑删除 - 全局配置

mybatis-plus:global-config:# 全局配置# 逻辑删除字段logic-delete-field: deleted# 代表已删除的字段值logic-delete-value: 1# 代表未删除的字段值logic-not-delete-value: 0

注意:就算进行了全局配置,在 Po 类中还是要加 deleted 字段

逻辑删除 - 局部配置

// 局部配置
@TableLogic(value = "0", delval = "1")
@TableField(select = false)
private Short deleted;

注意:自定义 SQL 语句时,MP 并不会自动加上逻辑删除相关的功能,需要自实现逻辑删除

  • 也就利用 xml 写 SQL 的时候,需要自己加上逻辑删除

驾考(旧)知识点

项目:驾考(旧)

分页的类设计(包含关键字)

PageQuery.java

@Data
public class PageQuery<T> {private static final int DEFAULT_SIZE = 10;// 当前页数private long page;// 每一页的记录数private long size;// 总记录数private long count;// 总页数private long pages;private List<T> data;public long getPage() {return Math.max(1, page);}public long getSize() {return (size < 1) ? DEFAULT_SIZE : size;}
}

KeywordQuery.java

@EqualsAndHashCode(callSuper = true)
@Data
public class KeywordQuery<T> extends PageQuery<T> {private String keyword;
}

DictTypeQuery.java

@EqualsAndHashCode(callSuper = true)
@Data
public class DictTypeQuery extends KeywordQuery<DictType> {}

mybatis-plus 封装好的分页

DictTypeMapper.java

public interface DictTypeMapper extends BaseMapper<DictType> {}

DictTypeServiceImpl.java

@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType>implements DictTypeService {@Autowiredprivate DictTypeMapper mapper;@Overridepublic void list(DictTypeQuery query) {// 查询条件LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();String keyword = query.getKeyword();if (!StringUtils.isEmpty(keyword)) {wrapper.like(DictType::getName, keyword).or().like(DictType::getValue, keyword).or().like(DictType::getIntro, keyword);}// 分页对象Page<DictType> page = new Page<>(query.getPage(), query.getSize());// 查询mapper.selectPage(page, wrapper);// 填充queryquery.setData(page.getRecords());query.setCount(page.getTotal());query.setPages(page.getPages());}
}

DictTypeController.java

  • 注意 service.list(query); 是将数据重新传回到 query 对象中
@Controller
@RequestMapping("/dictTypes")
public class DictTypeController {@Autowiredprivate DictTypeService service;@GetMapping("/list")public String list(DictTypeQuery query, Model model) {service.list(query);model.addAttribute("query", query);return "pages/dictType";}
}

多表查询

MyBatis Plus 中对单表查询的支持非常好,如果用它实现多表查询,还是需要依赖于 XML 文件

public interface ExamPlaceCourseMapper extends BaseMapper<ExamPlaceCourse> {MpPage<ExamPlaceCourseVo> selectPageVos(MpPage<ExamPlaceCourseVo> page,@Param(Constants.WRAPPER) Wrapper<ExamPlaceCourseVo> wrapper);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mj.jk.mapper.ExamPlaceCourseMapper"><resultMap id="rmSelectPageVos"type="ExamPlaceCourseVo"><id property="id" column="id"/><result property="name" column="name"/><result property="price" column="price"/><result property="type" column="type"/><result property="placeId" column="place_id"/><result property="provinceId" column="province_id"/><result property="cityId" column="city_id"/><result property="cover" column="cover"/></resultMap><select id="selectPageVos"resultMap="rmSelectPageVos">SELECTc.id,c.name,c.price,c.type,c.intro,c.place_id,c.cover,p.province_id,p.city_idFROM exam_place_course cJOIN exam_place p ON p.id = c.place_id${ew.customSqlSegment}</select>
</mapper>
@Override
@Transactional(readOnly = true)
public PageVo<ExamPlaceCourseVo> list(ExamPlaceCoursePageReqVo query) {MpQueryWrapper<ExamPlaceCourseVo> wrapper = new MpQueryWrapper<>();Integer placeId = query.getPlaceId();Integer provinceId = query.getProvinceId();Integer cityId = query.getCityId();Short type = query.getType();// 类型if (type != null && type >= 0) {wrapper.eq("c.type", type);}// 考场 -> 城市 -> 省份if (placeId != null && placeId > 0) {wrapper.eq("c.place_id", placeId);} else  if (cityId != null && cityId > 0) {wrapper.eq("p.city_id", cityId);} else if (provinceId != null && provinceId > 0) {wrapper.eq("p.province_id", provinceId);}// 关键词wrapper.like(query.getKeyword(), "c.name", "c.intro");return baseMapper.selectPageVos(new MpPage<>(query), wrapper).buildVo();
}

【Java从0到架构师】项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus相关推荐

  1. 【Java从0到架构师】项目实战 - 会话管理、EhCache、JWT、权限管理 Shiro、打包部署

    项目实战 - 权限管理 会话管理 客户端身份认证 - 基于 Cookie.Session 客户端身份验证 - 基于 token EhCache - 简单的缓存框架 JWT - 基于 JSON 的 to ...

  2. 【Java从0到架构师】项目实战 - 前后端分离、后端校验、Swagger、全局异常处理

    项目实战 - 前后端分离.后端校验.Swagger Layui 同源策略 SpringMVC 实现 CORS 后端校验 - hibernate-validator 方法的 Model 参数校验 方法的 ...

  3. 【Java从0到架构师】个人简历项目实战

    项目实战 功能性 登陆流程 验证码 JavaWeb Service.Dao 方法名规范 form 文件上传 - 前端.后台.实时预览 页面可见性 Service 层 面向接口编程 后端技巧 利用 Ja ...

  4. 【Java从0到架构师】Maven - 依赖冲突、分模块构建项目

    SpringBoot - Maven 补充 依赖冲突 解决方案 - dependencyManagement 自定义属性 分模块构建项目 继承 - parent 聚合 - modules 依赖 - d ...

  5. 【Java从0到架构师(1),Java中高级面试题总结(全面)

    JSP 九大内置对象 MySQL 基础 + 多表查询 [Java从0到架构师]MySQL 基础 MySQL MySQL 的使用步骤 数据库的内部存储细节 GUI 工具 SQL 语句 DDL 语句 DD ...

  6. 【Java从0到架构师】SpringCloud - Sleuth、Zipkin、Config

    SpringCloud 链路追踪组件 Sleuth Zipkin 分布式配置中心 - Config Git + Config 分布式配置中心 Java 从 0 到架构师目录:[Java从0到架构师]学 ...

  7. 【Java从0到架构师】SpringCloud - Hystrix、Zuul

    SpringCloud 基本概念 熔断和降级 服务雪崩效应 服务熔断与降级 - Hystrix SpringBoot 集成 Hystrix 熔断降级服务异常报警通知 重点属性 - 熔断隔离策略.超时时 ...

  8. 【Java从0到架构师】SpringCloud - Eureka、Ribbon、Feign

    SpringCloud 分布式.微服务相关概念 微服务框架构选型 SpringCloud 概述 服务注册与发现 - Eureka 案例项目 Eureka 自我保护机制 微服务调用方式 - Ribbon ...

  9. 【Java从0到架构师】RocketMQ 基础 - 应用、核心组件、安装

    RocketMQ 消息中间件 基础知识 消息中间件的应用 异步解耦 削峰填谷 消息分发 RocketMQ 核心组件 RocketMQ 安装 源码安装 修改配置参数 启动 管理控制台安装 测试项目 Ja ...

最新文章

  1. QT发布中遇到的问题 - wufan的专栏 - 博客频道 - CSDN.NET
  2. pycharm导入自定义模块问题
  3. 【前端就业课 第一阶段】HTML5 零基础到实战(十一)canvas 基础
  4. ip_forward
  5. 计算机数据恢复报告单,计算机数据恢复第三章MBR引导分析篇
  6. 十个提升网站访问性能的方法
  7. 2018-2019-2 20165222《网络对抗技术》Exp9 Web安全基础
  8. java J2EE 分层设计思想及各个文件命名规范
  9. UWB定位系统中为何要加入陀螺仪
  10. Mac怎么方便看节假日安排,添加中国法定节假日安排
  11. 基于jsp+mysql+Spring+mybatis的SSM健身房管理系统
  12. 高中必备学习软件_学霸必备app有哪些高中生必备app排行
  13. linux新增加swap空间,Linux增加swap空间的方法
  14. CentOS 7.2 配置Apache服务(httpd)--上篇
  15. DNS域名解析和正向解析
  16. rz command
  17. 我爷爷都看的懂的《栈和队列》,学不会来打我
  18. 电商交易之订单中心设计(一)
  19. 粉丝投稿 | Openvino2020.2.117在LattePanda上的安装和demo演示
  20. H5互动小游戏如何提升用户留存

热门文章

  1. 麒麟810相当于骁龙多少?
  2. 新买的手机一直没有更新系统,是不是新买的手机原装系统最好用啊?
  3. 【leveldb】资料
  4. vscode 使用flask
  5. html退出登录_退出登录 0152
  6. 获取SQL Server数据库增长和收缩事件的详细信息
  7. 数据库创建存储过程_创建存储过程来修复孤立的数据库用户
  8. T-SQL命令性能比较– NOT IN与SQL NOT EXISTS与SQL LEFT JOIN与SQL EXCEPT
  9. EasyNVR智能云终端硬件与EasyNVR解决方案软件综合对比
  10. Linux下OneinStack一键安装JAVA+PHP+Tomcat+Nginx+MySQL网站环境