RestController详解(上)

最近在网易云课堂上看一些视频,给大家推荐一个讲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中的流保存⽂件了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容