美文网首页
RestController详解(上)

RestController详解(上)

作者: 陆小愤 | 来源:发表于2018-11-10 10:04 被阅读0次

    最近在网易云课堂上看一些视频,给大家推荐一个讲Spring Boot的视频https://study.163.com/course/courseMain.htm?courseId=1005213034,老师讲的很不错。在学习的时候我也会做一些笔记,方便日后巩固。
    对这个系列感兴趣的可以看我之前写的博客:

    开始一个最简单的RESTful API项目

    在程序中记录日志

    • 有两种方法,分别依赖两个包,他们是Commons-logging和SLF4j。使用方法:

      private static final Log log = LogFactory.getLog(Xxxx.class);
      private static final Logger logger = LoggerFactory.getLogger(Xxxx.class);
      
    • 日志级别:可以选择某个级别及以上的日志进行记录,这点比单纯的用System.out.print()要好。TRACE和FATAL是Commons-logging包独有的

      TRACE < DEBUG < INFO < WARN < ERROR < FATAL

    • 需要在application.yml中进行配置,下面是参考:

      logging:
      file: target/app.log
      level:
        ROOT: WARN
        cn.luxiaofen: TRACE  #改成对应的包的名字
      

    commons-logging

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    public class SampleClass {
        //这是一个不变的对象。修饰为static是因为允许静态方法调用
        private static final Log log = LogFactory.getLog(SampleClass.class);
        
        public void print(String name) {
            if(log.isTraceEnabled()) {
                log.trace("传入参数是: " + name);
            }
            
            try {
                // do something
            }catch(Exception e) {
                if(log.isErrorEnabled()) {
                    log.error("出错啦", e);
                }
            }
        }
    
        … …
    }
    

    在getAll()方法中测试

    课时6.1

    启动Spring Boot后,在浏览器中打开http://localhost:8080/tvseries

    课时6.2

    注意这个下载的项目设置的编码形式为UTF-8,不支持其他编码形式。如需修改就去.pom文件里改。

    使用POSTMAN来测试API

    请求方式不止GET这一种,如果是其他的如POST,DELETE,PUT这种就不能单纯的用浏览器去测试。这时候就需要一些工具来帮助我们。一个是命令行工具UNIX系统自带的curl,因为我的系统是WIN10,所以接下来我主要会用到的是一个带界面的API测试工具POSTMAN

    POSTMAN

    详解RestController中获取请求的各种数据

    请求方式的POST,GET,PUT,DELETE形式分别对应着C(create),R(retrieve),U(update),D(delete)。下面来看看这些方法的实现。

    GET方法

    1. 首先对代码做一些重构,这是为了方便将各种TvSeriesDto对象放入list:


      课时8.1
    2. 添加一个从list中取得一个TvSeriesDto对象的方法


      课时8.2
    3. 启动Spring Boot后,在POSTMAN中测试


      课时8.3

    POST方法

    1. 在Controller中新增一个POST方法


      课时8.4
    2. 为了方便测试需要重写TvSeriesDto的toString()方法

      @Override
      public String toString() {
          return this.getClass().getName()+"{id:"+id+",name:"+name+"}";
      }
      
    3. 在POSTMAN中测试


      课时8.5
    4. 看一下日志

      传进来的参数是:cn.luxiaofen.test.TvSeriesDto{id:0,name:可爱的湖南人}
      

    PUT方法

    1. 在Controller中新增PUT方法
      @PutMapping("/{id}")
      public TvSeriesDto updateOne(@PathVariable int id,@RequestBody TvSeriesDto tvSeriesDto) {
          if (log.isTraceEnabled()) {
              log.trace("update one "+id);
          }
          if (id==1 || id ==2) {
              tvSeriesDto.setName("NanNan");//更新数据
              return tvSeriesDto;
          }else
              throw new ResourceNotFoundException();
      }
      
    2. 在POSTMAN中测试


      课时8.6

    DELETE方法

    1. 新增DELETE方法

      /**
       *
       * @param id 在url中的id
       * @param request 这个参数不用加注解,spring会自动传进来
       * @param deleteReason 删除的理由,required = false表示不是必需的
       * @return 删除的信息,储存在MAP中
       */
      @DeleteMapping("/{id}")
      public Map<String,String> deleteOne(@PathVariable int id, HttpServletRequest request,
                                          @RequestParam(name = "deleteReason",required = false)String deleteReason) throws Exception {
          if(log.isTraceEnabled()) {
              log.trace("delete one "+id);
          }
      
      
          Map<String,String> result = new HashMap<>();
          if (id == 2) {
              // TODO:执行删除的代码
              result.put("message","#2被"+request.getRemoteAddr()+"删除,原因("+deleteReason+")");
          }else if (id == 1) {
              throw new RuntimeException("LoveManchester不能被删除");
          }else
              throw new ResourceNotFoundException();
      
          return result;
      }
      
    2. 在POSTMAN中测试,注意这里request parameter不能使用中文,会引起编码错误


      课时8.7
    3. 查看日志

      2018-11-10 09:46:15.693 DEBUG 8300 --- [nio-8080-exec-1] cn.luxiaofen.test.TvSeriesController     : delete one 2
      

    RestController中的上传和下载示例

    上传文件

    1. 为了使用org.apache.commons.io包下的IOUtils,需要在MAVEN中引入这个包,在.pom文件中加入:

      <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
      </dependency>
      
    2. 在Controller中新增文件上传方法

      /**
       * 这是一个上传照片的方法
       * consumes表示传入的参数,这里采用的是MULTIPART_FORM_DATA_VALUE类型
       * @param photo 上传的照片
       */
      @PostMapping(value = "/photo",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
      public void addPhoto(@RequestParam("photo")MultipartFile photo) throws IOException {
          if (log.isTraceEnabled()) {
              log.trace("接收到文件"+photo.getOriginalFilename());
          }
      
          //保存文件到指定目录下
          FileOutputStream fos = new FileOutputStream("target/"+photo.getOriginalFilename());
          //注意这里引用的包是org.apache.commons.io.IOUtils
          IOUtils.copy(photo.getInputStream(),fos);
          fos.close();
      }
      
    3. 在POSTMAN中测试


      课时9.1
    4. 看一下IDEA中的结果:

      2018-11-10 11:18:31.941 DEBUG 3420 --- [nio-8080-exec-1] cn.luxiaofen.test.TvSeriesController     : 接收到文件nannan.jpg
      
      课时9.2

    下载文件

    1. 在src/main/resources目录下储存一张图片,命名为icon.jpg
    2. 增加下载文件的方法
      /**
       * 这是一个返回数据的方法
       * produces参数表示生成的文件格式,这里使用的是jpg文件格式
       * @return 图片
       */
      @GetMapping(value = "/icon",produces = MediaType.IMAGE_JPEG_VALUE)
      public byte[] getIcon() throws IOException {
          if (log.isTraceEnabled()) {
              log.trace("getIcon() is invoked");
          }
      
          //需要在指定目录下预先放好文件
          String iconFile = "src/main/resources/icon.jpg";
          InputStream inputStream = new FileInputStream(iconFile);
          return IOUtils.toByteArray(inputStream);
      }
      
    3. 浏览器中打开http://localhost:8080/tvseries/icon,看到浏览器中已经返回了我们预先储存的图片
      课时9.3
    4. 在IDEA中查看日志
      2018-11-10 12:05:26.622 DEBUG 6412 --- [nio-8080-exec-2] cn.luxiaofen.test.TvSeriesController     : getIcon() is invoked
      

    在RestController中获取各种相关信息的⽅法

    • URL中路径的⼀部分:

      ⾸先需要在RequestMapping做映射,之后在⽅法中可以通过注解使⽤映射的变量

      @GetMapping("/{id}")
      public TvSeries getOne(@PathVariable("id") Integer id){}
      

      可以写多个: @PutMapping("/{id}/characters/{cId}")

      还可以使⽤正则表达式限制类型(不符合要求会返回4xx的错误信息,表示请求参数
      有问题)此例⼦表示id必须是数字:
      @PutMapping("/{id:\d+}")

    • POST⽅法传递过来的JSON:

      给参数前增加@RequestBody注解, Spring会⾃动把POST的Request Body部分的JSON转成⽅法声明的类。如果转化失败会返回4xx错误,表示请求参数有问题。

      public Object updateOne(@RequestBody TvSeries tvSeries)
      
    • POST⽅法传递的是表单数据:

      ⾸先需要声明传⼊的是application/x-www-form-urlencoded的格式,可在RequestMapping增加consumes参数:

      @PostMapping(value="/tvseries",consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
      

      在⽅法上增加参数,参数使⽤@RequestParam注解即可:

      public Object insert(@RequestParam(value="name",required=false) String name) {}
      

      凡是可以通过HttpServletRequest.getParameter(String)⽅法取到的值,
      包含表单提交的、 QueryString附带的,都可以使⽤@RequestParam注解得到
      默认是request=true。

    • QueryString的参数:

      使⽤@RequestParam注解,通过参数获得,例如:

      public Object query(@RequestParam(value="page",required=false) Integer page)
      
    • Request Header:

      可以使⽤@Requestheader注解获取Request的头信息,例如:

      public ResultJSON editCompany(@RequestHeader("user-agent")String userAgent) {}
      

      注意: @RequestHeader后⾯的头名字不区分⼤⼩写,但RequestParam,PathVariable等是区分的。
      如果RequestHeader后⾯不写参数,会⽤后⾯的变量名替代

    • 获取cookie值:

      使⽤@CookieValue注解,和其他类似,除⾮为了兼容⽼现有客户端,新API⾥不建议⽤cookie。

    • 获取当前的RequestResponse:

      直接写参数,例如:

      public Object doSomething(HttpServletRequest request,HttpServletResponse response){}
      
    • 获取当前⽤户:

      直接在⽅法上增加参数,类型为:org.springframework.security.core.Authentication,例如:

      public TvSeries deleteOne(Authentication auth)
      

      参数auth内会存储有当前的⽤户信息。

    • ⽂件上传:

      ⾸先要设置consumes为multipart/form-data:

      @PostMapping(value="/files",consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
      

      在⽅法中写参数:

      public Map<String, Object> uploadFile(@RequestParam("file")MultipartFile file)
      

      在⽅法中可以直接使⽤MultipartFile中的流保存⽂件了。

    相关文章

      网友评论

          本文标题:RestController详解(上)

          本文链接:https://www.haomeiwen.com/subject/evqzxqtx.html