jfinal 判断方法参数不能为空的注解

本文介绍了一种使用Java注解和拦截器进行参数校验的方法,通过自定义注解EmptyInterface配合拦截器EmptyInterceptor实现对Controller方法参数的非空检查,并详细展示了配置与使用的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1:注解

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface EmptyInterface {
    String[] value();
}
2.:使用拦截器(没有使用处理器)
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.xinxing.annotation.EmptyInterface;
import com.xinxing.utils.StampToDate;

import net.coobird.thumbnailator.util.exif.IfdStructure;

/**
 * 参数不能为空注解验证
 * @author Administrator
 *
 */
public class EmptyInterceptor implements Interceptor {

	@Override
	public void intercept(Invocation inv) {
		EmptyInterface annotation = inv.getMethod().getAnnotation(EmptyInterface.class);
		if (annotation != null) {
			noEmpty(annotation, inv);
        }
	}
	
	public void noEmpty(EmptyInterface annotation,Invocation inv) {
		Controller con = inv.getController();
        String header = con.getHeader("Content-Type"); //取出head头
        if (header != null && header.indexOf("multipart/form-data") != -1) { //判断是否是form-data
        	String folderName = "loss/" + StampToDate.getMonthDay();
        	con.getFile("photo",folderName);
        }
        String[] value = annotation.value();
        boolean isTrue = true;
        String key = "";
        for (String v : value) {
            String parameter = con.getPara(v);
            if (parameter == null || parameter.trim().length() == 0) {
            	isTrue = false;
            	key = v;
            	break;
            }
        }
        if(isTrue){
        	inv.invoke();
        }else{
        	con.setAttr("msg", key+"不能为空");
        	con.setAttr("code", "509");
        	con.renderJson();
        }
        
    }

}
3.在路由配置文件中添加addInterceptor(new EmptyInterceptor()); 一定放在最上面,第一个使用。

4,控制器方法使用注解@EmptyInterface({"areaName","longitude","latitude","distance"}) 或 @EmptyInterface(“id”),没有参数验证的请clear掉拦截器 或者 修改

if (annotation != null) {
			noEmpty(annotation, inv);
        }
让注解参数不为空再去判断 为空就往下执行
inv.invoke();



<think>我们讨论的是如何在后端接收参数时对字段进行判处理,如果为则不使用该字段。这通常发生在使用DTO对象接收前端参数时,我们希望对DTO中的某些字段进行校验,如果字段为null字符串等),则在后续业务处理中忽略这些字段。 解决方案: 1. 在DTO类中,我们可以不对字段进行判,而是在服务层或业务逻辑中进行处理。但这样会导致业务逻辑中掺杂大量的判代码。 2. 使用Spring的@JsonInclude注解,可以在序列化时忽略字段,但这主要影响返回给前端的JSON,而不是接收参数。 3. 在Setter方法中判,如果为则设置默认值或者直接忽略(不设置)。但这样可能会丢失原始数据。 4. 使用验证注解(如@NotNull, @NotEmpty)结合分组验证,但这主要用于验证参数是否满足要求,不满足会抛出异常,而不是忽略字段。 然而,用户的需求是:如果前端传递的某个字段为,则在后端处理时不使用该字段(即忽略该字段,不参与后续业务逻辑)。这通常意味着我们希望在DTO中该字段保持为null,然后在业务逻辑中判断,如果为null就不使用。 但是,如果希望自动忽略字段,我们可以在DTO中使用包装类型(如Integer、Long等)而不是基本类型,这样未传递的字段就是null。然后,在业务逻辑中,我们只处理非null的字段。 另一种思路:使用Map来接收参数,然后遍历Map,移除所有值的键值对,再将Map转换为对象。但这种方式不够优雅,且失去了DTO的类型安全。 因此,推荐的做法是: 1. 使用DTO接收参数,字段使用包装类型(以便可以设置为null)。 2. 在业务逻辑中,检查每个字段,如果字段不为,则进行相应的处理;如果为,则跳过。 示例: 假设我们有一个更新用户信息的接口,前端可能只传递部分字段,我们希望只更新传递过来的非字段。 步骤1:定义DTO ```java @Data public class UserUpdateDTO { private String username; // 用户名 private String email; // 邮箱 private Integer age; // 年龄 } ``` 步骤2:Controller中接收参数 ```java @PostMapping("/update") public ResponseEntity<?> updateUser(@RequestBody UserUpdateDTO dto) { userService.updateUser(dto); return ResponseEntity.ok().build(); } ``` 步骤3:在Service中,判断字段是否为,不为才更新 ```java @Service public class UserService { @Autowired private UserRepository userRepository; public void updateUser(UserUpdateDTO dto) { User user = userRepository.findById(1L).orElseThrow(); // 假设根据id获取用户 if (dto.getUsername() != null) { user.setUsername(dto.getUsername()); } if (dto.getEmail() != null) { user.setEmail(dto.getEmail()); } if (dto.getAge() != null) { user.setAge(dto.getAge()); } userRepository.save(user); } } ``` 但是,如果字段很多,这种逐个判断的方式很繁琐。我们可以使用反射或者工具类来简化。 使用Spring的BeanUtils工具类(注意:这里我们只复制非属性): 我们可以编写一个工具方法,将源对象(DTO)中的非属性复制到目标对象(User)中,忽略值。 示例工具类: ```java public class UpdateUtils { public static void copyNonNullProperties(Object source, Object target) { BeanUtils.copyProperties(source, target, getNullPropertyNames(source)); } private static String[] getNullPropertyNames(Object source) { final BeanWrapper src = new BeanWrapperImpl(source); java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); Set<String> emptyNames = new HashSet<>(); for (java.beans.PropertyDescriptor pd : pds) { Object srcValue = src.getPropertyValue(pd.getName()); if (srcValue == null) { emptyNames.add(pd.getName()); } } String[] result = new String[emptyNames.size()]; return emptyNames.toArray(result); } } ``` 然后在Service中: ```java public void updateUser(UserUpdateDTO dto) { User user = userRepository.findById(1L).orElseThrow(); UpdateUtils.copyNonNullProperties(dto, user); userRepository.save(user); } ``` 这样,只有非的字段会被复制到user对象中,实现了忽略字段的需求。 注意:上面的工具类使用了Spring的BeanUtils和BeanWrapper,需要引入spring-beans包。 另外,如果DTO中字段为字符串("")而不是null,上面的工具类也会将其视为非(因为字符串不是null)。如果希望同时忽略字符串,可以修改工具类,在判断时加入字符串的判断: ```java if (srcValue == null || (srcValue instanceof String && ((String) srcValue).isEmpty())) { emptyNames.add(pd.getName()); } ``` 总结: 1. 使用DTO接收参数,字段使用包装类型。 2. 在业务逻辑中,使用工具类将非且非字符串的属性复制到实体中,实现部分更新。 这样,就实现了对字段的判处理,如果为则不使用该字段。 引用说明:在解决过程中,我们参考了Spring框架中BeanUtils的使用方式,这是一种常见的处理方式[^1]。 相关问题: 1. 如何在使用DTO更新数据库实体时忽略值? 2. Spring Boot中如何实现部分字段更新? 3. 如何使用反射工具忽略DTO中的字段?</think># Spring Boot 参数接收:字段判处理指南 在 Spring Boot 中接收参数时进行判处理,可以通过以下方法实现"若字段为则不使用该字段"的功能: ## 解决方案一:DTO 对象 + 业务逻辑判(推荐) ```java // 1. 创建DTO类 @Data public class UserUpdateDTO { private String username; private String email; private Integer age; // 其他字段... } // 2. Controller中接收参数 @PostMapping("/update") public ResponseEntity<?> updateUser(@RequestBody UserUpdateDTO dto) { // 3. 服务层处理,只使用非字段 userService.updateUser(dto); return ResponseEntity.ok().build(); } // 3. Service层实现判逻辑 @Service public class UserService { public void updateUser(UserUpdateDTO dto) { User user = userRepository.findById(1L).orElseThrow(); // 只更新非字段 if (dto.getUsername() != null) { user.setUsername(dto.getUsername()); } if (dto.getEmail() != null) { user.setEmail(dto.getEmail()); } if (dto.getAge() != null) { user.setAge(dto.getAge()); } userRepository.save(user); } } ``` ## 解决方案二:使用 Map 接收灵活参数 ```java @PostMapping("/update") public ResponseEntity<?> updateUser(@RequestBody Map<String, Object> params) { // 只处理非字段 Map<String, Object> nonNullParams = params.entrySet().stream() .filter(entry -> entry.getValue() != null) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); userService.updateUserWithMap(nonNullParams); return ResponseEntity.ok().build(); } ``` ## 解决方案三:自定义反序列化逻辑 ```java // 1. 自定义反序列化器 public class NullIgnoringDeserializer extends JsonDeserializer<Object> { @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); return node.isNull() ? null : node; } } // 2. 在DTO字段上应用 @Data public class UserUpdateDTO { @JsonDeserialize(using = NullIgnoringDeserializer.class) private String username; @JsonDeserialize(using = NullIgnoringDeserializer.class) private String email; } ``` ## 最佳实践建议 1. **DTO 设计原则**: - 使用包装类型(如 `Integer` 而不是 `int`)以便接收 null 值 - 为可选字段添加 `@Nullable` 注解 - 使用 `Optional` 类型处理可能为的字段 ```java @Data public class UserUpdateDTO { private String username; private String email; private Optional<Integer> age = Optional.empty(); } ``` 2. **验证框架集成**: ```java @PostMapping("/update") public ResponseEntity<?> updateUser( @Valid @RequestBody UserUpdateDTO dto) { // 只处理非字段 userService.updateUser(dto); return ResponseEntity.ok().build(); } ``` 3. **使用工具类简化判**: ```java public class UpdateUtils { public static void updateIfPresent(String value, Consumer<String> setter) { if (value != null) { setter.accept(value); } } } // 在Service中使用 public void updateUser(UserUpdateDTO dto) { User user = // 获取用户实体 UpdateUtils.updateIfPresent(dto.getUsername(), user::setUsername); UpdateUtils.updateIfPresent(dto.getEmail(), user::setEmail); userRepository.save(user); } ``` ## 前端请求示例 ```javascript // 使用 Axios 发送请求 axios.post('/update', { username: 'john_doe', email: null, // 后端将忽略此字段 age: 30 }, { headers: {'Content-Type': 'application/json'} }); ``` ## 注意事项 1. **字符串 vs null**: - `""`(字符串)和 `null` 是不同的概念 - 如果需要同时处理字符串,可添加额外检查: ```java if (dto.getUsername() != null && !dto.getUsername().isEmpty()) { // 处理逻辑 } ``` 2. **集合类型处理**: - 对于 `List` 或 `Set` 类型,使用 `CollectionUtils.isEmpty()` 检查 ```java if (!CollectionUtils.isEmpty(dto.getRoles())) { // 处理角色列表 } ``` 3. **性能考虑**: - 对于字段特别多的DTO,考虑使用反射+注解的方式自动处理 - 或者使用MapStruct等映射工具配置值忽略策略 通过以上方法,您可以灵活地实现"若字段为则不使用该字段"的业务逻辑,保持代码的清晰性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦里藍天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值