电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

瀏覽:21日期:2023-03-22 11:51:24

如果只想查看注解,請(qǐng)?zhí)轿恼履┪膊糠?/b>

簡(jiǎn)介

在前后端進(jìn)行數(shù)據(jù)交互中,在前端把數(shù)據(jù)傳送到后端前,一般會(huì)先進(jìn)行校驗(yàn)一次,校驗(yàn)成功之后,才把數(shù)據(jù)發(fā)送到后端。但是我們?cè)诜?wù)端還得在對(duì)數(shù)據(jù)進(jìn)行一次校驗(yàn)。因?yàn)檎?qǐng)求數(shù)據(jù)發(fā)送的鏈接很容易獲取,可以不經(jīng)過(guò)前端界面,使用postman等工具直接向后臺(tái)發(fā)送數(shù)據(jù),這就可能造成發(fā)送的數(shù)據(jù)是不合法的情況。

項(xiàng)目創(chuàng)建

首先創(chuàng)建一個(gè)springboot項(xiàng)目

使用的springboot版本為:(本文代碼以該版本為準(zhǔn),不同版本springboot,在下面內(nèi)容會(huì)出現(xiàn)一些差異

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>

引入如下依賴(lài)

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies>

這個(gè)作標(biāo)在新一點(diǎn)的springboot版本中,需要單獨(dú)引入。在老版本是默認(rèn)引入的。這個(gè)是用來(lái)引入對(duì)jsr303注解的支持。

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

接著創(chuàng)建一個(gè)Java Bean

package cn.jxj4869.demo.entity;import lombok.Data;import javax.validation.constraints.NotNull;@Datapublic class User { @NotNull private Integer id; private String username; private String password; private String email;}

返回類(lèi)型的JavaBean

package cn.jxj4869.demo.entity;import java.util.HashMap;public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put('code', 0);put('msg', 'success');}public static R error(int code, String msg) {R r = new R();r.put('code', code);r.put('msg', msg);return r;}public static R ok(String msg) {R r = new R();r.put('msg', msg);return r;}public R put(String key, Object value) {super.put(key, value);return this;}}

創(chuàng)建一個(gè)controller。

index方法用來(lái)跳轉(zhuǎn)到首頁(yè)。

package cn.jxj4869.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;@Controllerpublic class UserController { @RequestMapping('/') public String index(){ return 'index'; }}

首頁(yè)代碼放到resources/templates目錄下

<!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <title>Title</title> <style> div{ margin-top: 50px; } </style></head><body><div> 新增表單 <br><br> <form method='post'> <label>用戶(hù)名</label> <input type='text' name='username'/> <br> <label>密碼</label> <input type='text' name='password'/> <br> <label>郵箱</label> <input type='email' name='email'/> <br> <input type='submit' value='提交'/> </form></div><div> 更新表單 <br><br> <form method='post'> <input type='hidden' name='id' value='1'> <label>用戶(hù)名</label> <input type='text' name='username'/> <br> <label>密碼</label> <input type='text' name='password'/> <br> <label>郵箱</label> <input type='email' name='email'/> <br> <input type='submit' value='提交'/> </form></div></body></html>傳統(tǒng)的檢驗(yàn)方式

要在后端進(jìn)行數(shù)據(jù)校驗(yàn),傳統(tǒng)的校驗(yàn)方式在controller層接受數(shù)據(jù)后,按照要求對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)

比如要接收一個(gè)user bean對(duì)象。

現(xiàn)在要對(duì)user對(duì)象中的username屬性進(jìn)行非空校驗(yàn),password屬性進(jìn)行非空校驗(yàn)和長(zhǎng)度校驗(yàn)。

@PostMapping('/user') @ResponseBody public R user1(User user) throws Exception { if(StringUtils.isEmpty(user.getUsername())) { return R.error(400,'username不能為空'); } if(StringUtils.isEmpty(user.getPassword())||user.getPassword().length()>8||user.getPassword().length() <4) { return R.error(400,'password無(wú)效'); } return null; }

如果有多個(gè)方法都需要接受user對(duì)象, 而且要校驗(yàn)的屬性可能不止username和password這兩個(gè)屬性,如果每個(gè)方法里面都采用上面這種校驗(yàn)方式的話(huà),代碼就會(huì)很臃腫,而且不好維護(hù),當(dāng)改變了userbean的屬性,或者對(duì)校驗(yàn)規(guī)則進(jìn)行修改后,就得對(duì)所有的校驗(yàn)代碼進(jìn)行更新。 這是一件工程量很大的事。

使用JSR303

為了解決上述問(wèn)題,我們可以使用JSR303提供的注解進(jìn)行校驗(yàn)。

JSR是Java Specification Requests的縮寫(xiě),意思是Java 規(guī)范提案。JSR303也就是第303號(hào)提案。

使用JSR303的方法很簡(jiǎn)單,例如上面的需求,我們只需要在user的屬性上加上注解即可。

步驟如下:

1、給Bean添加校驗(yàn)注解,一般是在 javax.validation.constraints這個(gè)包下,也還有一些是hibernate提供的。

2、開(kāi)啟校驗(yàn)功能@Valid。

3、當(dāng)校驗(yàn)失敗的時(shí)候,會(huì)拋出org.springframework.validation.BindException異常。

常用的校驗(yàn)注解在文末

package cn.jxj4869.demo.entity;import lombok.Data;import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotNull;@Datapublic class User { private Integer id; @NotBlank private String username; @NotBlank @Length(min = 4,max = 8) private String password; private String email;}

然后在controller里面的方法上,加上@Valid注解即可

@PostMapping('/user2') @ResponseBody public R user2(@Valid User user) throws Exception { System.out.println(user); return null; }

當(dāng)校驗(yàn)失敗后,會(huì)出現(xiàn)如下錯(cuò)誤。并且會(huì)給出默認(rèn)的提示信息。

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

自定義錯(cuò)誤信息

那這個(gè)錯(cuò)誤信息是怎么來(lái)的呢。

進(jìn)入@NotNULL注解的代碼里面

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)@Documented@Constraint(validatedBy = { })public @interface NotBlank {String message() default '{javax.validation.constraints.NotNull.message}';............ ............ ............}

會(huì)有一個(gè)message屬性。顯然就是指定錯(cuò)誤的提示內(nèi)容。而這些錯(cuò)誤提示是在一個(gè)叫validationMessages.properties的文件中,用idea的搜索工具可以找到,雙擊shift鍵打開(kāi)搜索。

發(fā)現(xiàn)有這么多validationMessages.properties的文件,而且支持國(guó)際化。

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

打開(kāi)validationMessages_zh.properties,可以看到里面定義了這么多的提示。而錯(cuò)誤提示就是從這文件中獲取的。

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

如果我們不想用默認(rèn)的校驗(yàn)提示信息的話(huà),可以自己指定。

指定message的值即可。

@NotBlank(message = '用戶(hù)名不能為空') private String username;

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

錯(cuò)誤信息的獲取與響應(yīng)

當(dāng)校驗(yàn)出錯(cuò)時(shí),會(huì)默認(rèn)返回一個(gè)錯(cuò)誤界面,或者返回錯(cuò)誤提示的json數(shù)據(jù)。但默認(rèn)提供的顯然不是我們想要的,如果可以拿到錯(cuò)誤信息,那我們就能自定義相應(yīng)數(shù)據(jù)了。

拿到錯(cuò)誤信息的方式也很簡(jiǎn)單,只要在方法中加上BindingResult result這個(gè)參數(shù),錯(cuò)誤信息就會(huì)封裝這里面。

@PostMapping('/user2') @ResponseBody public R user2(@Valid User user, BindingResult result) throws Exception { System.out.println(user); if(result.hasErrors()) { //判斷是否有錯(cuò)誤 Map<String,String> map = new HashMap<>(); //1、獲取校驗(yàn)的錯(cuò)誤結(jié)果 result.getFieldErrors().forEach((item)->{ //FieldError 獲取到錯(cuò)誤提示 String message = item.getDefaultMessage(); //獲取錯(cuò)誤的屬性的名字 String field = item.getField(); map.put(field,message); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); } // 若沒(méi)有錯(cuò)誤,則進(jìn)行接下去的業(yè)務(wù)操作。 return null; }

不過(guò)不推薦上面這種方式,理由同上,當(dāng)校驗(yàn)的地方多了,每個(gè)方法里面都加上這么個(gè)異常處理,會(huì)讓代碼很臃腫。

不知道你們是否還記得,springmvc里面有個(gè)全局的異常處理,我們可以自定義一個(gè)異常處理,在這里面統(tǒng)一處理異常。

統(tǒng)一處理BinException。這樣就可以不用在controller中去處理錯(cuò)誤信息了。

package cn.jxj4869.demo.execption;import cn.jxj4869.demo.entity.R;import org.springframework.validation.BindException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;import java.util.Map;@RestControllerAdvice(basePackages = 'cn.jxj4869.demo.controller')public class MyExceptionControllerAdvice { @ExceptionHandler(value = BindException.class) public R handleVaildException(BindException e) { Map<String,String> map = new HashMap<>(); //1、獲取校驗(yàn)的錯(cuò)誤結(jié)果 e.getFieldErrors().forEach((item)->{ //FieldError 獲取到錯(cuò)誤提示 String message = item.getDefaultMessage(); //獲取錯(cuò)誤的屬性的名字 String field = item.getField(); map.put(field,message); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); }}錯(cuò)誤異常類(lèi)型補(bǔ)充

校驗(yàn)出錯(cuò)的時(shí)候,會(huì)拋出兩種異常

org.springframework.validation.BindException

使用@Valid注解進(jìn)行校驗(yàn)的時(shí)候拋出的

org.springframework.web.bind.MethodArgumentNotValidException

使用@validated校驗(yàn)的時(shí)候拋出的

在異常捕獲中加入下面這個(gè)

@ExceptionHandler(value= MethodArgumentNotValidException.class) public R handleVaildException(MethodArgumentNotValidException e){ BindingResult bindingResult = e.getBindingResult(); Map<String,String> map = new HashMap<>(); bindingResult.getFieldErrors().forEach((fieldError)->{ map.put(fieldError.getField(),fieldError.getDefaultMessage()); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); }分組校驗(yàn)

在不同業(yè)務(wù)場(chǎng)景下,校驗(yàn)規(guī)則是不一樣的,比如user對(duì)象中id這個(gè)屬性,在新增的時(shí)候,這個(gè)屬性是不用填的,要為null,但是在修改的時(shí)候,id屬性是不能為null的。

可以用注解中的groups屬性來(lái)指定,在什么場(chǎng)合下使用改注解

@Documented@Constraint(validatedBy = { })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)public @interface NotBlank {Class<?>[] groups() default { };........}

首先定義兩個(gè)接口AddGroup和UpdateGroup,不需要做任何實(shí)現(xiàn)

package cn.jxj4869.demo.valid;public interface UpdateGroup {}

package cn.jxj4869.demo.valid;public interface AddGroup {}

在user中指定group。

id屬性在AddGroup的時(shí)候,要為null,在UpdateGroup的時(shí)候不能為null username屬性在AddGroup和Update的時(shí)候,都要進(jìn)行校驗(yàn),不能為空。 password屬性,當(dāng)校驗(yàn)的時(shí)候指定分組的話(huà),會(huì)不起作用,因?yàn)闆](méi)有給它指定校驗(yàn)的分組

package cn.jxj4869.demo.entity;import cn.jxj4869.demo.valid.AddGroup;import cn.jxj4869.demo.valid.UpdateGroup;import lombok.Data;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotEmpty;import javax.validation.constraints.NotNull;import javax.validation.constraints.Null;@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id; @NotBlank(message = '用戶(hù)名不能為空',groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email;}

在controller中用@Validated注解,指定校驗(yàn)的分組

@PostMapping('/user3') @ResponseBody public R user3(@Validated(UpdateGroup.class) User user) { System.out.println(user); return null; }

結(jié)果如下圖所示,因?yàn)閜assword屬性沒(méi)有指定校驗(yàn)的分組,所以在校驗(yàn)的時(shí)候,都不會(huì)對(duì)它進(jìn)行合法性檢查。

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

自定義校驗(yàn)

當(dāng)提供的注解不能滿(mǎn)足我們需求的時(shí)候,可以自定義注解。

例如我們現(xiàn)在給user新加一個(gè)屬性status,并要求這個(gè)屬性的值只能是0或者1。

新建一個(gè)@StatusValue注解。

根據(jù)jsr303的規(guī)范,校驗(yàn)注解得有三個(gè)屬性。

message:用來(lái)獲取錯(cuò)誤提示的 groups:指定校驗(yàn)分組的。 payload:可以自定義一些負(fù)載信息

使用@Constraint注解指定該注解的校驗(yàn)器

package cn.jxj4869.demo.valid;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;import static java.lang.annotation.ElementType.TYPE_USE;import static java.lang.annotation.RetentionPolicy.RUNTIME;@Documented@Constraint(validatedBy = { StatusValueConstraintValidator.class })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@interface StatusValue { String message() default '{cn.jxj4869.valid.StatusValue.message}'; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; int[] value() default { };}

自定義校驗(yàn)器

需要實(shí)現(xiàn)ConstraintValidator這個(gè)接口,第一個(gè)泛型是表示要校驗(yàn)?zāi)膫€(gè)注解,第二個(gè)泛型是要校驗(yàn)的數(shù)據(jù)的類(lèi)型。

initialize是初始化方法 isValid校驗(yàn)方法,判斷是否校驗(yàn)成功

package cn.jxj4869.demo.valid;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.HashSet;import java.util.Set;public class StatusValueConstraintValidator implements ConstraintValidator<StatusValue,Integer> { private Set<Integer> set = new HashSet<>(); //初始化方法 @Override public void initialize(StatusValue constraintAnnotation) { int[] value = constraintAnnotation.value(); for (int val : value) { set.add(val); } } /** * 判斷是否校驗(yàn)成功 * @param value * @param context * @return */ @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { return set.contains(value); }}

最后在resources目錄下添加一個(gè)ValidationMessages.properties文件

用來(lái)指定錯(cuò)誤信息。

cn.jxj4869.valid.StatusValue.message=必須提交指定的值

UserBean

@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id; @NotBlank(message = '用戶(hù)名不能為空',groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email; @StatusValue(value = {0,1},groups = {AddGroup.class,UpdateGroup.class}) private Integer status;}

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解

常用注解匯總

注解 功能 @Null 對(duì)象必須為null @NotNull 對(duì)象必須不為null,無(wú)法檢查長(zhǎng)度為0的字符串 @NotBlank 字符串必須不為Null,且去掉前后空格長(zhǎng)度必須大于0 @NotEmpty 字符串必須非空 @Length(min = 1,max = 50) 字符串必須在指定長(zhǎng)度內(nèi) @Range(min = 0,max = 100) 必須在指定范圍內(nèi) @AssertTrue 對(duì)象必須為true @AssertFalse 對(duì)象必須為false @Max(Value) 必須為數(shù)字,且小于或等于Value @Min(Value) 必須為數(shù)字,且大于或等于Value @DecimalMax(Value) 必須為數(shù)字( BigDecimal ),且小于或等于Value。小數(shù)存在精度 @DecimalMin(Value) 必須為數(shù)字( BigDecimal ),且大于或等于Value。小數(shù)存在精度 @Digits(integer,fraction) 必須為數(shù)字( BigDecimal ),integer整數(shù)精度,fraction小數(shù)精度 @Size(min,max) 對(duì)象(Array、Collection、Map、String)長(zhǎng)度必須在給定范圍 @Email 字符串必須是合法郵件地址 @Past Date和Calendar對(duì)象必須在當(dāng)前時(shí)間之前 @Future Date和Calendar對(duì)象必須在當(dāng)前時(shí)間之后 @Pattern(regexp=“正則”) 字符串滿(mǎn)足正則表達(dá)式的值

到此這篇關(guān)于SpringBoot后端進(jìn)行數(shù)據(jù)校驗(yàn)JSR303的使用詳解的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)校驗(yàn)JSR303的使用內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 千淘酒店差旅平台-中国第一家针对TMC行业的酒店资源供应平台 | 东莞市海宝机械有限公司-不锈钢分选机-硅胶橡胶-生活垃圾-涡电流-静电-金属-矿石分选机 | 数码管_LED贴片灯_LED数码管厂家-无锡市冠卓电子科技有限公司 | 上海瑶恒实业有限公司|消防泵泵|离心泵|官网| 厚壁钢管-厚壁无缝钢管-小口径厚壁钢管-大口径厚壁钢管 - 聊城宽达钢管有限公司 | 喷漆房_废气处理设备-湖北天地鑫环保设备有限公司 | 大白菜官网,大白菜winpe,大白菜U盘装系统, u盘启动盘制作工具 | 安平县鑫川金属丝网制品有限公司,声屏障,高速声屏障,百叶孔声屏障,大弧形声屏障,凹凸穿孔声屏障,铁路声屏障,顶部弧形声屏障,玻璃钢吸音板 | 考勤系统_人事考勤管理系统_本地部署BS考勤系统_考勤软件_天时考勤管理专家 | 打包箱房_集成房屋-山东佳一集成房屋有限公司 | 螺旋丝杆升降机-SWL蜗轮-滚珠丝杆升降机厂家-山东明泰传动机械有限公司 | 美名宝起名网-在线宝宝、公司、起名平台| 高扬程排污泵_隔膜泵_磁力泵_节能自吸离心水泵厂家-【上海博洋】 | 全自动五线打端沾锡机,全自动裁线剥皮双头沾锡机,全自动尼龙扎带机-东莞市海文能机械设备有限公司 | 深圳工程师职称评定条件及流程_深圳职称评审_职称评审-职称网 | 厌氧反应器,IC厌氧反应器,厌氧三相分离器-山东创博环保科技有限公司 | 连栋温室大棚建造厂家-智能玻璃温室-薄膜温室_青州市亿诚农业科技 | 安平县鑫川金属丝网制品有限公司,声屏障,高速声屏障,百叶孔声屏障,大弧形声屏障,凹凸穿孔声屏障,铁路声屏障,顶部弧形声屏障,玻璃钢吸音板 | 行业分析:提及郑州火车站附近真有 特殊按摩 ?2025实地踩坑指南 新手如何避坑不踩雷 | 电加热导热油炉-空气加热器-导热油加热器-翅片电加热管-科安达机械 | 洁净化验室净化工程_成都实验室装修设计施工_四川华锐净化公司 | 韦伯电梯有限公司| 郑州爱婴幼师学校_专业幼师培训_托育师培训_幼儿教育培训学校 | 离子色谱自动进样器-青岛艾力析实验科技有限公司 | 讲师宝经纪-专业培训机构师资供应商_培训机构找讲师、培训师、讲师经纪就上讲师宝经纪 | 综合管廊模具_生态,阶梯护坡模具_检查井模具制造-致宏模具厂家 | 【直乐】河北石家庄脊柱侧弯医院_治疗椎间盘突出哪家医院好_骨科脊柱外科专业医院_治疗抽动症/关节病骨伤权威医院|排行-直乐矫形中医医院 | 工控机-图像采集卡-PoE网卡-人工智能-工业主板-深圳朗锐智科 | 医养体检包_公卫随访箱_慢病随访包_家签随访包_随访一体机-济南易享医疗科技有限公司 | 电动葫芦|手拉葫芦|环链电动葫芦|微型电动葫芦-北京市凌鹰起重机械有限公司 | 股票入门基础知识_股票知识_股票投资大师_格雷厄姆网 | ph计,实验室ph计,台式ph计,实验室酸度计,台式酸度计 | bng防爆挠性连接管-定做金属防爆挠性管-依客思防爆科技 | 带锯机|木工带锯机圆木推台锯|跑车带锯机|河北茂业机械制造有限公司| | 西安烟道厂家_排气道厂家_包立管厂家「陕西西安」推荐西安天宇烟道 | 【电子厂招聘_普工招工网_工厂招聘信息平台】-工立方打工网 | 盐水蒸发器,水洗盐设备,冷凝结晶切片机,转鼓切片机,絮凝剂加药系统-无锡瑞司恩机械有限公司 | 天津货架厂_穿梭车货架_重型仓储货架_阁楼货架定制-天津钢力仓储货架生产厂家_天津钢力智能仓储装备 | 武汉刮刮奖_刮刮卡印刷厂_为企业提供门票印刷_武汉合格证印刷_现金劵代金券印刷制作 - 武汉泽雅印刷有限公司 | 成都珞石机械 - 模温机、油温机、油加热器生产厂家 | 江西自考网-江西自学考试网|