需求
地区数据往往是存在强上下级关系的一种数据结构,在电商系统中是比较常应用到的,比如北京的下级地区只有海淀区、通州区……,而不会是太原市,而且在开发人员传递地区值的时候往往要传递很多的值,比如省、市、区、镇、省Id,市id、区id、镇id,这样影响了代码的美观性及校验强上下级关系代码的复杂性。基于这样的问题要求我们必须要实现一种可以简洁传递参数并且可以实现地区格式化的一种格式化器。这样衍生出了我们基于Spring Formatter地区自动化格式的一种格式化器,以下是Javashop电商系统中具体的源码分享。
预期效果
常规做法的地区参数传递:
1
|
?province_id= 1 &county_id= 2 &city_id= 3 &town_id= 4
|
在controller接收参数时:
@PostMapping<br>public Result someMethod(Integer provinceId,Integer countyId,Integer cityId,Integer townId){ //街道id不为空找到级联的父 if(townId!=null){ //找到区 countyId=findCounty(townId) //找到市 cityId=findCity(countyId); //找到省 provinceId=findProvince(cityId); } //如果是只保存到区的需求,也要依次寻找级联父 if(countyId!=null){ //找到市 cityId=findCity(countyId); //找到省 provinceId=findCity(cityId); } //如果是保存到市也是同样,不在赘述 }
使用注解后效果:
参数传递:
1
|
xxx?region= 3
|
在controller接收参数时
public result someMethod(@RegionFormat Region region) { //这里的region对象中的省市区街道已经按相应的级别对应好,直接使用即可 if(region.getProvinceProId!=null){ // 保存省id} if(region.getCityId!=null){ // 保存市id} if(region.getCountyId=!=null{//保存区id} if(region.getTwonId=!=null{//保存街道id} }
根据上述需求,如下是基于javashop电商系统中,地区参数接收注解的架构和实现:
类图
1、 RegionFormatter地区格式化器实现RegionFomat注解接口,实现地区转换器方法pase方法,传入地区id和地区语言,最后将转换后的数据输出。如下代码
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) public @interface RegionFormat { }
public class RegionFormatter implements Formatter<Region> { private RegionsClient regionsClient; public RegionFormatter(RegionsClient regionsClient) { this.regionsClient = regionsClient; } public RegionFormatter() { } /** * 地区转换器 * * @param regionId 地区id(只允许第三级或者第四级地区id) * @param locale 国际化US * @return 地区对象 * @throws ParseException */ @Override public Region parse(String regionId, Locale locale) throws ParseException { Regions regions = regionsClient.getModel(Integer.valueOf(regionId)); if (regions == null || regions.getRegionGrade() < 3) { throw new IllegalArgumentException("地区不合法,请联系管理员"); } //根据底层地区id反推出上级id String regionPath = regions.getRegionPath(); regionPath = regionPath.substring(1, regionPath.length()); String[] regionPathArray = regionPath.split(","); //给地区赋值 List rList = new ArrayList(); for (String path : regionPathArray) { Regions region = regionsClient.getModel(Integer.valueOf(path)); if (regions == null) { throw new IllegalArgumentException("地区不合法,请联系管理员"); } rList.add(region); } return this.createRegion(rList); } /** * 组织地区数据 * * @param list 地区集合 * @return 地区 */ private Region createRegion(List<Regions> list) { //将地区数据组织好存入Region对象 Region region = new Region(); region.setProvinceId(list.get(0).getId()); region.setProvince(list.get(0).getLocalName()); region.setCityId(list.get(1).getId()); region.setCity(list.get(1).getLocalName()); region.setCountyId(list.get(2).getId()); region.setCounty(list.get(2).getLocalName()); //如果地区数据为四级,为第四级地区赋值 if (list.size() == 4) { region.setTown(list.get(3).getLocalName()); region.setTownId(list.get(3).getId()); } else { region.setTown(""); region.setTownId(0); } return region; } /** * 将格式化的地区toString输出 * * @param object 地区对象 * @param locale 国际化US * @return */ @Override public String print(Region object, Locale locale) { return object.toString(); } }
2、 RegionFormatAnnotationFormatterFactory地区格式化工厂实现AnnotationFormatterFactory自定义格式工厂接口,将要实现的自动注解RegionFomat传入。如下代码:
public class RegionFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<RegionFormat> { /** * 获取被注解对象的类型 * * @return */ @Override public Set<Class<?>> getFieldTypes() { return new HashSet<Class<?>>(asList(Region.class)); } /** * 获取输出对象 * * @param annotation 注解实例 * @param fieldType 被注解字段的类型 * @return 地区格式化后输出的对象 */ @Override public Printer<?> getPrinter(RegionFormat annotation, Class<?> fieldType) { return new RegionFormatter(); } /** * 获取解析器 * * @param annotation 注解实例 * @param fieldType 被注解字段的类型 * @return 地区格式化后对象 */ @Override public Parser<?> getParser(RegionFormat annotation, Class<?> fieldType) { return new RegionFormatter(); } }
3、 WebConfig实现WebMvcConfigurer,注册自定义的地区格式化器。如下代码:
public class RegionFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<RegionFormat> { /** * 获取被注解对象的类型 * * @return */ @Override public Set<Class<?>> getFieldTypes() { return new HashSet<Class<?>>(asList(Region.class)); } /** * 获取输出对象 * * @param annotation 注解实例 * @param fieldType 被注解字段的类型 * @return 地区格式化后输出的对象 */ @Override public Printer<?> getPrinter(RegionFormat annotation, Class<?> fieldType) { return new RegionFormatter(); } /** * 获取解析器 * * @param annotation 注解实例 * @param fieldType 被注解字段的类型 * @return 地区格式化后对象 */ @Override public Parser<?> getParser(RegionFormat annotation, Class<?> fieldType) { return new RegionFormatter(); } }
使用
1、支持对象属性注解
@RegionFormat @ApiModelProperty(name = "region", value = "地区") private Region region;
2、值Controller入参注解
@ApiOperation(value = "平台添加店铺", response = ShopVO.class) @PostMapping() public ShopVO save(@Valid ShopVO shop, @RegionFormat @RequestParam("license_region") Region licenseRegion, @RegionFormat @RequestParam("bank_region") Region bankRegion, @RegionFormat @RequestParam("shop_region") Region shopRegion) { }
效果
使用上述地区格式化器方法,假设如下请求
1
|
xxx?region= 3
|
则会将id为1的地区及父的信息读取并且形成Region对象。
例如region=3的地区为长安街,父级为东城区->北京,形成的Region对象如下。
{ "cityId": 2, "townId": 0, "countyId": 3, "provinceId": 1, "province": "长安街", "county": "东城区", "city": "北京市", "town": "" }
如果传递的是townId,则会自动填充county、city及province。
如果传递的是countyId,则会自动填充city、province,此时townId为0。
同时支持对象属性级别注解:
对象:
public Person{ //所属区域 @RegionFormat private Region region; //geter and seter }
controller:
@PostMapping() public Result save(Person person) { //这里的地区已经按上述规则赋值 person.getRegion() }
易族智汇(javashop)原创文章
相关推荐
java excel 生成6级级联。加一个poi.jar就行。
在这个项目中,"Java三级级联,省份,市区,地区"意味着开发者正在创建一个系统,允许用户按照省、市、区的顺序逐级选择,每个级别都是基于前一级的选择动态加载的。这种功能常用于地址填写、订单配送等场景,确保...
在Java编程中,级联(Cascading)通常指的是数据的层次结构,比如在数据库查询、用户界面菜单或文件系统中。在这个特定的上下文中,"java2级级联程序"可能是指一个Java应用程序,它实现了两级联动的效果,可能是用于...
在Java编程中,级联查询和分页查询是数据库操作中的常见需求,特别是在处理大量数据时。级联查询用于获取一个实体的相关实体信息,而分页查询则用于提高查询效率和用户体验,避免一次性加载过多数据导致性能下降。...
在IT行业中,级联菜单(Cascading Menu)是一种常见的用户界面元素,它允许用户通过多级选择来筛选或导航到特定的信息。在本案例中,我们关注的是如何使用Java和Ajax技术来实现一个二级联动的菜单。Ajax,即...
在IT行业中,构建用户界面时,级联菜单(Cascading Menu)是一种常见的设计元素,尤其是在网站导航中...在实际项目中,这样的技术可以应用于大型网站的导航系统,电商产品的分类展示,甚至是复杂的管理系统菜单等场景。
如果希望创建级联,只需将另一个 `JMenu` 对象作为参数传递,例如 `myMenu.add(new JMenu("子菜单"))。 4. 设置快捷键:`JMenuItem` 可以通过 `setAccelerator(KeyStroke)` 方法设置快捷键,以提高用户的操作效率。...
全国地区级联数据是用于构建具有五级层次结构的下拉选择框或级联菜单的数据库资源,这种数据通常在Web开发中用于实现用户输入地址时的智能提示功能。五级级联指的是省级、市级、区县级、街道级以及社区级的逐级展开...
js 地区级联 省市两级级联 js 地区级联 省市两级级联 js 地区级联 省市两级级联 js 地区级联 省市两级级联 js 地区级联 省市两级级联 js 地区级联 省市两级级联 js 地区级联 省市两级级联
在Java编程语言中,数据库操作是开发Web应用或企业级应用不可或缺的一部分。"Java中单表和多表级联的增删改查"这个主题...通过实践和学习,你可以更深入地了解如何在Java中有效地操作数据库和创建交互式的用户界面。
智能电网级联故障建模matlab源码+项目说明.zip智能电网级联故障建模matlab源码+项目说明.zip智能电网级联故障建模matlab源码+项目说明.zip智能电网级联故障建模matlab源码+项目说明.zip智能电网级联故障建模matlab...
### Java面试中电商领域的常见问题解析 #### 一、多线程的应用场景及安全性 ...以上总结了Java面试中关于电商领域的一些常见问题及其解答思路,旨在帮助求职者更好地准备面试,理解电商系统的关键技术和业务逻辑。
在Java和JSP(JavaServer Pages)开发中,二级级联菜单是一种常见的用户界面元素,通常用于导航或数据选择,特别是在具有层次结构的数据中。它允许用户首先选择一个父类别,然后显示与所选父类别相关的子类别。这种...
【标题】:“地区动态级联”通常指的是在软件开发中,特别是在前端或后端系统设计时,涉及到的地区、省份、城市等地理信息的动态级联选择功能。这种功能常见于用户注册、地址填写等场景,用户在选择国家后,会自动...
在IT行业中,系统指标级联计算软件是一种至关重要的工具,特别是在通信系统、信号处理和电子工程领域。这个软件专门设计用于高效地计算系统的噪声系数和三阶互调等关键性能指标,为工程师提供了极大的便利。 首先,...
"jQuery实现级联地区选择"这个主题就是关于如何利用jQuery库来创建一个动态联动的省份-城市选择器。这个实例包含了JSP(JavaServer Pages)、JavaScript和CSS三个主要部分,旨在提供一种高效、用户友好的选择体验。 ...
在Windows Forms...通过创建菜单项,设置级联关系,以及添加事件处理程序,开发者可以构建出符合用户需求的交互式菜单系统。"ManyMenu"压缩包中的源代码提供了实际操作的例子,有助于初学者理解和实践这一概念。
现成的省市区三级地区级联json数据,json代码格式工整简明,便于开发者阅读和使用,开箱即用! 现成的省市区三级地区级联json数据,json代码格式工整简明,便于开发者阅读和使用,开箱即用!
基于OpenCV的级联分类器识别中国象棋棋子python源码+象棋分类数据集+项目说明+注释拉满.zip 【项目资源介绍】 使用OpenCV的级联分类器识别中国象棋棋子 OpenCV级联分类器模型训练 文件夹内容: Dataset_Red_Black...
无限级级联菜单在网页开发中是一个常见的需求,特别是在大型网站和复杂的后台管理系统中,用于组织和展示层次分明的导航结构。本项目“无限级级联菜单的多种演示源码v1.0”提供了一种解决方案,包含了多种实现方式,...