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 对象
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
<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 的增强工具
简单使用
<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 DictTypeServiceImpl
extends ServiceImpl<DictTypeMapper, DictTyp>
implements DictTypeService {
@Autowired
private DictTypeMapper mapper;
}
分页配置
Gitee 代码:分页配置
@Configuration
@MapperScan("com.mj.jk.mapper")
public class MyBatisPlusCfg {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
innerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(innerInterceptor);
return interceptor;
}
@Bean
public 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 generatorConfiguration
PUBLIC "-//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"/>
<javaModelGenerator targetPackage="com.mj.jk.pojo.po"
targetProject="src/test/java"/>
<sqlMapGenerator targetPackage="com.mj.jk.mapper"
targetProject="src/test/resources"/>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.mj.jk.mapper"
targetProject="src/test/java"/>
<table tableName="%"/>
</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);
驾考(旧)知识点
项目:驾考(旧)
分页的类设计(包含关键字)
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 {
@Autowired
private DictTypeMapper mapper;
@Override
public 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);
query.setData(page.getRecords());
query.setCount(page.getTotal());
query.setPages(page.getPages());
}
}
DictTypeController.java
- 注意
service.list(query); 是将数据重新传回到 query 对象中
@Controller
@RequestMapping("/dictTypes")
public class DictTypeController {
@Autowired
private DictTypeService service;
@GetMapping("/list")
public String list(DictTypeQuery query, Model model) {
service.list(query);
model.addAttribute("query", query);
return "pages/dictType";
}
}
|