当前位置: 首页 > 知识库问答 >
问题:

使用Spring进行自定义UniqueUsername验证

夏骏
2023-03-14

我想确保在创建新用户名或更新用户名时,用户名是唯一的。我写了下面的代码,它可以很好地创建和更新用户名。但是,如果只更新其他用户字段,如年龄或性别,并保留相同的用户名,它将返回invalid,因为用户名已经存在。

重要的是,我想要的验证是使用BindingResault。我已经有一个数据库,将用户名视为唯一的限制。但是现在我想要用BindingResault进行同样的验证。但是我更新用户时的方式会导致错误。

注释@UniqueUsername的定义

package app.condominio.validator;

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

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueUsername {
    String message() default "Nome de usuário já está sendo usado";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

实现验证器

package app.condominio.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.beans.factory.annotation.Autowired;

import app.condominio.service.UsuarioService;

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {

    @Autowired
    UsuarioService usuarioService;

    @Override
    public void initialize(UniqueUsername username) {
    }

    @Override
    public boolean isValid(String username, ConstraintValidatorContext cxt) {
        return !usuarioService.existe(username);
    }
}

在Usuario.class

@Entity
@Table(name = "Usuarios")
public class Usuario implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank
@UniqueUsername
private String username;

@NotBlank
private String password;

@NotBlank
private String nome;

@Email
private String email;

...

通常服务

@Service
@Transactional
public class UsuarioServiceImpl implements UsuarioService {

    @Autowired
    private UsuarioDao usuarioDao;

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public boolean existe(String username) {
        return usuarioDao.existsByUsername(username);
    }

日常岛

public interface UsuarioDao extends CrudRepository<Usuario, Long> {

    Usuario findByUsername(String username);

    Boolean existsByUsername(String username);

}

控制器

@Controller
@RequestMapping("conta")
public class UsuarioController {

    @Autowired
    private UsuarioService usuarioService;

    @GetMapping("/cadastrar/sindico")
    public ModelAndView preCadastro(@ModelAttribute("usuario") Usuario usuario, ModelMap model) {
        model.addAttribute("conteudo", "cadastrarSindico");
        return new ModelAndView("site/layout", model);
    }

    @PostMapping("/cadastrar/sindico")
    public ModelAndView posCadastro(@Valid @ModelAttribute("usuario") Usuario usuario, BindingResult validacao, ModelMap model) {
        if (validacao.hasErrors()) {
            return preCadastro(usuario, model);
        }
        usuarioService.salvarSindico(usuario);
        model.addAttribute(usuario);
        model.addAttribute("conteudo", "cadastrarCondominio");
        return new ModelAndView("site/layout", model);
    }

共有2个答案

许奇
2023-03-14

您可以使用验证组尝试以下方法:

创建标记接口(或类)

public interface UserCreateValidationGroup {
}

然后在你的实体中使用它,就像下面这样

@NotBlank
@UniqueUsername(groups = UserCreateValidationGroup.class)
private String username;

然后在控制器中与< code > @ Validated (JSR-303的Spring变体)一起使用。请注意,为了进行不同的验证,您必须将单个方法分成单独的创建和更新方法。

创建:

@PostMapping("/cadastrar/sindico")
public ModelAndView create(
    @Validated(UserCreateValidationGroup.class) @ModelAttribute("usuario") Usuario usuario, 
    BindingResult validacao, 
    ModelMap model
) { ... }

更新:

// note, here I did use PUT and no argument for @Validated annotation
@PutMapping("/cadastrar/sindico") 
public ModelAndView update(
    @Validated @ModelAttribute("usuario") Usuario usuario, 
    BindingResult validacao, 
    ModelMap model
) { ... }

但是,在更新情况下,您必须对用户名执行手动检查(UsuarioService.existe)。

尹英华
2023-03-14

我认为UniqueUsernameValidator操作符合预期。

我对你的申请不是很清楚。因此很难实现一种方法来检查验证用户是否与数据库中的用户具有相同的id。您可能需要提供更多详细信息,例如< code > usualioservice . existe(username)方法的代码。

对我来说,为了确保用户名是唯一的,我这样做:

@Column(unique=true)
String username;

或使用@UniqueConstraint

@Table(name = "users", uniqueConstraints = {
    @UniqueConstraint(columnNames = {
        "username"
    })
})

但请注意,如果您让 JPA 创建表,它将起作用。

    < li>@UniqueConstraint
 类似资料:
  • 我需要保护我的spring boot应用程序,这是我所拥有的: null 我知道spring boot的web安全特性,但是没有足够的信息来说明如何与自定义令牌一起使用这些特性。

  • 我试图使用keycloak只用于身份验证,并有自己的自定义过滤器用于授权。因此理想的流程是:首先,Keycloak filter对请求进行身份验证,并在上下文中设置身份验证对象。然后,我的自定义过滤器应该运行,它应该获得现有的身份验证对象,在该身份验证对象中添加权限,并将其设置回上下文中。 因此,首先,在speing引导应用程序中使用keycloak是正确的方法吗?如果是,那么如何使我的过滤器在过

  • 我正在用Spring和Thymeleaf填表: MyForm如下所示: 正如您所看到的,我做了一个自定义注释,它应该检查输入值是否可以解析为: 现在在我的Controller类中,我正在执行以下操作: 但是,当试图将放入文本字段以测试验证时,获取: 下面是我读到的示例,并希望用自定义验证器进行扩展:http://viralpatel.net/blogs/spring-mvc-hashmap-for

  • 我们正在尝试在Spring中为我们的rest api创建一个自定义注释。我是创建自定义注释的新手,我已经给出了下面的代码片段 Spring Boot应用程序-- RestController- 自定义注释-- 注解处理器 方法回调-- 我试图处理自定义注释在一个类中实现BeanPost处理器,但我有一个问题 Issue_1:回调被调用一次,但是我不能对 /service/v1/version应用编

  • 我正在学习本教程https://www.baeldung.com/spring-mvc-custom-validator 我现在面临的情况是,我有两个不同的类型,其中一个是,另一个是在其他不同的类中属于类型 并且我想使用regex检查它们内部字符串元素的验证。 因此,一个bean验证注释不是使用两个bean验证注释,而是使用 另一个是带有的 是否可以让一个类同时接受两种类型?如果是,一段代码对我很

  • 问题内容: 我想注册一个可以处理以下处理程序方法定义的自定义 我可以注册我的解析器,这只是创建了一个通过重写通过请求参数对象,从。当Spring尝试解析该参数时,它将遍历其列表(有很多),并选择它的第一个。 在上面的例子中,虽然我的解析器将被调用,我的论点将得到初始化,注释将不会被处理 ,并 为解析器,一个是因为它需要一个会失败,或在处理方法的说法,这我不没有。 如果我尝试通过添加来修复它 一实施