spring-webflux两种开发模式,获取不到使用ajax的post提交的数据?

遇到的问题:

1、使用注解式:在js中使用ajax提交post数据name,在controller中使用@RequestBody无法获取到数据。
2、使用函数式:在js中使用ajax提交post数据name,在hander中怎么使用ServerRequest获取到提交的数据name的值呢?

相关尝试:

在注解式中:开始我使用的是@RequestBody String name,但是获取到的值是空的。然后看到网上的有用@RequestBody final Mono<String> name,但是这种也没有获取到值。
在函数式中:我想直接从request中拿,使用方法resolveBodyFromRequest将serverHttpRequest.getBody得到的mono数据转为String.但是仍然拿到的值是空的。

麻烦用过webflux获取到post请求参数的大佬帮忙看看应该怎么获取?

相关代码

// 注解式的请求js
$.ajax({
        type: 'POST',
        url: "/postController/find",
        data: {
            name: "aa",
        },
        dataType: "json",
        success: function (data) {
            console.log(data);
        },error:function () {
            console.log("error");
        }
    });


// 注解式 controller
@RestController
@RequestMapping("/postController")
public class PostController {
    @PostMapping(value = "/find", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Mono<String> find(@RequestBody final String name) {
         // 这里一直拿不到 post过来的name   ???
        System.out.println(name);
        return Mono.justOrEmpt(name);
    }
}


// 函数式的请求js
$.ajax({
        type: 'POST',
        url: "/post/find",
        data: {
            name: "aa",
        },
        dataType: "json",
        success: function (data) {
            console.log(data);
        },error:function () {
            console.log("error");
        }
    });
    
// 函数式 router
    @Configuration
public class PostRouter {
    @Bean
    public RouterFunction<ServerResponse> route(PostHandler handler) {
                return RouterFunctions
                .route(RequestPredicates.POST("/post/find")
                                .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                        handler::find);
    }
}


// 函数式 handle
    @Component
public class PostHandler {

    public Mono<ServerResponse> find(ServerRequest serverRequest){
        // 这里一直拿不到 post过来的data  ???
        String str =readRequestData((ServerHttpRequest)serverRequest);
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
                .body(BodyInserters.fromObject(str));
    }


    public  String readRequestData(ServerHttpRequest serverHttpRequest) {
        String bodyData = "";
        String method = serverHttpRequest.getMethodValue();
        if ("POST".equals(method)) {
            bodyData = resolveBodyFromRequest(serverHttpRequest);
        } else if ("GET".equals(method)) {
            bodyData = getContentByGetRequest(serverHttpRequest);
        }
        return bodyData;
    }

    private String getContentByGetRequest(ServerHttpRequest serverHttpRequest) {
        Map requestQueryParams = serverHttpRequest.getQueryParams().toSingleValueMap();
        StringBuffer s = new StringBuffer();
        String content = "";
        requestQueryParams.forEach((k, v) -> {
            System.out.println(k + "  v:" + v);
            s.append(k + "=" + v + "&");
        });
        if (null != s && !s.equals("")) {
            content = s.toString().substring(0, s.toString().lastIndexOf('&'));
        }
        return content;
    }

    /**
     * * 从Flux<DataBuffer>中获取字符串的方法
     * @return 请求体
     */
    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        System.out.println(body);
        AtomicReference<String> bodyRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyRef.set(charBuffer.toString());
        });
        //获取request body
        return bodyRef.get();
    }
}

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 10.3k
2 个回答

1、函数式:

//1、若是form-data形式提交表单内容,即Content-Type: application/x-www-form-urlencoded;可以通过ServerWebExchange 获取
    $.ajax({
            type: 'POST',
            url: "/post/findform",
            data: {
                name: "aa",
                sex:"n"
            },
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });
        
    // route:
    @Configuration
    public class PostRouter {
    @Bean
    public RouterFunction<ServerResponse> postroute(PostHandler handler) {
                return RouterFunctions.route(RequestPredicates.POST("/post/findform")                          
            .and(RequestPredicates.accept(MediaType.APPLICATION_FORM_URLENCODED)),handler::findform);
        }
    }

    // handle:
   public Mono<ServerResponse> findform(ServerRequest request){
        // 获取form data,在方法中添加ServerWebExchange对象,使用方法getFormData
        ServerWebExchange exchange = request.exchange();
        Mono<MultiValueMap<String, String>> formData =exchange.getFormData();

        return formData.flatMap(map -> {
            System.out.println(map.get("name").get(0));
            System.out.println(map.get("sex").get(0));
            return ServerResponse.ok().contentType(MediaType.APPLICATION_STREAM_JSON)
                    .body(BodyInserters.fromObject(map));
        });
    }
    
 // 2、若是application/json的形式提交表单
    $.ajax({
            type: 'POST',
            url: "/post/findjson",
            data: JSON.stringify({
                "name": "aa"
            }),
            contentType:"application/json",
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });
        
   // route:   
    @Configuration
    public class PostRouter {
        @Bean
        public RouterFunction<ServerResponse> postroute(PostHandler handler) {
                    return RouterFunctions.route(RequestPredicates.POST("/post/findjson")
                    .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),handler::find)
                           
        }
    }

   // handle:直接通过map映射获取
    public Mono<ServerResponse> find(ServerRequest serverRequest){
        Mono<Map> body = serverRequest.bodyToMono(Map.class);
        return body.flatMap(map -> {
            String name = (String) map.get("name");
            System.out.println(name);
            return ServerResponse.ok().contentType(MediaType.APPLICATION_STREAM_JSON)
                    .body(BodyInserters.fromObject(name));
        });
    }

2、注解式
若是get请求,可通过@RequestParam或直接获取

    // get形式提交,下面两种形式都可以直接获取到请求参数
    @GetMapping("/save")
    private Mono<User> save(final User user){
        System.out.println(user.getName());
        return Mono.justOrEmpty(userService.save(user));
    }
    @GetMapping("/save1")
    private Mono<User> save(@RequestParam final String name,@RequestParam final String sex){
        System.out.println(name);
        return Mono.justOrEmpty(userService.save(new User(name,sex)));
    }

若是Post请求,当请格式分别为json或表单格式,json使用@RequestBody获取,form格式通过实体映射或使用ServerWebExchange获取

$.ajax({
            type: 'POST',
            url: "/postController/json",
            data: JSON.stringify({
                "name": "aa",
                "sex":"m"
            }),
            contentType:"application/json",
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });

        $.ajax({
            type: 'POST',
            url: "/postController/jsonS",
            data: JSON.stringify({
                "name": "aa",
                "sex":"m"
            }),
            contentType:"application/json",
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });


        $.ajax({
            type: 'POST',
            url: "/postController/form",
            data: {
                name: "bb",
                sex:"m"
            },
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });


        $.ajax({
            type: 'POST',
            url: "/postController/formS",
            data: {
                name: "bb",
                sex:"m"
            },
            dataType: "json",
            success: function (data) {
                console.log(data);
            },error:function () {
                console.log("error");
            }
        });
        
        
// controller

@RestController
@RequestMapping("/postController")
public class PostController {

    /**
     * 通过@RequestBody获取提交的application/json数据
     * @param
     * @return
     */
    @PostMapping(value = "/json",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Mono<String> json(@RequestBody String user) {
        System.out.println("json:"+user);
        return Mono.just(user);
    }

    /**
     * 通过实体映射获取post的请求体 application/json数据
     * @param user
     * @return
     */
    @PostMapping(value = "/jsonS",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Mono<String> jsonS(@RequestBody User user) {
        System.out.println("jsonS:"+ user);
        return Mono.just(user.toString());

    }

    /**
     * 通过实体映射获取表单数据
     * request:Content-Type: application/x-www-form-urlencoded
     * @param user
     * @return
     */
    @PostMapping(value = "/form", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Mono<User> save(User user) {
        System.out.println("form:"+user);
        return Mono.justOrEmpty(user);
    }

    /**
     * 通过ServerWebExchange获取表单数据
     * request:Content-Type: application/x-www-form-urlencoded
     * @param exchange
     * @return
     */
    @PostMapping(value = "/formS", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Mono<String> save(ServerWebExchange exchange) {
        Mono<MultiValueMap<String, String>> formData =exchange.getFormData();
        return formData.flatMap(map -> {
            System.out.println("formS:"+map);
            return Mono.justOrEmpty(map.toString());
        });
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题