zoukankan      html  css  js  c++  java
  • webFlux 学习(三)

    入门crud

    这次我们来学习webflux入门CRUD

    首先我们需要安装一个mondodb 在这里我就不说怎么安装了.

    配置文件如下

    spring.data.mongodb.uri=mongodb://xxxxx:27017/webflux

    领域对象

    /**
     * @Created by xiaodao
     */
    @Document(collection = "user")
    @Data
    public class User {
    
    
        @Id
        private String id;
    
        @NotBlank
        private String name;
        @Range(min = 10,max = 100)
        private Integer age;
    }

    repository

    /**
     * @Created by xiaodao
     */
    @Repository
    public interface UserRepository extends ReactiveMongoRepository<User,String> {
    
        Flux<User> findByAgeBetween(int start, int end );
    
    
        @Query("{'age':{$gte:?0,$lte:?1}}")
        Flux<User> oldUser(int start, int end );
    }

     Controller

    package com.xiaodao.webflux.controller;
    
    import com.xiaodao.webflux.pojo.User;
    import com.xiaodao.webflux.repository.UserRepository;
    import com.xiaodao.webflux.utils.CheckUtil;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import javax.validation.Valid;
    import java.awt.*;
    
    /**
     * @Created by xiaodao
     */
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        private final UserRepository userRepository;
    
        public UserController(UserRepository userRepository) {
            this.userRepository = userRepository;
        }
    
        /**
         * 以数组形式一次性返回数据
         * @return
         */
        @GetMapping("/")
        public Flux<User> getAll(){
            return userRepository.findAll();
        }
    
        /**
         * sse 形式多次返回方式
         * @return
         */
        @GetMapping(value = "/stream/all",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
        public Flux<User> getStreamAll(){
            return userRepository.findAll();
        }
    
        /**
         * 新增
         * @param user
         * @return
         */
        @PostMapping("/")
        public Mono<User> createUser(@Valid @RequestBody User user){
            CheckUtil.checkName(user.getName());
            return this.userRepository.save(user);
    
        }
    
        /**
         * 返回状态码 存在返回200 不存在返回404
         * @param id
         * @return
         */
        @DeleteMapping("/{id}")
        public Mono<ResponseEntity<Void>> delete(@PathVariable String id){
    
            //没有返回值.不知道数据有没有
    //        this.userRepository.deleteById(id);
    
           return this.userRepository.findById(id)
                    //当需要操作数据,并返回一个mono这时候用flatMap
                    //当不操作数据,不返回数据,只是转换数据使用map
                    .flatMap(user->this.userRepository.delete(user)
                    .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK))))
                    .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    
        }
    
        /**
         * 修改
         * 存在的时候返回200 和修改后的数据,不存在的时候返回404
         * @param id
         * @param user
         * @return
         */
        @PutMapping("/{id}")
        public Mono<ResponseEntity<User>> updateUser( @PathVariable String id ,@RequestBody @Valid User user){
           return this.userRepository.findById(id).flatMap(u->{
                user.setId(id);
              return   this.userRepository.save(user);
            }).map(u->new ResponseEntity<User>(u,HttpStatus.OK))
                    .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
        }
    
    
        /**
         * 根据id查找一个值
         * @param id
         * @return
         */
        @GetMapping("/{id}")
        public Mono<ResponseEntity<User>> findById(@PathVariable String id ){
            return  this.userRepository.findById(id).map(u->new ResponseEntity<User>(u,HttpStatus.OK))
                    .defaultIfEmpty(new ResponseEntity<User>(HttpStatus.NOT_FOUND));
        }
    
    
        /**
         * 根据年龄段查找
         * @param start
         * @param end
         * @return
         */
        @GetMapping("/age/{start}/{end}")
        public Flux<User> findByage(@PathVariable int start , @PathVariable int end){
            return this.userRepository.findByAgeBetween( start,end  );
        }
    
        /**
         * 流式
         * @param start
         * @param end
         * @return
         */
        @GetMapping(value = "/ageStream/{start}/{end}",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
        public Flux<User> findByageStream(@PathVariable int start , @PathVariable int end){
            return this.userRepository.findByAgeBetween( start,end  );
        }
    
    
        @GetMapping("/findoldUser/{start}/{end}")
        public Flux<User> findoldUser(@PathVariable int start , @PathVariable int end){
            return this.userRepository.oldUser( start,end  );
        }
    }

    上面的代码加了一点hibernate的校验和自己的校验

    controllerAdvice

    /**
     * 异常处理
     * @Created by xiaodao
     */
    @ControllerAdvice
    public class CheckAdvice {
    
    
    
        @ExceptionHandler(WebExchangeBindException.class)
        public ResponseEntity<String> handleBindException(WebExchangeBindException e ){
            return new ResponseEntity<String>(tostr(e), HttpStatus.BAD_REQUEST);
        }
    
        /**
         * 校验异常转换为字符串
         * @param e
         * @return
         */
        private String tostr(WebExchangeBindException e) {
    
         return    e.getFieldErrors().stream()
                    .map(a->a.getField()+" : "+ a.getDefaultMessage())
                    .reduce("",(s1,s2)-> s1+ "
    "+s2);
    
        }
    
        @ExceptionHandler(CheckException.class)
        public ResponseEntity<String> handleCheckException(
                CheckException e) {
            return new ResponseEntity<String>(toStr(e), HttpStatus.BAD_REQUEST);
        }
    
        private String toStr(CheckException e) {
            return e.getFieldName() + ": 错误的值 " + e.getFieldValue();
        }
    
    }

    这里注意的一点就是@valid需要加载具体的类上,不然不会生效

    这里还有我们的自己定义的校验名字的方法,我也贴到这里

    /**
     * @Created by xiaodao
     */
    public class CheckUtil {
    
        private static final String[] INVALID_NAMES={"admin","role"};
    
    
        public static void checkName(String value){
    
            Stream.of(INVALID_NAMES).filter(name -> name.equalsIgnoreCase(value))
                    .findAny().ifPresent(name->{throw new CheckException("name",value);});
        }
    
    
    }

     RouterFucntion

    routerFunction 是webflux的另一种开始模式

    webflux 可以运行在servlet3.1 和netty上 需要把

    httpServletRequest - >serverRequest

    httpServletResponse - >serverResponse 

    使用routerFunction开发过程需要  

    1.HandlerFunction  就是输入servletRequest 返回的是 serverResponse

    2.routerFunction (将请求url和HandleFunction对应起来)

    3.然后才是你自己定义的userhandle处理

    4.server 处理

    代码如下

    package com.xiaodao.webflux.handle;
    
    import com.xiaodao.webflux.pojo.User;
    import com.xiaodao.webflux.repository.UserRepository;
    import com.xiaodao.webflux.utils.CheckUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Component;
    import org.springframework.web.reactive.function.server.ServerRequest;
    import org.springframework.web.reactive.function.server.ServerResponse;
    import reactor.core.publisher.Mono;
    
    /**
     * @Created by xiaodao
     */
    
    @Component
    public class UserHandle {
    
        @Autowired
        private UserRepository userRepository;
    
        /***
         * 获取所有用户
         * @param request
         * @return
         */
        public Mono<ServerResponse> getAllUser(ServerRequest request){
            return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8)
                    .body(userRepository.findAll(), User.class);
        }
    
    
        /**
         * 创建用户
         * @param request
         * @return
         */
        public Mono<ServerResponse> createUser(ServerRequest request) {
            Mono<User> userMono = request.bodyToMono(User.class);
    
            return userMono.flatMap(u -> {
                        CheckUtil.checkName(u.getName());
                        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8)
                                .body(userRepository.save(u), User.class);
                    }
    
            );
        }
        /**
         * 删除
         * @param request
         * @return
         */
        public Mono<ServerResponse> deleteUser(ServerRequest request){
            String id = request.pathVariable("id");
            return userRepository.findById(id).flatMap(user->userRepository.delete(user))
                    .then(ServerResponse.ok().build())
                    .switchIfEmpty(ServerResponse.notFound().build());
        }
    
    }

    routerFunction 

    /**
     * @Created by xiaodao
     */
    @Configuration
    public class AllRouter {
    
        @Bean
        RouterFunction<ServerResponse> userRouter(UserHandle userHandle){
    
            return RouterFunctions.nest(
                    RequestPredicates.path("/user"),
                    //查找所有用户
                    RouterFunctions.route(RequestPredicates.GET("/"),userHandle::getAllUser)
                            //创建用户
                    .andRoute(RequestPredicates.POST("/")
                            .and(RequestPredicates.accept(MediaType.APPLICATION_JSON_UTF8)
                   ) ,userHandle::createUser)
                            //删除用户
                    .andRoute(RequestPredicates.DELETE("/{id}"),userHandle::deleteUser)
            );
        }
    }
    /**
     * @Created by xiaodao
     */
    @Component
    @Order(-2)
    public class ExceptionHandle implements WebExceptionHandler {
        @Override
        public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
            ServerHttpResponse response = exchange.getResponse();
            //设置响应头400
            response.setStatusCode(HttpStatus.BAD_REQUEST);
            //设置返回类型
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
    
            //异常信息
            String errorMsg = tostr(throwable);
    
    
            DataBuffer wrap = response.bufferFactory().wrap(errorMsg.getBytes());
            return response.writeWith(Mono.just(wrap));
        }
    
        private String tostr(Throwable ex) {
            //已知异常
            if(ex instanceof CheckException){
    
                CheckException check = (CheckException)ex;
                return check.getFieldName() +"  invalid value  "+ check.getFieldValue();
    
                //未知异常需要打印堆栈方便定位
            }else{
                ex.printStackTrace();
                return ex.toString();
            }
        }
    }

    这个时候我来就可以去访问.

    localhost:8080/user

  • 相关阅读:
    .net中数据库事务机制
    位图排序
    JavaScript实现手动画线
    CSS 样式
    我的知识计划
    开发民政信息采集工具有感
    系统小技巧
    C++的学习笔记
    Android核心服务学习笔记
    突然想到的“社会发展历程”
  • 原文地址:https://www.cnblogs.com/bj-xiaodao/p/11051038.html
Copyright © 2011-2022 走看看