1 请求方式

  在定义一个Rest接口时通常会利用GET、POST、PUT、DELETE来实现数据的增删改查;这几种方式有的需要传递参数,后台开发人员必须对接收到的参数进行参数验证来确保程序的健壮性

  1.1 GET

    一般用于查询数据,采用明文进行传输,一般用来获取一些无关用户信息的数据

  1.2 POST

    一般用于插入数据

  1.3 PUT

    一般用于数据更新

  1.4 DELETE

    一般用于数据删除

    技巧01:一般都是进行逻辑删除(即:仅仅改变记录的状态,而并非真正的删除数据)

2 参数获取注解

  2.1 @PathVariable

    路径参数,形如 url/{param} 时会用到,我们可以通过该注解来获取路径后面的参数来进行GET、DELETE、PUT操作

    

  1. @GetMapping(value = "/{id}")
  2. public ResultViewModel findGirlById(
  3. @PathVariable("id") String id
  4. ) {
  5. // 01 参数去空格
  6. id = StringUtils.trim(id);
  7.  
  8. // 02 判断参数是否全为数字
  9. Integer girlId = 0;
  10. if (JudgeUtil.allIsNumber(id)) {
  11. girlId = Integer.parseInt(id);
  12. } else {
  13. throw new GirlException(GirlEnum.PARAM_NOT_ALL_NUMBER);
  14. }
  15.  
  16. // 03 调用服务层获取数据
  17. return ResultViewModelUtil.success(girlService.findGirlById(girlId));
  18. }

    2.1.1 为路径参数添加正则表达式

      如果前端请求的url中的路径参数不满足正则表达式时,请求就会失败;错误信息是找不到相应的请求方法

        

        代码解释:路径参数必须是数字类型,否则就不会匹配到这个请求路径,如果不是数字类型时返回给前端的信息如下:

          

  2.2 @RequestParam

    用来获取多个参数,常用语POST、PUT操作

    技巧01:这种参数时通过请求rul进行传递的,请求url中?后面的参数就是这种类型

    技巧02:默认就是利用这种方式进行传参

    技巧03:controller中方法参数可以利用一个对象来接收前端传过来的参数

  2.3 @RequestBody

    利用一个对象去获取前端传过来的数据

    技巧01:这种参数是通过请求体进行传递的

  1. @PutMapping
  2. public ResultViewModel updateOneGirl(
  3. @Valid @RequestBody GirlFormModel girlFormModel,
  4. BindingResult result
  5. ) {
  6. // 01 参数验证
  7. if (result.hasErrors()) {
  8. // 0101 存储错误信息的字符串变量
  9. StringBuffer msgBuffer = new StringBuffer();
  10. // 0102 错误字段集合
  11. List<FieldError> fieldErrors = result.getFieldErrors();
  12. for (FieldError fieldError : fieldErrors) {
  13. // 0103 获取错误信息
  14. msgBuffer.append(fieldError.getField() + ":" + fieldError.getDefaultMessage());
  15. }
  16. // 0104 抛出错误信息
  17. throw new GirlException(GirlEnum.PARAM_ERROR.getCode(), msgBuffer.toString());
  18. }
  19.  
  20. // 02 将表单对象转化成数据对象
  21. GirlModel girlModel = new GirlModel();
  22. BeanUtils.copyProperties(girlFormModel, girlModel);
  23.  
  24. // 03 调用服务层进行更新操作
  25. Boolean updateResult = girlService.updateGirl(girlModel);
  26. if (updateResult) {
  27. return ResultViewModelUtil.success(GirlEnum.UPDATE_SUCCESS.getMessage());
  28. } else {
  29. return ResultViewModelUtil.error(GirlEnum.UPDATE_ERROR.getCode(), GirlEnum.UPDATE_ERROR.getMessage());
  30. }
  31. }

3 参数验证注解

  后台单独对接收到的参数进行验证时比较麻烦,springboot项目的web组件集成了hibernate-validator,开发者可以直接使用hibernate-validator提供的注解对数据进行校验,当有一些复杂的参数校验时我们也可以自定义校验注解

  技巧01:接收到的参数默认都是字符串类型的

  技巧02:如果是SpringBoot项目必须导入JPA先关的jar包,因为JPA是基于Hibernate的,所以JPA相关的jar包里面会有相关的验证注解;其实不用导入JPA的jar包也可以使用,因为 spring-boot-starter-web 中已经包含了 hibernate-validator 相关的校验注解。

  坑01:有的注解只能用在String类型的属性上

  3.1 常用的验证注解有

    

    技巧01:@JsonProperty可以实现前端的属性名和后台实体类的属性名不一致问题,例如

      

      代码解释:前端传过来的属性名为nick,后台接收的属性名为nickname

      技巧01:前端传过来的参数和后台不一致的情况只对@RequestBody这种参数有效

      技巧02:后台传给前台时使用的属性名是@JsonProperty中的参数而不是实体中定义的属性名

  3.2 使用方法

    直接在表单实体类的属性上面添加相应的注解就可以啦

  1. package cn.xiangxu.springboottest.model.dataFormModel;
  2.  
  3. import cn.xiangxu.springboottest.commons.validators.GirlFormIdValidator;
  4. import com.fasterxml.jackson.annotation.JsonProperty;
  5. import lombok.Data;
  6. import org.hibernate.validator.constraints.NotBlank;
  7. import org.hibernate.validator.constraints.NotEmpty;
  8.  
  9. import javax.validation.constraints.Min;
  10.  
  11. @Data
  12. public class GirlFormModel {
  13.  
  14. // @NotBlank(message = "目标girl的ID不能为空")
  15. // @NotEmpty(message = "目标girl的ID不能为空哟")
  16. // @GirlFormIdValidator
  17. private Integer girlId;
  18.  
  19. @Min(value = 123)
  20. private Integer age;
  21.  
  22. private String name;
  23.  
  24. private String password;
  25.  
  26. @NotEmpty(message = "昵称不能为空")
  27. @NotBlank(message = "昵称不能为空哟")
  28. @JsonProperty("nick") // 当前端属性为nick后台接收对象的属性为nickName时可以用@JsonProperty来保持一致
  29. private String nickname;
  30.  
  31. @NotEmpty(message = "地址不能为空")
  32. @NotBlank(message = "地址不能为空哟")
  33. private String address;
  34. }

  3.3 如何使参数校验生效

    3.3.1 在控制层方法的形参前面添加@Valid注解

      技巧01:如果在controller层控制方法中的参数标注了@Valid注解后,前端传过来的参数一旦发现不合法就会抛出请求错误(即:400错误)

      

    3.3.2 利用BindingResult对象获取参数错误字段和参数错误信息

      技巧01:如果只是添加@Valid注解,如果参数错误就会直接抛出异常

      技巧02:后台开发时通常都需要对前端传过来的参数进行一次参数验证,如果参数不正确我们需要抛出一些用户可以识别的错误信息而不是抛出原生的错误;所以我们需要在方法中添加一个BindingResult参数

      技巧03:给控制方法添加了BindingResult参数后,即使前端传过来的参数不合法也会继续执行方法体;我们可以利用BindingResult对象去判断时哪一个参数不合法,从而抛出一些自定义的异常信息

      》获取所有错误字段和错误信息的代码如下

      

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5.  
  6. package org.springframework.validation;
  7.  
  8. import java.beans.PropertyEditor;
  9. import java.util.Map;
  10. import org.springframework.beans.PropertyEditorRegistry;
  11.  
  12. public interface BindingResult extends Errors {
  13. String MODEL_KEY_PREFIX = BindingResult.class.getName() + ".";
  14.  
  15. Object getTarget();
  16.  
  17. Map<String, Object> getModel();
  18.  
  19. Object getRawFieldValue(String var1);
  20.  
  21. PropertyEditor findEditor(String var1, Class<?> var2);
  22.  
  23. PropertyEditorRegistry getPropertyEditorRegistry();
  24.  
  25. void addError(ObjectError var1);
  26.  
  27. String[] resolveMessageCodes(String var1);
  28.  
  29. String[] resolveMessageCodes(String var1, String var2);
  30.  
  31. void recordSuppressedField(String var1);
  32.  
  33. String[] getSuppressedFields();
  34. }

BindingResult源码

      》获取单个错误字段和错误信息的代码如下

        

  1. @PostMapping(value = "/user")
  2. public String create(
  3. @Valid @RequestBody User user,
  4. BindingResult errors
  5. ) {
  6. if (errors.hasErrors()) {
  7. errors.getAllErrors().stream().forEach(
  8. error -> {
  9. FieldError fieldError = (FieldError)error;
  10. log.info("错误字段:{} -> 错误信息:{}",
  11. fieldError.getField(),
  12. fieldError.getDefaultMessage()
  13. );
  14. }
  15. );
  16. }
  17.  
  18. log.info("获取到的参数信息为:" + user);
  19. String info = "新增用户成功";
  20. return info;
  21. }

      技巧04:利用BindingResult对象的hasErrors方法判断是否有参数错误

    ·  技巧05:利用BindingResult对象的getFieldErrors方法获取所有有参数错误的属性

       技巧06:利用错误属性对象的getDefaultMessage去获取错误提示信息

4 自定义参数验证注解

  4.1 定义一个注解接口

    技巧01:每个自定义的校验注解必须要有这四个成员

    

  1. package cn.xiangxu.springboottest.commons.validators;
  2.  
  3. import cn.xiangxu.springboottest.commons.validators.validatorClass.GirlFormValidatorClass;
  4.  
  5. import javax.validation.Constraint;
  6. import javax.validation.Payload;
  7. import java.lang.annotation.*;
  8.  
  9. @Documented
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Target({ElementType.PARAMETER, ElementType.FIELD})
  12. @Constraint(validatedBy = GirlFormValidatorClass.class)
  13. public @interface GirlFormIdValidator {
  14. String values();
  15. String message() default "girl的ID必须为纯数字";
  16.  
  17. Class<?>[] groups() default {};
  18. Class<? extends Payload>[] payload() default {};
  19.  
  20. }

  4.2 定义一个注解接口实现类

    技巧01:必须实现ConstraintValidator接口

    技巧02:实现了ConstraintValidator接口后即使不进行Bean配置,spring也会将这个类进行Bean管理

    技巧03:可以在实现了ConstraintValidator接口的类中依赖注入其它Bean

    技巧04:实现了ConstraintValidator接口后必须重写 initialize 和 isValid 这两个方法;initialize方法主要来进行初始化,通常用来获取自定义注解的属性值;isValid 方法主要进行校验逻辑,返回true表示校验通过,返回false表示校验失败,通常根据注解属性值和实体类属性值进行校验判断

    

  1. package cn.xiangxu.springboottest.commons.validators.validatorClass;
  2.  
  3. import cn.xiangxu.springboottest.commons.validators.GirlFormIdValidator;
  4. import cn.xiangxu.springboottest.utils.JudgeUtil;
  5.  
  6. import javax.validation.ConstraintValidator;
  7. import javax.validation.ConstraintValidatorContext;
  8.  
  9. public class GirlFormValidatorClass implements ConstraintValidator<GirlFormIdValidator, Object> {
  10.  
  11. private String values;
  12.  
  13. @Override
  14. public void initialize(GirlFormIdValidator girlFormValidator) {
  15. this.values = girlFormValidator.values();
  16. }
  17.  
  18. @Override
  19. public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
  20. if (JudgeUtil.allIsNumber((String)value)) {
  21. return true;
  22. }
  23. return false;
  24. }
  25. }

  4.3 在实体类中使用自定义的参数校验注解

    

5 BeanUtils的使用

  利用BeanUtils提供的copyProperties可以实现实体类数据的复制

  坑01:只用属性名和属性类型一致的部分才可以进行复制操作,例如

    BeanUtils.copyProperties(girlFormModel, girlModel);

    代码解释:将girlFormModel对象复制给girlModel对象

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5.  
  6. package org.springframework.beans;
  7.  
  8. import java.beans.PropertyDescriptor;
  9. import java.beans.PropertyEditor;
  10. import java.lang.reflect.Constructor;
  11. import java.lang.reflect.InvocationTargetException;
  12. import java.lang.reflect.Method;
  13. import java.lang.reflect.Modifier;
  14. import java.net.URI;
  15. import java.net.URL;
  16. import java.util.Arrays;
  17. import java.util.Collections;
  18. import java.util.Date;
  19. import java.util.List;
  20. import java.util.Locale;
  21. import java.util.Set;
  22. import org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.springframework.core.MethodParameter;
  25. import org.springframework.util.Assert;
  26. import org.springframework.util.ClassUtils;
  27. import org.springframework.util.ConcurrentReferenceHashMap;
  28. import org.springframework.util.ReflectionUtils;
  29. import org.springframework.util.StringUtils;
  30.  
  31. public abstract class BeanUtils {
  32. private static final Log logger = LogFactory.getLog(BeanUtils.class);
  33. private static final Set<Class<?>> unknownEditorTypes = Collections.newSetFromMap(new ConcurrentReferenceHashMap(64));
  34.  
  35. public BeanUtils() {
  36. }
  37.  
  38. public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
  39. Assert.notNull(clazz, "Class must not be null");
  40. if (clazz.isInterface()) {
  41. throw new BeanInstantiationException(clazz, "Specified class is an interface");
  42. } else {
  43. try {
  44. return clazz.newInstance();
  45. } catch (InstantiationException var2) {
  46. throw new BeanInstantiationException(clazz, "Is it an abstract class?", var2);
  47. } catch (IllegalAccessException var3) {
  48. throw new BeanInstantiationException(clazz, "Is the constructor accessible?", var3);
  49. }
  50. }
  51. }
  52.  
  53. public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
  54. Assert.notNull(clazz, "Class must not be null");
  55. if (clazz.isInterface()) {
  56. throw new BeanInstantiationException(clazz, "Specified class is an interface");
  57. } else {
  58. try {
  59. return instantiateClass(clazz.getDeclaredConstructor());
  60. } catch (NoSuchMethodException var2) {
  61. throw new BeanInstantiationException(clazz, "No default constructor found", var2);
  62. }
  63. }
  64. }
  65.  
  66. public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
  67. Assert.isAssignable(assignableTo, clazz);
  68. return instantiateClass(clazz);
  69. }
  70.  
  71. public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
  72. Assert.notNull(ctor, "Constructor must not be null");
  73.  
  74. try {
  75. ReflectionUtils.makeAccessible(ctor);
  76. return ctor.newInstance(args);
  77. } catch (InstantiationException var3) {
  78. throw new BeanInstantiationException(ctor, "Is it an abstract class?", var3);
  79. } catch (IllegalAccessException var4) {
  80. throw new BeanInstantiationException(ctor, "Is the constructor accessible?", var4);
  81. } catch (IllegalArgumentException var5) {
  82. throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", var5);
  83. } catch (InvocationTargetException var6) {
  84. throw new BeanInstantiationException(ctor, "Constructor threw exception", var6.getTargetException());
  85. }
  86. }
  87.  
  88. public static Method findMethod(Class<?> clazz, String methodName, Class... paramTypes) {
  89. try {
  90. return clazz.getMethod(methodName, paramTypes);
  91. } catch (NoSuchMethodException var4) {
  92. return findDeclaredMethod(clazz, methodName, paramTypes);
  93. }
  94. }
  95.  
  96. public static Method findDeclaredMethod(Class<?> clazz, String methodName, Class... paramTypes) {
  97. try {
  98. return clazz.getDeclaredMethod(methodName, paramTypes);
  99. } catch (NoSuchMethodException var4) {
  100. return clazz.getSuperclass() != null ? findDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes) : null;
  101. }
  102. }
  103.  
  104. public static Method findMethodWithMinimalParameters(Class<?> clazz, String methodName) throws IllegalArgumentException {
  105. Method targetMethod = findMethodWithMinimalParameters(clazz.getMethods(), methodName);
  106. if (targetMethod == null) {
  107. targetMethod = findDeclaredMethodWithMinimalParameters(clazz, methodName);
  108. }
  109.  
  110. return targetMethod;
  111. }
  112.  
  113. public static Method findDeclaredMethodWithMinimalParameters(Class<?> clazz, String methodName) throws IllegalArgumentException {
  114. Method targetMethod = findMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName);
  115. if (targetMethod == null && clazz.getSuperclass() != null) {
  116. targetMethod = findDeclaredMethodWithMinimalParameters(clazz.getSuperclass(), methodName);
  117. }
  118.  
  119. return targetMethod;
  120. }
  121.  
  122. public static Method findMethodWithMinimalParameters(Method[] methods, String methodName) throws IllegalArgumentException {
  123. Method targetMethod = null;
  124. int numMethodsFoundWithCurrentMinimumArgs = 0;
  125. Method[] var4 = methods;
  126. int var5 = methods.length;
  127.  
  128. for(int var6 = 0; var6 < var5; ++var6) {
  129. Method method = var4[var6];
  130. if (method.getName().equals(methodName)) {
  131. int numParams = method.getParameterTypes().length;
  132. if (targetMethod != null && numParams >= targetMethod.getParameterTypes().length) {
  133. if (!method.isBridge() && targetMethod.getParameterTypes().length == numParams) {
  134. if (targetMethod.isBridge()) {
  135. targetMethod = method;
  136. } else {
  137. ++numMethodsFoundWithCurrentMinimumArgs;
  138. }
  139. }
  140. } else {
  141. targetMethod = method;
  142. numMethodsFoundWithCurrentMinimumArgs = 1;
  143. }
  144. }
  145. }
  146.  
  147. if (numMethodsFoundWithCurrentMinimumArgs > 1) {
  148. throw new IllegalArgumentException("Cannot resolve method '" + methodName + "' to a unique method. Attempted to resolve to overloaded method with the least number of parameters but there were " + numMethodsFoundWithCurrentMinimumArgs + " candidates.");
  149. } else {
  150. return targetMethod;
  151. }
  152. }
  153.  
  154. public static Method resolveSignature(String signature, Class<?> clazz) {
  155. Assert.hasText(signature, "'signature' must not be empty");
  156. Assert.notNull(clazz, "Class must not be null");
  157. int firstParen = signature.indexOf("(");
  158. int lastParen = signature.indexOf(")");
  159. if (firstParen > -1 && lastParen == -1) {
  160. throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected closing ')' for args list");
  161. } else if (lastParen > -1 && firstParen == -1) {
  162. throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected opening '(' for args list");
  163. } else if (firstParen == -1 && lastParen == -1) {
  164. return findMethodWithMinimalParameters(clazz, signature);
  165. } else {
  166. String methodName = signature.substring(0, firstParen);
  167. String[] parameterTypeNames = StringUtils.commaDelimitedListToStringArray(signature.substring(firstParen + 1, lastParen));
  168. Class<?>[] parameterTypes = new Class[parameterTypeNames.length];
  169.  
  170. for(int i = 0; i < parameterTypeNames.length; ++i) {
  171. String parameterTypeName = parameterTypeNames[i].trim();
  172.  
  173. try {
  174. parameterTypes[i] = ClassUtils.forName(parameterTypeName, clazz.getClassLoader());
  175. } catch (Throwable var10) {
  176. throw new IllegalArgumentException("Invalid method signature: unable to resolve type [" + parameterTypeName + "] for argument " + i + ". Root cause: " + var10);
  177. }
  178. }
  179.  
  180. return findMethod(clazz, methodName, parameterTypes);
  181. }
  182. }
  183.  
  184. public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException {
  185. CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
  186. return cr.getPropertyDescriptors();
  187. }
  188.  
  189. public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) throws BeansException {
  190. CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz);
  191. return cr.getPropertyDescriptor(propertyName);
  192. }
  193.  
  194. public static PropertyDescriptor findPropertyForMethod(Method method) throws BeansException {
  195. return findPropertyForMethod(method, method.getDeclaringClass());
  196. }
  197.  
  198. public static PropertyDescriptor findPropertyForMethod(Method method, Class<?> clazz) throws BeansException {
  199. Assert.notNull(method, "Method must not be null");
  200. PropertyDescriptor[] pds = getPropertyDescriptors(clazz);
  201. PropertyDescriptor[] var3 = pds;
  202. int var4 = pds.length;
  203.  
  204. for(int var5 = 0; var5 < var4; ++var5) {
  205. PropertyDescriptor pd = var3[var5];
  206. if (method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())) {
  207. return pd;
  208. }
  209. }
  210.  
  211. return null;
  212. }
  213.  
  214. public static PropertyEditor findEditorByConvention(Class<?> targetType) {
  215. if (targetType != null && !targetType.isArray() && !unknownEditorTypes.contains(targetType)) {
  216. ClassLoader cl = targetType.getClassLoader();
  217. if (cl == null) {
  218. try {
  219. cl = ClassLoader.getSystemClassLoader();
  220. if (cl == null) {
  221. return null;
  222. }
  223. } catch (Throwable var5) {
  224. if (logger.isDebugEnabled()) {
  225. logger.debug("Could not access system ClassLoader: " + var5);
  226. }
  227.  
  228. return null;
  229. }
  230. }
  231.  
  232. String editorName = targetType.getName() + "Editor";
  233.  
  234. try {
  235. Class<?> editorClass = cl.loadClass(editorName);
  236. if (!PropertyEditor.class.isAssignableFrom(editorClass)) {
  237. if (logger.isWarnEnabled()) {
  238. logger.warn("Editor class [" + editorName + "] does not implement [java.beans.PropertyEditor] interface");
  239. }
  240.  
  241. unknownEditorTypes.add(targetType);
  242. return null;
  243. } else {
  244. return (PropertyEditor)instantiateClass(editorClass);
  245. }
  246. } catch (ClassNotFoundException var4) {
  247. if (logger.isDebugEnabled()) {
  248. logger.debug("No property editor [" + editorName + "] found for type " + targetType.getName() + " according to 'Editor' suffix convention");
  249. }
  250.  
  251. unknownEditorTypes.add(targetType);
  252. return null;
  253. }
  254. } else {
  255. return null;
  256. }
  257. }
  258.  
  259. public static Class<?> findPropertyType(String propertyName, Class... beanClasses) {
  260. if (beanClasses != null) {
  261. Class[] var2 = beanClasses;
  262. int var3 = beanClasses.length;
  263.  
  264. for(int var4 = 0; var4 < var3; ++var4) {
  265. Class<?> beanClass = var2[var4];
  266. PropertyDescriptor pd = getPropertyDescriptor(beanClass, propertyName);
  267. if (pd != null) {
  268. return pd.getPropertyType();
  269. }
  270. }
  271. }
  272.  
  273. return Object.class;
  274. }
  275.  
  276. public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd) {
  277. return pd instanceof GenericTypeAwarePropertyDescriptor ? new MethodParameter(((GenericTypeAwarePropertyDescriptor)pd).getWriteMethodParameter()) : new MethodParameter(pd.getWriteMethod(), 0);
  278. }
  279.  
  280. public static boolean isSimpleProperty(Class<?> clazz) {
  281. Assert.notNull(clazz, "Class must not be null");
  282. return isSimpleValueType(clazz) || clazz.isArray() && isSimpleValueType(clazz.getComponentType());
  283. }
  284.  
  285. public static boolean isSimpleValueType(Class<?> clazz) {
  286. return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() || CharSequence.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || URI.class == clazz || URL.class == clazz || Locale.class == clazz || Class.class == clazz;
  287. }
  288.  
  289. public static void copyProperties(Object source, Object target) throws BeansException {
  290. copyProperties(source, target, (Class)null, (String[])null);
  291. }
  292.  
  293. public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException {
  294. copyProperties(source, target, editable, (String[])null);
  295. }
  296.  
  297. public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
  298. copyProperties(source, target, (Class)null, ignoreProperties);
  299. }
  300.  
  301. private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties) throws BeansException {
  302. Assert.notNull(source, "Source must not be null");
  303. Assert.notNull(target, "Target must not be null");
  304. Class<?> actualEditable = target.getClass();
  305. if (editable != null) {
  306. if (!editable.isInstance(target)) {
  307. throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
  308. }
  309.  
  310. actualEditable = editable;
  311. }
  312.  
  313. PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
  314. List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
  315. PropertyDescriptor[] var7 = targetPds;
  316. int var8 = targetPds.length;
  317.  
  318. for(int var9 = 0; var9 < var8; ++var9) {
  319. PropertyDescriptor targetPd = var7[var9];
  320. Method writeMethod = targetPd.getWriteMethod();
  321. if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
  322. PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
  323. if (sourcePd != null) {
  324. Method readMethod = sourcePd.getReadMethod();
  325. if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
  326. try {
  327. if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
  328. readMethod.setAccessible(true);
  329. }
  330.  
  331. Object value = readMethod.invoke(source);
  332. if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
  333. writeMethod.setAccessible(true);
  334. }
  335.  
  336. writeMethod.invoke(target, value);
  337. } catch (Throwable var15) {
  338. throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
  339. }
  340. }
  341. }
  342. }
  343. }
  344.  
  345. }
  346. }

BeanUtils源代码

·下面是我的公众号二维码,欢迎关注·

尋渝記

微信号:xyj_fury

SpringBoot08 请求方式、参数获取注解、参数验证、前后台属性名不一致问题、自定义参数验证注解、BeanUtils的使用的更多相关文章

  1. SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数

    SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...

  2. java反射获取类的类名、属性名、属性类型、方法、执行方法、构造函数

    public class Demo02 { @SuppressWarnings("all") public static void main(String[] args) thro ...

  3. JMeter学习-011-JMeter 后置处理器实例之 - 正则表达式提取器(三)多参数获取进阶引用篇

    前两篇文章分表讲述了 后置处理器 - 正则表达式提取器概述及简单实例.多参数获取,相应博文敬请参阅 简单实例.多参数获取. 此文主要讲述如何引用正则表达式提取器获取的数据信息.其实,正则表达式提取器获 ...

  4. 【spring springmvc】这里有你想要的SpringMVC的REST风格的四种请求方式

    概述 之前的文章springmvc使用注解声明控制器与请求映射有简单提到过控制器与请求映射,这一次就详细讲解一下SpringMVC的REST风格的四种请求方式及其使用方法. 你能get的知识点 1.什 ...

  5. get、post请求方式在jmeter中使用步骤

    jmeter:性能测试工具,压测 一.jmeter工具测试接口时使用步骤: 1.测试计划右键--添加--Threads(Users)--线程组(线程数就是并发数) 2.线程组右键--Sampler-- ...

  6. Java自定义数据验证注解Annotation

    本文转载自:https://www.jianshu.com/p/616924cd07e6 Java注解Annotation用起来很方便,也越来越流行,由于其简单.简练且易于使用等特点,很多开发工具都提 ...

  7. mybatis——解决属性名和数据库字段名不一致问题(注解方式)

    当我们使用注解开发时有时会遇到数据库字段名与实体类属性名不一致的问题.xml方式开发可以通过结果集映射的方式解决,那注解方式开发要怎么解决呢? 注解解决方式: @Results()注解 Results ...

  8. Scrapy命令行调用传入自定义参数

    在做爬虫服务化时,有这样一个需求:接口用命令行启动爬虫,但是数据入库时要记录此次任务的task_id. 简单说就是,Scrapy命令行启动时要动态传参进去. 解决方案: 在spider中定义一个构造函 ...

  9. webAPI(DOM) 2.1 获取页面元素 | 事件1 | 属性操作 | 节点 | 创建元素 | 事件2

    js分三个部分: ECMAScript标准:js的基本语法 DOM:Ducument Object Model--->文档对象模型--->操作页面的元素 BOM:Browser Objec ...

随机推荐

  1. 【JEECG技术文档】数据权限自定义SQL表达式用法说明

    功能介绍   数据规则通过配置自定义sql来实现数据权限的控制,自定义SQL支持表达式取值 其中自定义sql 条件中字段的名称和数据库表的字段名保持一致. 角色授权 用户角色授权,权限测试不要用adm ...

  2. Django - cookies 会话跟踪技术

    一.HTTP协议的无状态保存 两次请求之间没有关联 会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应 2.会话路径技术使用Cookie或session完成 我们知道HTTP ...

  3. es6初级之解构----之二 及 键值反转实现

    1.解构: 不定参数,扩展表达式 let arr = [100, 201, 303, 911]; let [one, ...others] = arr; console.log(others.leng ...

  4. http post 接口

    集团需求管理系统通过网状网与给各省公司需求管理系统进行交互.落地方为发起方提供访问的URL,发起方使用HTTP POST方法发送请求报文并得到应答报文,发起方作为落地方的HTTP客户端,落地方作为发起 ...

  5. 25. IO流.md

    目录 IO分类: 1.FIle类 1.1目录分隔符 1.2常用方法 2.FileInputStream类 2.1读取文件 3.FileOutputStream类 拷贝文件 4.缓冲流 4.1 Buff ...

  6. Windows Server 2008 R2微软官方下载

    注意:Windows Server 2008 R2仅有64位版本. 以下下载地址为Windows Server 2008 R2 RTM Build 7600.16385的评估版本,此版本可免费试用18 ...

  7. Python系列之 __new__ 与 __init__

    很喜欢Python这门语言.在看过语法后学习了Django 这个 Web 开发框架.算是对 Python 有些熟悉了.不过对里面很多东西还是不知道,因为用的少.今天学习了两个魔术方法:__new__ ...

  8. 实现了一下Mp3播放器的功能

    实现了一下Mp3播放器的功能 简单的实现了一下Mp3播放器的功能,见面比较的不美好,讲 究看一下就好了. 主要功能: 1.显示文件列表,主要参照了一位前辈的代码,谢咯. 2.可以实现播放开始,暂停. ...

  9. hdu3826-Squarefree number-(欧拉筛+唯一分解定理)

    Squarefree number Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  10. Linux安装face_recgnition

    Ubuntu 3:apt-get install python3.6-dev 4:pip3 install face_recgnition 5:  pip3 install opencv-python ...