当前位置:网站首页>22-07-04 西安 尚好房-项目经验总结(01)
22-07-04 西安 尚好房-项目经验总结(01)
2022-07-05 09:10:00 【£小羽毛】
尚好房是一个二手房管理服务平台,开放优质资源和线上能力,聚合线上线下二手房产资源,打造一个全方位二手房服务生态市场,为消费者提供优质房产服务资源。
根据演示了解项目业务
尚好房后台管理系统:权限管理系统
尚好房前端:找房网
惊讶一:抽取公共的模块
BaseController,里面真的很简单,但是考虑到以后每一个Controller都要用到封装的那俩行代码,
在新增,修改添加成功会用得到。是用来给消费者的Controller继承的。
public class BaseController {
private final static String PAGE_SUCCESS = "common/successPage";
public String successPage(Model model, String successMessage){
model.addAttribute("messagePage",successMessage);
return PAGE_SUCCESS;
}
}
BaseService是用来给中间商“service-api”来继承的,
它里面的内容是下面这样子的,继承了它就相当于Service里写了五个通用的增删改查方法
public interface BaseService<T> {
void insert(T t);
T getById(Long id);
/**
* 逻辑删除
* @param id
*/
void delete(Long id);
/**
* 修改信息
* @param t
*/
void update(T t);
/**
* 分页查询信息
* @param filters
* @return
*/
PageInfo<T> findPage(Map<String, Object> filters);
}
BaseServiceImpl和BaseMapper就是让服务的提供者去使用继承的。一个写具体的业务逻辑,一个写对数据库的操作。
这里BaseServiceImpl是一个抽象类,它里面有一个抽象方法getEntityMapper(),这个方法就是为了让继承它的子类去重写它,把正真的mapper接口送给他,他好帮你去调用方法呐
public abstract class BaseServiceImpl<T> {
/**
* 该抽象方法用来获取真实的mapper接口
* @return
*/
protected abstract BaseMapper<T> getEntityMapper();
public void insert(T t) {
getEntityMapper().insert(t);
}
@Transactional(propagation = Propagation.SUPPORTS)
public T getById(Long id) {
return getEntityMapper().getById(id);
}
public void delete(Long id) {
getEntityMapper().delete(id);
}
public void update(T t) {
getEntityMapper().update(t);
}
@Transactional(propagation = Propagation.SUPPORTS)
public PageInfo<T> findPage(Map<String, Object> filters) {
//将pageSize和pageNum强转成int类型
//第二个参数表示如果强转失败给默认值
int pageNum = CastUtil.castInt(filters.get("pageNum"),1);
int pageSize = CastUtil.castInt(filters.get("pageSize"),10);
//开启分页
PageHelper.startPage(pageNum,pageSize);
//调用持久层的方法查询数据集
//封装返回结果,老师这里没有传第二个参数
return new PageInfo<>(getEntityMapper().findPage(filters),10);
}
}
最后就是这BaseMapper了,我们创建的每一个mapper接口都要去继承这个接口,这样我们的mapper接口就可以省略掉这五个最常用的方法不写了
public interface BaseMapper<T> {
/**
* 保存一个实体
* @param t
*/
void insert(T t);
/**
* 通过一个标识ID 获取一个唯一实体
* @param id
* @return
*/
T getById(Long id);
/**
*修改
* @param t
*/
void update(T t);
/**
* 删除
* @param id
*/
void delete(Long id);
/**
* 分页查询
* @param filters
* @return
*/
Page<T> findPage(Map<String, Object> filters);
}
惊讶2、字典
这个字典表本身就设计的巧妙
这个页面的视觉效果也很nice:这种树形的目录看着很高级,实际上后端返给前端的也只是一个json数组。
java后端代码:
后端逻辑就很简单,根据父节点的id去查询所有的子节点,把查出来的数据用Stream流做整理。
2021/11/12 北京 stream流,内部类,lambda表达式_£小羽毛的博客-CSDN博客
public List<Map<String, Object>> findZnodes(Long id) {
//1. 调用持久层方法,根据父节点id查询List<Dict>
List<Dict> dictList = dictMapper.findListByParentId(id);
//使用Stream流
List<Map<String, Object>> znodes = dictList.stream()
.map(dict -> {
Map<String, Object> znode = new HashMap<>();
//往znode中存放id
znode.put("id", dict.getId());
//往znode中存放name
znode.put("name", dict.getName());
//往znode中存放isParent
znode.put("isParent", dictMapper.countIsParent(dict.getId()) > 0);
return znode;
})
.collect(Collectors.toList());
return znodes;
}
在SQlyog中执行如下sql:
-- 根据父节点的id去查询所有的子节点
SELECT * FROM hse_dict WHERE parent_id =1
点击全部分类
观察network,发送了这样一个请求,那不就是咱上面分析的那种情况嘛
http://139.198.152.148:8001/dict/findZnodes?id=1
返给前端的json数据:实际上返回的还是json数组。
{
"code": 200,
"data": [
{
"isParent": true,
"name": "户型",
"id": 10000
},
{
"isParent": true,
"name": "楼层",
"id": 20000
},
{
"isParent": true,
"name": "建筑结构",
"id": 30000
},
{
"isParent": true,
"name": "装修情况",
"id": 40000
},
{
"isParent": true,
"name": "朝向",
"id": 50000
},
{
"isParent": true,
"name": "房屋用途",
"id": 60000
},
{
"isParent": true,
"name": "省",
"id": 100000
}
],
"message": "成功",
"ok": true
}
我们再点击户型,此时再发送请求去查询
http://139.198.152.148:8001/dict/findZnodes?id=10000
返给前端的json数组如下:
{
"code": 200,
"data": [
{
"isParent": false,
"name": "一室",
"id": 10001
},
{
"isParent": false,
"name": "两室",
"id": 10002
},
{
"isParent": false,
"name": "三室",
"id": 10003
},
{
"isParent": false,
"name": "四室",
"id": 10004
},
{
"isParent": false,
"name": "四室以上",
"id": 10005
}
],
"message": "成功",
"ok": true
}
枚举的俩种用法:
用法1:房源的发布状态HouseStatus
public enum HouseStatus {
//未发布表示用户看不到,但是后台管理系统可以看得到
PUBLISHED(1,"已发布"), UNPUBLISHED(0,"未发布");
public int code;
public String message;
HouseStatus(int code, String message) {
this.code = code;
this.message = message;
}
}
在添加房源信息的时候使用:
@PostMapping("/save")
public String save(House house,Model model){
//未发布
house.setStatus(HouseStatus.UNPUBLISHED.code);
houseService.insert(house);
return successPage(model,"添加房源信息成功");
}
枚举用法2:定义为私有变量。
public enum DictCode {
HOUSETYPE("houseType"),FLOOR("floor"),BUILDSTRUCTURE("buildStructure"),
DECORATION("decoration"),DIRECTION("direction"),HOUSEUSE("houseUse");
private String message;
DictCode(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
使用:
//3. 查询各种初始化列表:户型列表、楼层列表、装修情况列表....
List<Dict> houseTypeList =
dictService.findDictListByParentDictCode(DictCode.HOUSETYPE.getMessage());
getListingDateString() House类
在show.html中
<dt>挂牌时间:</dt><dd th:text="${house.listingDateString}"></dd>
<dt>上次交易:</dt><dd th:text="${house.lastTradeDateString}"></dd>
可实际上House这个类中并没有这俩属性,只有如下俩个Date属性,那么是怎么把数据展示到页面中的呢
- 挂牌日期 private Date listingDate;
- 上次交易日期 private Date lastTradeDate;
一个重要知识点,在thymeleaf语法中,在请求域中是用get方法拿到值的。所以实际上是House这个类多了俩个方法。妙啊,美琪妙妙屋
/**
* 以字符串类型获取挂牌日期
* @return
*/
public String getListingDateString() {
Date date = this.getListingDate();
if(null == date) {
return "";
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String dateString = df.format(date);
return dateString;
}
/**
* 以字符串方式获取上次交易日期
* @return
*/
public String getLastTradeDateString() {
Date date = this.getLastTradeDate();
if(null == date) {
return "";
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String dateString = df.format(date);
return dateString;
}
边栏推荐
- 520 diamond Championship 7-4 7-7 solution
- C#【必备技能篇】ConfigurationManager 类的使用(文件App.config的使用)
- 交通运输部、教育部:广泛开展水上交通安全宣传和防溺水安全提醒
- 一题多解,ASP.NET Core应用启动初始化的N种方案[上篇]
- My life
- Applet (global data sharing)
- Generate confrontation network
- Rebuild my 3D world [open source] [serialization-3] [comparison between colmap and openmvg]
- asp. Net (c)
- Codeworks round 681 (Div. 2) supplement
猜你喜欢
Introduction Guide to stereo vision (5): dual camera calibration [no more collection, I charge ~]
Hi Fun Summer, play SQL planner with starrocks!
RT thread kernel quick start, kernel implementation and application development learning with notes
Understanding rotation matrix R from the perspective of base transformation
Huber Loss
容易混淆的基本概念 成员变量 局部变量 全局变量
[beauty of algebra] singular value decomposition (SVD) and its application to linear least squares solution ax=b
What is a firewall? Explanation of basic knowledge of firewall
Hosting environment API
Node collaboration and publishing
随机推荐
Wechat H5 official account to get openid climbing account
Solution to the problems of the 17th Zhejiang University City College Program Design Competition (synchronized competition)
多元线性回归(梯度下降法)
2311. 小于等于 K 的最长二进制子序列
Editor use of VI and VIM
It cold knowledge (updating ing~)
Programming implementation of ROS learning 5-client node
Composition of applet code
.NET服务治理之限流中间件-FireflySoft.RateLimit
Hi Fun Summer, play SQL planner with starrocks!
scipy.misc.imread()
LLVM之父Chris Lattner:为什么我们要重建AI基础设施软件
利用请求头开发多端应用
C#图像差异对比:图像相减(指针法、高速)
Nodejs modularization
Introduction Guide to stereo vision (7): stereo matching
Huber Loss
Confusing basic concepts member variables local variables global variables
It's too difficult to use. Long articles plus pictures and texts will only be written in short articles in the future
Dynamic dimensions required for input: input, but no shapes were provided. Automatically overriding