Commit b63d003e839192d219bc141d7b72469eb2108e8c
1 parent
b9a2d4b9
选择巷道, 首选排除任务多余2个的巷道,选择空闲库位多的库位,
Showing
8 changed files
with
165 additions
and
29 deletions
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/LocationAllocationService.java
... | ... | @@ -4,7 +4,43 @@ import java.util.List; |
4 | 4 | |
5 | 5 | public interface LocationAllocationService { |
6 | 6 | |
7 | + /** | |
8 | + * 获得库位分配的库位 | |
9 | + */ | |
7 | 10 | String allocation(int locationRule, List<String> locationTypeCodeList, int high, String zoneCode, List<Integer> raodWays, String warehouseCode, |
8 | 11 | String containerCode, String materialAreaCode); |
9 | 12 | |
13 | + String doubleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode); | |
14 | + | |
15 | + String singleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode); | |
16 | + | |
17 | + /** | |
18 | + * 获取可用巷道 | |
19 | + * @param roadWays | |
20 | + * @return | |
21 | + */ | |
22 | + Integer getRoadWay(List<Integer> roadWays, String warehouseCode); | |
23 | + | |
24 | + /** | |
25 | + * 获取巷道,选取空闲库位最多作为巷道 | |
26 | + * @param roadWays | |
27 | + * @return | |
28 | + */ | |
29 | + Integer getRoadWayByMaxFreeLocation(List<Integer> roadWays, String warehouseCode); | |
30 | + | |
31 | + /** | |
32 | + * 排除巷道,如果这个巷道分配了超过2个库位,那么就不往这边分库位了,避免堵死的情况 | |
33 | + * @param roadWays | |
34 | + * @param warehouseCode | |
35 | + * @return | |
36 | + */ | |
37 | + List<Integer> removeRoadWaysByPreLocations(List<Integer> roadWays, String warehouseCode); | |
38 | + | |
39 | +// /** | |
40 | +// * 获取巷道,根据入库物料均分原则,选取物料最少的巷道 | |
41 | +// * @param roadWays | |
42 | +// * @return | |
43 | +// */ | |
44 | +// Integer getRoadWayByMinMaterial(List<Integer> roadWays, String warehouseCode); | |
45 | + | |
10 | 46 | } |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/LocationAllocationServiceImpl.java
1 | 1 | package org.jeecg.modules.wms.api.wcs.service; |
2 | 2 | |
3 | +import static java.util.stream.Collectors.toList; | |
4 | + | |
5 | +import java.util.ArrayList; | |
6 | +import java.util.Collections; | |
7 | +import java.util.List; | |
8 | + | |
9 | +import javax.annotation.Resource; | |
10 | + | |
3 | 11 | import org.jeecg.common.exception.JeecgBootException; |
4 | -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
5 | -import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
6 | 12 | import org.jeecg.modules.wms.config.container.entity.Container; |
7 | 13 | import org.jeecg.modules.wms.config.container.service.IContainerService; |
8 | 14 | import org.jeecg.modules.wms.config.containerType.entity.ContainerType; |
... | ... | @@ -11,10 +17,9 @@ import org.jeecg.modules.wms.config.location.entity.Location; |
11 | 17 | import org.jeecg.modules.wms.config.location.service.ILocationService; |
12 | 18 | import org.jeecg.modules.wms.config.locationType.entity.LocationType; |
13 | 19 | import org.jeecg.modules.wms.config.locationType.service.ILocationTypeService; |
14 | -import org.jeecg.modules.wms.config.parameterConfiguration.entity.ParameterConfiguration; | |
15 | 20 | import org.jeecg.modules.wms.config.parameterConfiguration.service.IParameterConfigurationService; |
16 | -import org.jeecg.modules.wms.config.zone.entity.Zone; | |
17 | 21 | import org.jeecg.modules.wms.config.zone.service.IZoneService; |
22 | +import org.jeecg.modules.wms.task.taskHeader.entity.TaskHeader; | |
18 | 23 | import org.jeecg.modules.wms.task.taskHeader.service.ITaskHeaderService; |
19 | 24 | import org.jeecg.utils.StringUtils; |
20 | 25 | import org.jeecg.utils.constant.QuantityConstant; |
... | ... | @@ -22,12 +27,8 @@ import org.springframework.stereotype.Service; |
22 | 27 | import org.springframework.transaction.annotation.Transactional; |
23 | 28 | import org.springframework.util.StopWatch; |
24 | 29 | |
25 | -import javax.annotation.Resource; | |
26 | -import java.util.ArrayList; | |
27 | -import java.util.Collections; | |
28 | -import java.util.List; | |
29 | - | |
30 | -import static java.util.stream.Collectors.toList; | |
30 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
31 | +import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
31 | 32 | |
32 | 33 | /** |
33 | 34 | * @author 游杰 |
... | ... | @@ -49,6 +50,8 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
49 | 50 | private IZoneService zoneService; |
50 | 51 | @Resource |
51 | 52 | private IParameterConfigurationService parameterConfigurationService; |
53 | + @Resource | |
54 | + private LocationAllocationService locationAllocationService; | |
52 | 55 | |
53 | 56 | @Override |
54 | 57 | @Transactional(rollbackFor = Exception.class) |
... | ... | @@ -76,9 +79,9 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
76 | 79 | List<String> mergelocationTypeCodeList = locationTypeCodeList.stream().filter(item -> locationTypeCodes.contains(item)).collect(toList()); |
77 | 80 | switch (locationRule) { |
78 | 81 | case QuantityConstant.DOUBLE_FORK: |
79 | - return doubleRk(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode); | |
82 | + return locationAllocationService.doubleRk(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode); | |
80 | 83 | case QuantityConstant.SINGLE_FORK: |
81 | - return singleRk(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode); | |
84 | + return locationAllocationService.singleRk(zoneCode, raodWays, high, warehouseCode, mergelocationTypeCodeList, materialAreaCode); | |
82 | 85 | } |
83 | 86 | return null; |
84 | 87 | } |
... | ... | @@ -86,7 +89,9 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
86 | 89 | /** |
87 | 90 | * 双伸位库位入库分配库位 |
88 | 91 | */ |
89 | - private String doubleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode) { | |
92 | + @Override | |
93 | + @Transactional(rollbackFor = Exception.class) | |
94 | + public String doubleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode) { | |
90 | 95 | if (roadWays == null || roadWays.size() < 1) { |
91 | 96 | List<Location> locationList = locationService.getLocationListByZoneCode(zoneCode, warehouseCode); |
92 | 97 | roadWays = locationList.stream().map(Location::getRoadWay).distinct().collect(toList()); |
... | ... | @@ -121,15 +126,14 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
121 | 126 | System.out.println("waste aa:" + stopWatch.getLastTaskTimeMillis()); |
122 | 127 | stopWatch.start("bbb"); |
123 | 128 | roadWays.removeAll(removeRoadWays); |
124 | - Collections.shuffle(roadWays); | |
125 | 129 | if (roadWays == null || roadWays.size() == 0) { |
126 | 130 | throw new JeecgBootException("分配库位时, 巷道为空"); |
127 | 131 | } |
128 | - Integer roadWay = roadWays.get(0); | |
132 | + Integer roadWay = locationAllocationService.getRoadWay(roadWays, warehouseCode); | |
129 | 133 | // 优先找外侧库位 |
130 | 134 | LambdaQueryWrapper<Location> locationLambda = Wrappers.lambdaQuery(); |
131 | 135 | locationLambda.eq(Location::getZoneCode, zoneCode).eq(Location::getWarehouseCode, warehouseCode).eq(Location::getRoadWay, roadWay) |
132 | - .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).eq(Location::getHigh, high) | |
136 | + .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).ge(Location::getHigh, high) | |
133 | 137 | .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode).eq(Location::getRowFlag, QuantityConstant.ROW_OUT) |
134 | 138 | .in(Location::getLocationTypeCode, locationTypeCodeList).eq(Location::getContainerCode, QuantityConstant.EMPTY_STRING).last(lastString); |
135 | 139 | List<Location> locationList = locationService.list(locationLambda); |
... | ... | @@ -148,7 +152,7 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
148 | 152 | if (locationList.size() == 0) { |
149 | 153 | locationLambda = Wrappers.lambdaQuery(); |
150 | 154 | locationLambda.eq(Location::getZoneCode, zoneCode).eq(Location::getWarehouseCode, warehouseCode).eq(Location::getRoadWay, roadWay) |
151 | - .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).eq(Location::getHigh, high) | |
155 | + .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).ge(Location::getHigh, high) | |
152 | 156 | .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode).eq(Location::getRowFlag, QuantityConstant.ROW_IN) |
153 | 157 | .in(Location::getLocationTypeCode, locationTypeCodeList).eq(Location::getContainerCode, QuantityConstant.EMPTY_STRING).last(lastString); |
154 | 158 | locationList = locationService.list(locationLambda); |
... | ... | @@ -173,16 +177,17 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
173 | 177 | /** |
174 | 178 | * 单伸位库位入库分配库位 |
175 | 179 | */ |
176 | - private String singleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode) { | |
180 | + @Override | |
181 | + @Transactional(rollbackFor = Exception.class) | |
182 | + public String singleRk(String zoneCode, List<Integer> roadWays, int high, String warehouseCode, List<String> locationTypeCodeList, String materialAreaCode) { | |
177 | 183 | if (roadWays == null || roadWays.size() < 1) { |
178 | 184 | List<Location> locationList = locationService.getLocationListByZoneCode(zoneCode, warehouseCode); |
179 | 185 | roadWays = locationList.stream().map(Location::getRoadWay).distinct().collect(toList()); |
180 | 186 | } |
181 | - Collections.shuffle(roadWays); | |
182 | - Integer roadWay = roadWays.get(0); | |
187 | + Integer roadWay = locationAllocationService.getRoadWay(roadWays, warehouseCode); | |
183 | 188 | LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); |
184 | 189 | locationLambdaQueryWrapper.eq(Location::getZoneCode, zoneCode).eq(Location::getWarehouseCode, warehouseCode).eq(Location::getRoadWay, roadWay) |
185 | - .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).eq(Location::getHigh, high) | |
190 | + .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).ge(Location::getHigh, high) | |
186 | 191 | .eq(StringUtils.isNotEmpty(materialAreaCode), Location::getMaterialAreaCode, materialAreaCode).in(Location::getLocationTypeCode, locationTypeCodeList) |
187 | 192 | .eq(Location::getContainerCode, QuantityConstant.EMPTY_STRING).last("ORDER BY layer asc, id asc limit 1"); |
188 | 193 | // 单伸位逻辑简单,只需要找到一个空闲库位 |
... | ... | @@ -194,4 +199,67 @@ public class LocationAllocationServiceImpl implements LocationAllocationService |
194 | 199 | return locationCode; |
195 | 200 | } |
196 | 201 | |
202 | + @Override | |
203 | + @Transactional(rollbackFor = Exception.class) | |
204 | + public Integer getRoadWay(List<Integer> roadWays, String warehouseCode) { | |
205 | + if (roadWays.size() == 1) { | |
206 | + return roadWays.get(0); | |
207 | + } | |
208 | + roadWays = locationAllocationService.removeRoadWaysByPreLocations(roadWays, warehouseCode); | |
209 | + int roadWay = getRoadWayByMaxFreeLocation(roadWays, warehouseCode); | |
210 | + return roadWay; | |
211 | + } | |
212 | + | |
213 | + @Override | |
214 | + @Transactional(rollbackFor = Exception.class) | |
215 | + public Integer getRoadWayByMaxFreeLocation(List<Integer> roadWays, String warehouseCode) { | |
216 | + List<Integer> locationSizeList = new ArrayList<Integer>(); | |
217 | + int max = 0; | |
218 | + // 最多空闲库位的巷道索引 | |
219 | + int index = 0; | |
220 | + // 获取每个巷道的可用空闲库位数 | |
221 | + for (Integer roadWay : roadWays) { | |
222 | + int size = locationService.getEmptyLocationSizeByRoadWay(roadWay, warehouseCode); | |
223 | + locationSizeList.add(size); | |
224 | + } | |
225 | + // 通过比较每个巷道的库位数,最终找到最大库位数的索引,这个索引是roadWays的第几个。 | |
226 | + for (int i = 0; i < locationSizeList.size(); i++) { | |
227 | + int locationSize = locationSizeList.get(i);; | |
228 | + if (max == 0) { | |
229 | + max = locationSize; | |
230 | + index = i; | |
231 | + } else { | |
232 | + if (max < locationSize) { | |
233 | + max = locationSize; | |
234 | + index = i; | |
235 | + } | |
236 | + } | |
237 | + } | |
238 | + // 获得空闲库位数 | |
239 | + int maxRoadWay = roadWays.get(index); | |
240 | + return maxRoadWay; | |
241 | + } | |
242 | + | |
243 | + @Override | |
244 | + @Transactional(rollbackFor = Exception.class) | |
245 | + public List<Integer> removeRoadWaysByPreLocations(List<Integer> roadWays, String warehouseCode) { | |
246 | + // 同巷道分配的库位大于等于2时,这个巷道就不能再分了 | |
247 | + LambdaQueryWrapper<TaskHeader> taskHeaderLambdaQueryWrapper = Wrappers.lambdaQuery(); | |
248 | + taskHeaderLambdaQueryWrapper.lt(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED).ne(TaskHeader::getToLocationCode, | |
249 | + QuantityConstant.EMPTY_STRING); | |
250 | + List<TaskHeader> taskHeaderList = taskHeaderService.list(taskHeaderLambdaQueryWrapper); | |
251 | + if (taskHeaderList.size() != 0) { | |
252 | + List<Integer> roadWayList = taskHeaderList.stream().map(TaskHeader::getRoadWay).collect(toList()); | |
253 | + List<Integer> removeRoadWayList = new ArrayList<>(); | |
254 | + for (Integer roadWay : roadWays) { | |
255 | + int i = Collections.frequency(roadWayList, roadWay); | |
256 | + if (i >= 2) { | |
257 | + removeRoadWayList.add(roadWay); | |
258 | + } | |
259 | + } | |
260 | + roadWays.removeAll(removeRoadWayList); | |
261 | + } | |
262 | + return roadWays; | |
263 | + } | |
264 | + | |
197 | 265 | } |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/service/WcsServiceImpl.java
... | ... | @@ -241,6 +241,7 @@ public class WcsServiceImpl implements WcsService { |
241 | 241 | taskHeader = new TaskHeader(); |
242 | 242 | taskHeader.setId(Integer.parseInt(taskNo)); |
243 | 243 | taskHeader.setZoneCode(location.getZoneCode()); |
244 | + taskHeader.setRoadWay(location.getRoadWay()); | |
244 | 245 | taskHeader.setPreTaskNo(preTaskNo); |
245 | 246 | taskHeader.setWeight(Integer.parseInt(warecellDomain.getWeight())); |
246 | 247 | taskHeader.setToLocationCode(locationCode); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/container/service/impl/ContainerServiceImpl.java
... | ... | @@ -62,6 +62,9 @@ public class ContainerServiceImpl extends ServiceImpl<ContainerMapper, Container |
62 | 62 | |
63 | 63 | @Override |
64 | 64 | public Container getContainerByCode(String containCode, String warehouseCode) { |
65 | + if (StringUtils.havaLowerCase(containCode)) { | |
66 | + throw new JeecgBootException("容器不能有小字母" + containCode); | |
67 | + } | |
65 | 68 | LambdaQueryWrapper<Container> containerLambdaQueryWrapper = Wrappers.lambdaQuery(); |
66 | 69 | containerLambdaQueryWrapper.eq(Container::getCode, containCode).eq(Container::getWarehouseCode, warehouseCode); |
67 | 70 | Container container = this.getOne(containerLambdaQueryWrapper); |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/location/service/ILocationService.java
... | ... | @@ -3,12 +3,7 @@ package org.jeecg.modules.wms.config.location.service; |
3 | 3 | import java.util.List; |
4 | 4 | |
5 | 5 | import org.jeecg.common.api.vo.Result; |
6 | -import org.jeecg.modules.wms.config.location.dto.CompareContainerTaskDto; | |
7 | -import org.jeecg.modules.wms.config.location.dto.CompareLocationDto; | |
8 | -import org.jeecg.modules.wms.config.location.dto.CompareLocationTaskDto; | |
9 | -import org.jeecg.modules.wms.config.location.dto.QueryCompareContainerTaskDto; | |
10 | -import org.jeecg.modules.wms.config.location.dto.QueryCompareLocationDto; | |
11 | -import org.jeecg.modules.wms.config.location.dto.QueryCompareLocationTaskDto; | |
6 | +import org.jeecg.modules.wms.config.location.dto.*; | |
12 | 7 | import org.jeecg.modules.wms.config.location.entity.BatchLocation; |
13 | 8 | import org.jeecg.modules.wms.config.location.entity.Location; |
14 | 9 | import org.jeecg.modules.wms.config.location.entity.LocationInfo; |
... | ... | @@ -44,6 +39,8 @@ public interface ILocationService extends IService<Location> { |
44 | 39 | |
45 | 40 | Location getEmptyLocation(Location location); |
46 | 41 | |
42 | + int getEmptyLocationSizeByRoadWay(Integer roadWay, String warehouseCode); | |
43 | + | |
47 | 44 | Location getEmptyInsideLocation(Location location); |
48 | 45 | |
49 | 46 | Location getEmptyOutSideLocation(Location location); |
... | ... | @@ -66,8 +63,7 @@ public interface ILocationService extends IService<Location> { |
66 | 63 | PageUtil<CompareLocationDto> compareWcsLocation(QueryCompareLocationDto queryCompareLocationDto); |
67 | 64 | |
68 | 65 | PageUtil<CompareLocationTaskDto> compareWcsLocationTask(QueryCompareLocationTaskDto queryCompareLocationTaskDto); |
69 | - | |
70 | - PageUtil<CompareContainerTaskDto> compareWcsContainerTask(QueryCompareContainerTaskDto queryCompareLocationTaskDto); | |
71 | 66 | |
67 | + PageUtil<CompareContainerTaskDto> compareWcsContainerTask(QueryCompareContainerTaskDto queryCompareLocationTaskDto); | |
72 | 68 | |
73 | 69 | } |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/location/service/impl/LocationServiceImpl.java
... | ... | @@ -79,6 +79,9 @@ public class LocationServiceImpl extends ServiceImpl<LocationMapper, Location> i |
79 | 79 | |
80 | 80 | @Override |
81 | 81 | public Location getLocationByCode(String locationCode, String warehouseCode) { |
82 | + if (StringUtils.havaLowerCase(locationCode)) { | |
83 | + throw new JeecgBootException("库位不能有小字母" + locationCode); | |
84 | + } | |
82 | 85 | LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); |
83 | 86 | locationLambdaQueryWrapper.eq(Location::getCode, locationCode).eq(Location::getEnable, QuantityConstant.STATUS_ENABLE).eq(Location::getWarehouseCode, |
84 | 87 | warehouseCode); |
... | ... | @@ -187,6 +190,15 @@ public class LocationServiceImpl extends ServiceImpl<LocationMapper, Location> i |
187 | 190 | } |
188 | 191 | |
189 | 192 | @Override |
193 | + public int getEmptyLocationSizeByRoadWay(Integer roadWay, String warehouseCode) { | |
194 | + LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); | |
195 | + locationLambdaQueryWrapper.eq(Location::getRoadWay, roadWay).eq(Location::getWarehouseCode, warehouseCode) | |
196 | + .eq(Location::getStatus, QuantityConstant.STATUS_LOCATION_EMPTY).eq(Location::getContainerCode, QuantityConstant.EMPTY_STRING); | |
197 | + int count = count(locationLambdaQueryWrapper); | |
198 | + return count; | |
199 | + } | |
200 | + | |
201 | + @Override | |
190 | 202 | public Location getEmptyInsideLocation(Location location) { |
191 | 203 | LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery(); |
192 | 204 | locationLambdaQueryWrapper.eq(Location::getWarehouseCode, location.getWarehouseCode()).eq(Location::getRoadWay, location.getRoadWay()) |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/entity/TaskHeader.java
... | ... | @@ -142,6 +142,8 @@ public class TaskHeader implements Serializable { |
142 | 142 | private String exceptionName; |
143 | 143 | @ApiModelProperty(value = "异常状态") |
144 | 144 | private Integer exceptionState; |
145 | + @ApiModelProperty(value = "巷道") | |
146 | + private Integer roadWay; | |
145 | 147 | /** 备用字段1 */ |
146 | 148 | @Excel(name = "备用字段1", width = 15) |
147 | 149 | @ApiModelProperty(value = "备用字段1") |
... | ... |
huaheng-wms-core/src/main/java/org/jeecg/utils/StringUtils.java
... | ... | @@ -327,6 +327,24 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { |
327 | 327 | } |
328 | 328 | |
329 | 329 | /** |
330 | + * 字符串有小写 | |
331 | + */ | |
332 | + public static boolean havaLowerCase(String str) { | |
333 | + int strLen; | |
334 | + boolean have = false; | |
335 | + if (str == null || (strLen = str.length()) == 0) { | |
336 | + return true; | |
337 | + } | |
338 | + for (int i = 0; i < strLen; i++) { | |
339 | + char charAt = str.charAt(i); | |
340 | + if (Character.isLowerCase(charAt)) { | |
341 | + return true; | |
342 | + } | |
343 | + } | |
344 | + return false; | |
345 | + } | |
346 | + | |
347 | + /** | |
330 | 348 | * 驼峰式命名法 例如:user_name->userName |
331 | 349 | */ |
332 | 350 | public static String toCamelCase(String s) { |
... | ... |