SpringBoot
概述
- 起步依赖:告诉SpringBoot需要什么功能,它就能够引入需要的库,起步依赖其实就是利用Maven传递依赖解析,把常用的库聚合在一起,组成了几个为特定功能而定制的依赖
- 自动配置:针对很多Spring应用程序常见的功能,Spring提供了自动依赖扫描,并进行自动配置
使用
Spring Initialize(SpringBoot初始化器)
选择需要的功能
- Spring Web
- Mybatis
- MySQL驱动
- Lombok
- Devtools(开发工具)
配置
#配置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
添加Mapper扫描
@SpringBootApplication @MapperScan("com.neu.springbootdemo1.mapper") public class SpringbootDemo1Application { public static void main(String[] args) { SpringApplication.run(SpringbootDemo1Application.class, args); } }
正常编写业务逻辑层和控制器
解决跨域问题
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedHeaders("*") .allowedMethods("GET","POST","PUT","DELETE") .allowCredentials(true); }
配置日志输出
#application.properties logging.level.com.neu.springbootdemo1.mapper=debug
日期格式化
全局设置: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;
@PathVaribale使用
单个路径参数:同名
@GetMapping("{empno}") public Emp getById(@PathVariable Long empno){ return empService.getById(empno); }
单个路径参数:不同名
@GetMapping("{empno1}") public Emp getById(@PathVariable("empno1") Long empno){ return empService.getById(empno); }
多个路径参数
@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); }
全局异常处理
@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>
输入校验
添加依赖
<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>
在实体类,需要验证的字段上添加验证规则注解
/** * 机会来源 */ @NotEmpty(message = "不能为空")//非空且不是空串 private String source; /** * 客户名称 */ @NotEmpty(message = "不能为空") private String custName;
在处理器方法的验证实体前,加验证注解
@PostMapping public boolean create(@Validated/*需要验证*/ @RequestBody SaleChance salechance) { }
使用全局异常处理器处理
@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); } }
常用验证注解
@NotBlank
:确保字段的值不为null或仅包含空格。
前端处理
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) } ) }
分组验证
在实体类中加上分组接口定义
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或空。
拦截器
拦截器主要用于在请求处理之前或之后执行一些操作,例如:身份验证,日志记录,设置响应头
使用
创建一个类,实现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;//放行 } }
注册拦截器
@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");//不拦截哪些请求 } }