当前位置:网站首页>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;
}
边栏推荐
- uni-app 实现全局变量
- Nodemon installation and use
- 【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
- Use arm neon operation to improve memory copy speed
- 【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
- Introduction Guide to stereo vision (3): Zhang calibration method of camera calibration [ultra detailed and worthy of collection]
- [code practice] [stereo matching series] Classic ad census: (5) scan line optimization
- 利用请求头开发多端应用
- Codeforces round 684 (Div. 2) e - green shopping (line segment tree)
- 2311. Longest binary subsequence less than or equal to K
猜你喜欢
TF coordinate transformation of common components of ros-9 ROS
Introduction Guide to stereo vision (7): stereo matching
Rebuild my 3D world [open source] [serialization-2]
Nodejs modularization
Wxml template syntax
Editor use of VI and VIM
Wxss template syntax
AUTOSAR从入门到精通100讲(103)-dbc文件的格式以及创建详解
Multiple solutions to one problem, asp Net core application startup initialization n schemes [Part 1]
Install the CPU version of tensorflow+cuda+cudnn (ultra detailed)
随机推荐
RT thread kernel quick start, kernel implementation and application development learning with notes
Programming implementation of ROS learning 6 -service node
Nodejs modularization
【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
Talking about label smoothing technology
Priority queue (heap)
. Net service governance flow limiting middleware -fireflysoft RateLimit
MPSoC QSPI Flash 升级办法
OpenFeign
【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
Multiple linear regression (sklearn method)
Programming implementation of ROS learning 2 publisher node
阿里云发送短信验证码
Programming implementation of subscriber node of ROS learning 3 subscriber
How many checks does kubedm series-01-preflight have
Oracle advanced (III) detailed explanation of data dictionary
kubeadm系列-01-preflight究竟有多少check
Multiple solutions to one problem, asp Net core application startup initialization n schemes [Part 1]
Codeworks round 681 (Div. 2) supplement
Codeforces round 684 (Div. 2) e - green shopping (line segment tree)