SpringBoot写出简单的后端接口

所需依赖包

<!--web依赖包,web应用必备-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

参数校验 Validator + BindResult进行校验

Validator可以非常方便的制定校验规则,并自动帮你完成校验。首先在入参里需要校验的字段加上注解,每个注解对应不同的校验规则,并可制定校验失败后的信息:
实体类 参数加上校验注解

@Data
public class User {
    @NotNull(message = "用户id不能为空")
    private Long id;

    @NotNull(message = "用户账号不能为空")
    @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符")
    private String account;

    @NotNull(message = "用户密码不能为空")
    @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符")
    private String password;

    @NotNull(message = "用户邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
}

校验规则和错误提示信息配置完毕后,接下来只需要在接口需要校验的参数上加上@Valid注解,并添加BindResult参数即可方便完成验证:

@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/addUser")
    public String addUser(@RequestBody @Valid User user, BindingResult bindingResult) {
        // 如果有参数校验失败,会将错误信息封装成对象组装在BindingResult里
        for (ObjectError error : bindingResult.getAllErrors()) {
            return error.getDefaultMessage();
        }
        return userService.addUser(user);
    }
}

这样当请求数据传递到接口的时候Validator就自动完成校验了,校验的结果就会封装到BindingResult中去,如果有错误信息我们就直接返回给前端,业务逻辑代码也根本没有执行下去。

现在可以看一下参数校验效果。我们故意给这个接口传递一个不符合校验规则的参数,先传递一个错误数据给接口,故意将password这个字段不满足校验条件:

错误参数:
在这里插入图片描述
正确参数:
在这里插入图片描述
这样是不是方便很多?不难看出使用Validator校验有如下几个好处:

  • 简化代码: 之前业务层那么一大段校验代码都被省略掉了。
  • 使用方便: 那么多校验规则可以轻而易举的实现,比如邮箱格式验证,之前自己手写正则表达式要写那么一长串,还容易出错,用Validator直接一个注解搞定。
  • 更多注解 释义:
  • 在这里插入图片描述
  • 减少耦合度: 使用Validator能够让业务层只关注业务逻辑,从基本的参数校验逻辑中脱离出来。使用Validator+ BindingResult已经是非常方便实用的参数校验方式了,在实际开发中也有很多项目就是这么做的,不过这样还是不太方便,因为每写一个接口都要添加一个BindingResult参数,然后再提取错误信息返回给前端。这样有点麻烦,并且重复代码很多,可以 直接将 BindingResult参数 去掉,也可以编写全局异常处理 !

去掉BindingResult参数:

@PostMapping("/addUser")
public String addUser(@RequestBody @Valid User user) {
    return userService.addUser(user);
}

去掉之后会试验一下,还是按照之前一样故意传递一个不符合校验规则的参数给接口。此时观察控制台可以发现接口已经引发MethodArgumentNotValidException异常了:
自动返回了非明文的错误信息,其实这样就已经达到我们想要的效果了,参数校验不通过自然就不执行接下来的业务逻辑。不过事情还没有完,异常是引发了,可并没有编写返回错误信息的代码呀,那参数校验失败了会响应什么数据给前端呢?

全局异常处理

参数校验失败会自动引发异常,我们当然不可能再去手动捕捉异常进行处理,不然还不如用之前BindingResult方式呢。又不想手动捕捉这个异常,又要对这个异常进行处理,那正好使用SpringBoot全局异常处理来达到一劳永逸的效果!
处理参数校验异常>>>:

首先,我们需要新建一个类,在这个类上加上
@ControllerAdvice或@RestControllerAdvice注解这个类就配置成全局处理类了。
(这个根据你的Controller层用的是@Controller还是@RestController来决定)然后在类中新建方法,在方法上加上@ExceptionHandler注解并指定你想处理的异常类型,接着在方法内编写对该异常的操作逻辑,就完成了对该异常的全局处理!我们现在就来演示一下对参数校验失败抛出的MethodArgumentNotValidException全局处理:

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义 处理  MethodArgumentNotValidException 参数校验错误
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     * 如果 使用的是 org.hibernate.validator jar 的话 使用:
     * MethodArgumentNotValidException.class 捕捉参数校验异常
     * 如果是 SpringBoot默认的校验  使用:
     * org.springframework.validation.BindException.class 捕捉参数校验异常
     * 我这里使用的是  SpringBoot默认的
     */
    @ExceptionHandler(value = BindException.class)
    public String BindException(BindException e) {
      StringBuilder sb = new StringBuilder();
      for (ObjectError error: e.getBindingResult().getAllErrors()) {
        sb.append(error.getDefaultMessage());
        sb.append("、");
      }
      String errorMsg = sb.substring(0,sb.length() - 1).toString();
      return errorMsg;
    }

}

404异常处理
因为 是后端接口都是API 返回的是JSON内容,并不是 使用模板引擎html页面,但是SpringBoot 在发生404的时候会自动去映射,会去找对应模版, 需要将SpringBoot的错误自动映射给关闭:
1、关闭 SpringBoot错误自动映射,打开application.properties

# 关闭SpringBoot 错误自动映射 ,如 404错误 会自动映射寻找对应模板,系统使用全局异常处理了返回结果
# 如果是 用thymeleaf 的话不用关闭错误自动映射
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

2、在全局异常类中 处理 NoHandlerFoundException 404 异常

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义异常 处理  NoHandlerFoundException  404 异常
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public String NoHandlerFoundException(NoHandlerFoundExceptione) {
        String msg = "请求错误,接口路径错误!不存在";
        // org.springframework.web.servlet.NoHandlerFoundException 为 404错误
		return msg;
    }


	// 或者 在全局 异常中判断处理
    @ExceptionHandler(value = Exception.class)
    public StringexceptionHandler(Exception e){
        String msg = null;
        // org.springframework.web.servlet.NoHandlerFoundException 为 404错误
        if( e instanceof  NoHandlerFoundException){
            msg = "请求错误,接口路径错误!不存在";
        }else{
            msg = "请求错误[{"+e.getMessage()+"}]";
        }
        return msg ;
    }
  }

自定义异常

全局处理当然不会只能处理一种异常,用途也不仅仅是对一个参数校验方式进行优化。在实际开发中,如何对异常处理其实是一个很麻烦的事情。

1、 定义一个 运行异常实体类:

/**
 * 自定义异常
 */
public class itException extends  RuntimeException {
    private String errorMsg;

    public String getErrorMsg() {
        return errorMsg;
    }
	// 创建 构造方法,传入错误内容
    public itException (String message) {
        super(message);
        this.errorMsg = message;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

2、在全局异常类中 处理 自定义的异常类

/**
 * 错误请求控制器
 */
@RestControllerAdvice
@CrossOrigin
public class exceptionController {
    public static Logger log = LoggerFactory.getLogger(exceptionController.class);

    /** 自定义异常类  itException 
     * @param e
     * @return 根据自定义返回结果 返回对应内容
     */
    @ExceptionHandler(value = itException .class)
    public String MethodArgumentNotValidException(itException e) {
 		String msg = e.getErrorMsg()
 		return msg; 
    }

}

3、使用:

	public static void main(String[] args) {
		// 测试自定义异常
		throw  new foundException("自定义异常");
	}

异常结果:忽略我的 这个异常类和上面的 itException不一样,因为 我临时用的一个异常类 随便娶的名字
在这里插入图片描述

到这里 SpringBoot写出简单的后端接口 就结束咯

好的,下面是 Spring Boot 后端和 Vue.js 前端的示例代码和步骤。 1. 在 Spring Boot 后端,我们可以使用 Spring Security 框架来实现基于 token 的认证和授权。 首先,在 pom.xml 文件中添加 Spring Security 的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 其次,我们需要创建一个类来实现 Spring Security 的配置,例如: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtAuthenticationEntryPoint unauthorizedHandler; @Bean public JwtAuthenticationFilter authenticationTokenFilterBean() throws Exception { return new JwtAuthenticationFilter(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http .cors().and().csrf().disable() .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .anyRequest().authenticated(); // 添加 JWT token 过滤器 http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); } } ``` 在上面的代码中,我们配置了 Spring Security 的一些基本参数,例如:使用 BCryptPasswordEncoder 进行密码加密,实现 UserDetailsService 接口来加载用户信息,配置 JWT token 过滤器等。 2. 在用户登录成功后,生成一个 token 并返回给前端。 在 Spring Boot 后端,我们可以使用 JWT token 来实现认证和授权。在用户登录成功后,我们需要生成一个 JWT token 并返回给前端,例如: ```java // 生成 JWT token String token = Jwts.builder() .setSubject(user.getUsername()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); // 将 token 返回给前端 response.addHeader(HEADER_STRING, TOKEN_PREFIX + token); ``` 在上面的代码中,我们使用 Jwts 类创建一个 JWT token,设置 token 的过期时间和签名算法,并将 token 添加到响应头中返回给前端。其中,HEADER_STRING 和 TOKEN_PREFIX 是我们自定义的常量。 3. 在前端,我们需要在请求头中添加 Authorization 字段,值为 "Bearer " + token。 在 Vue.js 前端,我们可以使用 axios 库来发送 HTTP 请求,并在请求头中添加 Authorization 字段。 首先,我们需要在 main.js 文件中设置 axios 的默认配置,例如: ```javascript import axios from 'axios' axios.defaults.baseURL = 'http://localhost:8080/api' axios.defaults.headers.common['Content-Type'] = 'application/json' // 在请求头中添加 Authorization 字段 axios.interceptors.request.use( config => { const token = localStorage.getItem('token') if (token) { config.headers.common['Authorization'] = 'Bearer ' + token } return config }, error => { return Promise.reject(error) } ) ``` 在上面的代码中,我们设置了 axios 的默认请求 URL 和请求头的 Content-Type。并在 axios 的请求拦截器中,判断本地存储中是否有 token,如果有,则将 token 添加到请求头的 Authorization 字段中。 4. 在后端,我们需要从请求头中解析出 token,然后使用 JWT token 进行验证和授权。 在 Spring Boot 后端,我们需要从请求头中解析出 Authorization 字段,然后使用 JWT token 进行验证和授权。 例如,在 JwtAuthenticationFilter 类中,我们可以重 doFilterInternal 方法,从请求头中解析出 token,并将 token 传递给 JwtTokenUtil 类进行验证和授权,例如: ```java @Component public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String header = request.getHeader(HEADER_STRING); String username = null; String authToken = null; if (header != null && header.startsWith(TOKEN_PREFIX)) { authToken = header.replace(TOKEN_PREFIX, ""); try { username = jwtTokenUtil.getUsernameFromToken(authToken); } catch (IllegalArgumentException e) { logger.error("an error occurred during getting username from token", e); } catch (ExpiredJwtException e) { logger.warn("the token is expired and not valid anymore", e); } } else { logger.warn("couldn't find bearer string, will ignore the header"); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (jwtTokenUtil.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); logger.info("authenticated user " + username + ", setting security context"); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } } ``` 在上面的代码中,我们首先从请求头中解析出 Authorization 字段,然后使用 JwtTokenUtil 类的 getUsernameFromToken 方法解析出 token 中的用户名。接着,我们使用 UserDetailsService 接口加载用户信息,并使用 JwtTokenUtil 类的 validateToken 方法进行 token 的验证和授权。最后,我们将用户信息设置到 Spring Security 的上下文中,以便后续的请求可以进行访问控制。 至此,我们就完成了 Spring Boot 后端和 Vue.js 前端如何在登录后请求头上加上 token 的示例代码和步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值