正在连接海拉鲁...

SpringBoot

概述

  1. 起步依赖:告诉SpringBoot需要什么功能,它就能够引入需要的库,起步依赖其实就是利用Maven传递依赖解析,把常用的库聚合在一起,组成了几个为特定功能而定制的依赖
  2. 自动配置:针对很多Spring应用程序常见的功能,Spring提供了自动依赖扫描,并进行自动配置

使用

  1. Spring Initialize(SpringBoot初始化器)

  2. 选择需要的功能

    • Spring Web
    • Mybatis
    • MySQL驱动
    • Lombok
    • Devtools(开发工具)
  3. 配置

    #配置web服务器的端口号
    server.port=8089
    
    #配置数据源参数
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/neusoft?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    spring.datasource.username=root
    spring.datasource.password=root
  4. 添加Mapper扫描

    @SpringBootApplication
    @MapperScan("com.neu.springbootdemo1.mapper")
    public class SpringbootDemo1Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootDemo1Application.class, args);
        }
    
    }
  5. 正常编写业务逻辑层和控制器

  6. 解决跨域问题

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedHeaders("*")
                .allowedMethods("GET","POST","PUT","DELETE")
                .allowCredentials(true);
    }
  7. 配置日志输出

    #application.properties
    
    logging.level.com.neu.springbootdemo1.mapper=debug
  8. 日期格式化

    • 全局设置:application.properties

      spring.jackson.date-format=yyyy-MM-dd
      spring.jackson.time-zone=Asia/Shanghai
    • 单独在实体类属性上设置

      @JsonFormat(pattern = "yyyy-MM-dd",time-zone="Asia/Shanghai")
      private Date hiredate;
  9. @PathVaribale使用

    1. 单个路径参数:同名

      @GetMapping("{empno}")
          public Emp getById(@PathVariable Long empno){
              return empService.getById(empno);
          }
    2. 单个路径参数:不同名

      @GetMapping("{empno1}")
          public Emp getById(@PathVariable("empno1") Long empno){
              return empService.getById(empno);
          }
    3. 多个路径参数

      @GetMapping("{empno}/{ename}")
          public Emp getById(@PathVariable Long empno,@PathVariable String ename){
              System.out.println(ename);
              return empService.getById(empno);
          }
      //http://localhost:8080/emp/7844/name/tom
      @GetMapping("{empno}/name/{ename}")
          public Emp getById(@PathVariable Long empno,@PathVariable String ename){
              System.out.println(ename);
              return empService.getById(empno);
          }
  10. 全局异常处理

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        public ResponseEntity<String> handlerException(Exception e){
            return  new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
        }
        @ExceptionHandler(ArithmeticException.class)
        public ResponseEntity<String> handlerException(ArithmeticException e){
            return  new ResponseEntity<>("算数异常", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    • 前端处理方法

      • 为Axios添加一个响应拦截器,把错误的消息放到Vuex中

        import axios from "axios";
        import store from "../store/index.js";
        const instance = axios.create({
            baseURL:"http://localhost:8080"
        })
        
        instance.interceptors.response.use(
            response=>{
                return response;
            },
            error => {
                store.commit("setError",error.response.data);
        
                return Promise.reject(error);
            }
        );
        
        export default instance

        instance.interceptors.response.use();该方法有两个参数,第一个参数是一个函数,用来处理成功的响应(状态码在2XX的范围内),第二个参数也是一个函数,用于处理错误响应

        Promise.reject(error);是一种常见做法,用于确保拦截器捕获的错误能够继续传播到后续的catch块

      • Vuex

        import {createStore} from "vuex";
        
        const store = createStore({
            state(){
                return{
                    error:null
        
                }
            },mutations:{
                setError(state,error){
                    state.error = error;
                }
            }
        })
        
        export default store
      • 组建中发送异步请求并显示错误消息

        <script setup>
        import store from "../store/index.js";
        import axios from "../axios/index.js";
        axios.get("/emp/7369/tom").then(resp=>{
        
        })
        </script>
        
        <template>
        <h3>{{store.state.error}}</h3>
        </template>
        
        <style scoped>
        
        </style>

输入校验

  1. 添加依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
            
      <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>2.0.1.Final</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>6.2.0.Final</version>
            </dependency>
  2. 在实体类,需要验证的字段上添加验证规则注解

    /**
        * 机会来源
        */
       @NotEmpty(message = "不能为空")//非空且不是空串
       private String source;
       
       /**
        * 客户名称
        */
       @NotEmpty(message = "不能为空")
       private String custName;
  3. 在处理器方法的验证实体前,加验证注解

    @PostMapping
        public boolean create(@Validated/*需要验证*/ @RequestBody SaleChance salechance) {
    
        }
  4. 使用全局异常处理器处理

    @ControllerAdvice
    public class GlobalExceptionHandle {
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<List<ValidationError>> handleValidationExceptions(MethodArgumentNotValidException ex){
            List<ObjectError> errors = ex.getBindingResult().getAllErrors();
            List<ValidationError> list = new ArrayList<>();
            //把所有字段放入list集合中
            for (ObjectError error : errors){
                String field = ((FieldError) error).getField();
                String defaultMessage = error.getDefaultMessage();
                list.add(new ValidationError(field,defaultMessage));
            }
    
            return new ResponseEntity<>(list, HttpStatus.BAD_REQUEST);
        }
    }
  5. 常用验证注解

    • @NotBlank:确保字段的值不为null或仅包含空格。
  6. 前端处理

    const addSaleChance = ()=> {
           saleChance.createId= 1;
           axios.post("/SaleChance",saleChance).then(resp => {
               if (resp.data) {
                   router.push("/main/saleChance")
               }
           }).catch(
               error=>{
                   let str = ''
                   for (let s of error.response.data) {
                       str += s.field+':'+s.message;
                   }
                   alert(str)
               }
           )
       }
  7. 分组验证

    • 在实体类中加上分组接口定义

      public interface Update{};
          public interface Create{};
    • 在字段上的验证规则注解中加入分组

      /**
       * 销售机会编号
       */
      @TableId(value = "Id", type = IdType.AUTO)
      @NotNull(groups = Update.class)
      private Integer id;
           
      /**
       * 机会来源
       */
      @NotEmpty(message = "不能为空",groups = {Create.class,Update.class})//非空且不是空串
      @Length(min = 3)
      private String source;
    • 在处理器的方法上添加分组验证

      @PostMapping
          public boolean create(@Validated(SaleChance.Create.class)/*需要验证*/ @RequestBody SaleChance salechance) {
      
                  return salechanceService.save(salechance);
      
          }
      
        @PutMapping
          public boolean update(@Validated(SaleChance.Update.class) @RequestBody SaleChance salechance) {
              return salechanceService.updateById(salechance);
          }

    字符串验证

    • @Size(min=, max=):确保字段的字符串长度在指定的范围内。
    • @Length(min=, max=):与@Size类似,但专用于字符串。
    • @Pattern(regexp=):确保字段的值符合正则表达式。

    数值验证

    • @Min(value=):确保字段的数值不小于指定的最小值。
    • @Max(value=):确保字段的数值不大于指定的最大值。
    • @Positive:确保字段的数值为正数。
    • @PositiveOrZero:确保字段的数值为正数或零。
    • @Negative:确保字段的数值为负数。
    • @NegativeOrZero:确保字段的数值为负数或零。
    • @DecimalMin(value=):确保字段的数值不小于指定的最小值(可以是小数)。
    • @DecimalMax(value=):确保字段的数值不大于指定的最大值(可以是小数)。

    日期和时间验证

    • @Past:确保日期或时间在当前时间之前。
    • @PastOrPresent:确保日期或时间在当前时间或之前。
    • @Future:确保日期或时间在当前时间之后。
    • @FutureOrPresent:确保日期或时间在当前时间或之后。

    其他验证

    • @Email:验证字段是否是有效的电子邮件地址。
    • @URL:验证字段是否是有效的URL。

    基础验证注解

    • @NotNull:确保字段的值不为null。
    • @NotEmpty:确保字段的值不为null或空。

拦截器

拦截器主要用于在请求处理之前或之后执行一些操作,例如:身份验证,日志记录,设置响应头

使用

  1. 创建一个类,实现HeadlerInterceptor接口,可以选择覆盖该接口的三个方法

    • preHandler():在请求处理之前调用

    • postHandler():在请求处理之后,被调用

    • afterCompletion():在整个请求结束之后调用

      public class LoginInterceptor implements HandlerInterceptor {
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              HttpSession session = request.getSession();
              Object user = session.getAttribute("user");
              if (user == null){
                  response.setStatus(HttpStatus.UNAUTHORIZED.value());
                  return false;//拦截请求
              }
              return true;//放行
          }
      
      }
  2. 注册拦截器

    @SpringBootConfiguration
    public class SpringMVCConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOriginPatterns("*")
                    .allowedMethods("GET","POST","PUT","DELETE")
                    .allowCredentials(true);
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor())
                    .addPathPatterns("/api/**")//拦截那些请求
                    .excludePathPatterns("/api/SysUser/login");//不拦截哪些请求
        }
    }