springboot axios多文件上传 数据分组校验 拦截器Interceptor jwt登录

代码https://github.com/hitgub123/java_vscode/tree/master/springbootvue1/main

获取ajax的post请求的参数需要加@RequestBody,否则取不到
        @PostMapping("update")
        public Result update(@RequestBody User o) 
    获取的ajax multipart/form-data类型的post请求的参数不加,加了反而报错
    
    // 如果设置int page,即使加上@RequestParam(required = false) int page设置可以为空,
    // 如果url是page=&keyword=,会报错""无法转成int
    // 如果url是keyword=,url里不带page参数,会报错null无法转成基本类型,所以需要写成Integer
    // public Result page(@RequestParam(required = false) int page,String keyword) 
    // public Result page(int page,String keyword) 
    @GetMapping("page")
    public Result page(Integer page, String keyword) 

    处理ajax多/单文件上传
        前端html:
            <form>
                文件1<input type='file' name='file11' ref='file1'/><br />
                文件2<input type='file' name='file22' ref='file2'/><br />
            </form>
        前端js:
            let params = new FormData();
            let fileSelectDom1 =this.$refs.file1
            let fileSelectDom2 =this.$refs.file2     
            const config = {
                headers: { "Content-Type": "multipart/form-data"}
            }
            params.append('userfile', fileSelectDom1.files[0])        
            params.append('userfile', fileSelectDom2.files[0])
            params.append('name', this.user.name)
            axios.post("/u/insert", params,config)
            .then(function (res) {
                if (res.data.code == 0) {
                    location.href = "/u/users"
                }
            });
        后端:
            @PostMapping("insert")     
            //@RequestPart里的value需要和FormData的文件数组的key对应
            public Result insert(@Nullable @RequestPart("userfile") MultipartFile[] uploadFiles, User o) {
                for (MultipartFile f : uploadFiles) {
                    try {
                        String modulePath = FileAndPathUtil.getModulePath() + uploadPath;
                        String extension = FilenameUtils.getExtension(f.getOriginalFilename());
                        String filename = FileAndPathUtil.getRandomFilename()+ "." + extension;
                        File f1 = new File(modulePath, filename);
                        f.transferTo(f1);   
                    } catch (IllegalStateException | IOException e) {
                        e.printStackTrace();
                    }
                }
            }


数据校验(仅对绑定到对象的数据):
        1,对被绑定的对象加上各种校验规则,参考slq\me\module1\entity\User.java,修改后可能要mvn clean install后才生效
        2,在controoler里,要校验的方法的该对象前加上@Validated,参考slq\me\module1\controller\UserController.java
        3,对校验异常进行处理,有两种方法:
            a,全局异常处理,参考slq\me\module1\controller\GlobalExceptionHandler.java
                a-1,数据校验失败报错BindException,看BindException的处理方法即可
                a-2,BindException的处理方法在接收到BindException后返回json对象,controller内部的代码不会被执行
                a-3,UserController.java里insert方法使用的是全局异常处理,注意方法形参里不能含有BindingResult,
                否则不会被GlobalExceptionHandler处理
                a-4,前端拿到BindException后返回json对象后,分字段显示对应的所有错误,参考user.html
            b,单个异常处理,slq\me\module1\controller\UserController.java的upate方法
                b-1,update方法形参里必须含有BindingResult,
                result.hasErrors()判断是否也error,result.getAllErrors()获取所有error
                b-2,也返回json对象,后续前端的处理后全局异常处理一模一样
            不管用哪个异常处理,接收异常后必须return,否则之后的controller代码会继续执行
    
    数据分组校验(往db插入或更新user时需要在form输入很多字段,login时form只填写user和pass,校验规则不同,所以需要进行分组校验):
        1,创建groups的空接口,如public class ValidationGroups {public interface Required {}}
        2,在有校验差异需求的规则里加上groups,如 @Email(message = "需要邮箱格式", groups = {ValidationGroups.Required.class })
        3,在controller里@Validated注解里加groups,
            如public Result update(@Validated(ValidationGroups.Required.class) @RequestBody User o) ,此时@Email对此User生效。
        4,一个组的校验规则,对其他组不生效
        5,如果某个校验规则没有groups属性,那么它对controller里@Validated含有groups属性的表单都不生效
        6,如果某个controller里@Validated不含groups,那么@Validated含有groups属性的校验规则对它都不生效


拦截器:
    1,配置springboot扫描拦截器,参考slq\me\module1\config\WebConfig.java
        注意:要写addPathPatterns("/**"),不要写addPathPatterns("/*"),否则/u/delete这样的url不会被拦截
    2,配置拦截器,参考slq\me\module1\interceptor\LoginInterceptor.java
拦截器实现使用session登录:
    1,在LoginInterceptor.java的preHandle里使用preHandleInnerWithSession方法,
    检查被拦截的请求的session里是否有user,如果没有就跳转login
    2,login登录成功后,往session里设置user
    3,访问任意页面session里都会携带user
拦截器实现使用jwt登录:
    1,pom引用com.auth0.java-jwt
    2,使用jwt生成/校验token,检查是否快过期,参考slq\me\module1\util\JWTUtils.java
    3,在LoginInterceptor.java的preHandle里使用preHandleInnerWithJWT方法,
    检查被拦截的请求的cookie里是否有token,是否过期,能否通过检验,如果不能就跳转login
    4,login登录成功后,往cookie里设置token,注意设置cookie路径为根路径("/"5,访问任意页面cookie里都会自动携带token
    网上参考别人的方法是把token放在响应头里返回前端,之后保存在localstorage里,
    访问其他页面时读取localstorage再手动加到请求头,后台的拦截器从请求头读取token进行校验。
    自己有些页面时js的location.href跳转,不知道怎么设置请求头,所以把token放在cookie里。
jwt简介:
	将生成的token直接base64解码,得到如下字符串
	  {"typ":"JWT","alg":"HS512"}{"sub":"87","exp":1664013689}**后面的乱码**
	第一部分是header,第二部分是Payload,第三部分是Signature,对前两部分的签名,防止数据篡改。
	Payload加入了要加密的信息,后端用自己的密匙对header+Payload加密后,生成上面的token交给服务器。
	服务器把token给后端,后端解密,核对是否与header+Payload匹配。
	所以token不用保存在服务器端。保存在客户端,不管服务器重启也不失效(只要token没过期且密钥不变)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值