SpringBoot入门建站全系列(二)Controller种类及映射处理详解

SpringBoot入门建站全系列(二)Controller种类及映射处理详解

Controller及Mapping其实不属于SpringBoot,SpringBoot只是个大杂烩的容器而已。Controller及Mapping分别在Spring的web和context包中存在着。

本文主要介绍Controller种类及映射处理详解,并针对不同的写法做出示例。

品茗IT-SpringBoot专题-同步发布

品茗IT 提供在线支持:

一键快速构建Spring项目工具

一键快速构建SpringBoot项目工具

一键快速构建SpringCloud项目工具

一站式Springboot项目生成

Mysql一键生成Mybatis注解Mapper

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

一、Controller种类

Controller可以简单分为RestController和Controller。RestController位于Spring的web包中,Controller还是在Spring的context包中。

1.1 Controller

控制器Controller 负责处理由DispatcherServlet 分发的请求。在这个时候,就先不考虑Model、ModelMap和ModelAndView之类的东东,大多数时候根本用不上这三个东东的,Spring提供的方法很简洁的,后面会一一讲解。

@Controller注解的类,会作为访问的路径映射处理,不加特殊处理的返回值会被作为跳转路径。

1.2 RestController

就是@Controller + @ResponseBody 注解的综合,返回值如果是实体,一般作为json数据返回,也可以定制返回值。

二、Mapping种类

RequestMapping是mapping的基本类型,另外还有GetMapping、PostMapping、PutMapping、DeleteMapping、PatchMapping。

2.1 RequestMapping

RequestMapping注解包含以下属性:

name: 别名

value/path: 请求路径

method:请求类型(get/post...)

params: 筛选参数

headers:筛选http header

consumes: 筛选content-type

produces: 返回值的content-type

2.2 GetMapping

等价于@RequestMapping(method = RequestMethod.GET),只处理http的get请求。

2.3 PostMapping

等价于@RequestMapping(method = RequestMethod.POST),只处理http的post请求。

2.4 PutMapping

等价于@RequestMapping(method = RequestMethod.PUT),只处理http的pus请求。

2.5 DeleteMapping

等价于@RequestMapping(method = RequestMethod.DELETE),只处理http的delete请求。

2.6 PatchMapping

等价于@RequestMapping(method = RequestMethod.PATCH),只处理http的patch请求。

2.7 Http不同方法的区别

幂等: 如果一个方法重复执行多次,产生的效果是一样的,那就是幂等的。幂等的意思是如果相同的操作再执行第二遍第三遍,结果还是一样。

RESTful架构应该遵循统一接口原则,统一接口包含了一组受限的预定义的操作,不论什么样的资源,都是通过使用相同的接口进行资源的访问。接口应该使用标准的HTTP方法如GET,PUT和POST,并遵循这些方法的语义。

如果按照HTTP方法的语义来暴露资源,那么接口将会拥有安全性和幂等性的特性,例如GET和HEAD请求都是安全的, 无论请求多少次,都不会改变服务器状态。而GET、HEAD、PUT和DELETE请求都是幂等的,无论对资源操作多少次, 结果总是一样的,后面的请求并不会产生比第一次更多的影响。

RESTful其实还是http,只是定义了一种http请求的规范,我们如果按照这个规范来了,它就是RESTful,如果不按照这个规范来,就不能称之为RESTful。比如,我们在GET请求里做了新建或更新,那它就不是幂等的,事实上,我们一般只是用到了GET和POST请求,PUT、PATCH、DELETE一般都没用上,都是用GET/POST来完成这些操作了,而且没毛病,不过最好是按照RESTful的要求来写,比如elasticsearch就有一套很规范的RESTful Api。

RESTful风格主要用到以下几种:

GET: 获取数据。

POST: POST方法不是幂等的,多次执行,将导致多条相同的条目被创建。

PUT: PUT方法一般会用来更新一个已知资源,幂等。

PATCH:是对PUT方法的补充,用来对已知资源进行局部更新,PATCH是幂等的。

DELETE: 删除操作。

三、Request参数获取方法种类

对请求的参数获取,一般有以下几种方式:

3.1 RequestBody

请求体body作为字符串进行解析,一般是是json或者xml。

3.2 RequestParam

请求参数为键值对,请求方式可以为GET请求的key=xx&value=xx形式,也可以是post的form或x-www-form-urlencoded

3.3 RequestPart

作用类似于RequestParam,但是更强大,复杂的请求,如一个formdata中,包含一个文件和一个json,这时用RequestParam只能解析出文件和一个json字符串,用RequestPart可以解析出文件和实体。

3.4 RequestHeader

可以把Request请求header部分的值绑定到方法的参数上.

3.5 CookieValue

顾名思义,获取cookie值。

3.6 PathVariable

请求路径中的某一部分。

3.7 ModelAttribute

运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中。

运用在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中。

反正没用过。

3.8 RequestAttribute

获取Request作用域下塞入的Attribute属性。

3.9 SessionAttribute

获取Session作用域下塞入的Attribute属性。

四、示例

4.1 请求跳转

默认跳转方式就是forward。

forward和redirect的不同就是,redirect是302,地址栏会变化的,显示最新请求地址。forward不会变。

@Controller
@RequestMapping("/web")
public class HelloWorldWeb {

    @RequestMapping(value = "/hello")
    public String test() {
        return "/index.html";
    }

        @RequestMapping(value = "/hello1")
    public String test1() {
        return "forward:/index.html";
    }
    
    @RequestMapping(value = "/hello2")
    public String test2() {
        return "redirect:/index.html";
    }

}

4.2 请求json/xml,返回json/xml

根据下面的测试情况可以看出,不指定produces,默认都是返回json。不指定consumes和produces的情况下,可以根据请求数据类型做解析,默认都是返回json。

要想返回xml,或支持xml数据,需要添加依赖:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
</dependency>

同名路径允许存在,但请求信息应不同,比如请求数据为json/xml的不同。

@PostMapping和@RequestMapping功能一样,但是@PostMapping只支持POST请求,@RequestMapping不指定请求类型的时候,是可以捕获所有类型的请求。

@RestController
@RequestMapping("/test")
public class HelloWorldRest {

    @RequestMapping(value = "/hello")
    public String test() {
        return "hello,world";
    }
    @RequestMapping(value = "/testJsonx")
    public TestClass hellox(@RequestBody TestClass json) {
        return json;
    }
    @RequestMapping(value = "/testResXml",consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_XML_VALUE)
    public TestClass hello(@RequestBody TestClass json) {
        return json;
    }
    @PostMapping(value = "/test",consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
    public TestClass hello1(@RequestBody TestClass json) {
        return json;
    }
    
    @RequestMapping(value = "/test",consumes=MediaType.APPLICATION_XML_VALUE, produces=MediaType.APPLICATION_XML_VALUE)
    public TestClass hello2(@RequestBody TestClass json) {
        return json;
    }
    @RequestMapping(value = "/testReqJson",consumes=MediaType.APPLICATION_XML_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
    public TestClass hello3(@RequestBody TestClass json) {
        return json;
    }
    
    public static class TestClass{
        String key;
        String value;
        public String getKey() {
            return key;
        }
        public void setKey(String key) {
            this.key = key;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }

}

4.3 跳转和json/xml共存

只需在需要返回json/xml的实体上加上ResponseBody即可。

@Controller
@RequestMapping("/web")
public class HelloWorldWeb {

    @RequestMapping(value = "/hello")
    public String test() {
        return "/index.html";
    }
    
    @RequestMapping(value = "/testJsonx")
    @ResponseBody
    public TestClass hellox(@RequestBody TestClass json) {
        return json;
    }
}

4.4 各种参数获取方式示例

@RestController
@RequestMapping("/all")
public class HelloWorldALLRest {

    /**
     * 测试json请求
     * @param json
     * @return
     */
    @PostMapping(value = "/testJson")
    public TestClass hellox(@RequestBody TestClass json) {
        return json;
    }

    /**
     * 测试获取url参数
     * @param json
     * @return
     */
    @GetMapping(value = "/testBody")
    public TestClass testBody(TestClass json) {
        return json;
    }

    /**
     * 测试获取key-value的参数值
     * @param key
     * @return
     */
    @GetMapping(value = "/testParam")
    public String testParam(@RequestParam("key") String key) {
        return key;
    }

    /**
     * 测试获取路径
     * @param id
     * @return
     */
    @GetMapping(value = "/testParam/{id}")
    public String helloxx(@PathVariable("id") String id) {
        return id;
    }

    /**
     * 测试获取参数
     * @param key
     * @return
     */
    @GetMapping(value = "/testAttr")
    public String testAttr(@ModelAttribute("key") String key) {
        return key;
    }

    /**
     * 测试RequestPart功能
     * @param file
     * @param testClass
     * @return
     */
    @PostMapping(value = "/testPart")
    public TestClass testPart(@RequestPart("file") MultipartFile file, @RequestPart("testClass") TestClass testClass) {
        return testClass;
    }

    /**
     * 测试文件自动填充
     * @param testClassMutiPart
     * @return
     */
    @PostMapping(value = "/testMultipart")
    public TestClassMutiPart testMultipart(TestClassMutiPart testClassMutiPart) {
        return testClassMutiPart;
    }

    /**
     * 测试http头自动填充
     * @param type
     * @return
     */
    @GetMapping(value = "/testHeader")
    public String testHeader(@RequestHeader("Connection") String type) {
        return type;
    }

    /**
     * 测试cookie信息自动填充
     * @param JSESSIONID
     * @return
     */
    @GetMapping(value = "/testCookie")
    public String testCookie(@CookieValue("JSESSIONID") String JSESSIONID) {
        return JSESSIONID;
    }

    /**
     * 测试session的属性值获取
     * @param test
     * @param http
     * @return
     */
    @GetMapping(value = "/testSession")
    public String testSession(@SessionAttribute(value = "test", required = false) String test,
            HttpServletRequest http) {
        http.getSession().setAttribute("test", "asdasd");
        return test;
    }

    /**
     * 测试requst的属性值获取,需要一个跳转到本路径的请求做配置,或者中途对requst做过修改也可以。
     * @param test
     * @return
     */
    @GetMapping(value = "/testReqAttr")
    public String testReqAttr(@RequestAttribute(value = "test", required = false) String test) {
        return test;
    }

    /**
     * 测试用内部类,写成外部类也可以
     * @author fufei
     *
     */
    public static class TestClass {
        String key;
        String value;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
    /**
     * 测试用内部类,写成外部类也可以
     * @author fufei
     *
     */
    public static class TestClassMutiPart {
        String key;
        String value;
        MultipartFile file;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public MultipartFile getFile() {
            return file;
        }

        public void setFile(MultipartFile file) {
            this.file = file;
        }

    }
}
    喜欢这篇文章么,喜欢就[加入我们的Java学习圈(点击加入或下方扫码)](https://jq.qq.com/?_wv=1027&k=52sgH1J)一起讨论SpringBoot技术吧!
    ![品茗IT技术交流群](https://upload-images.jianshu.io/upload_images/15296705-b024ad1fce668926.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servl...
    alexpdh阅读 2,637评论 0 3
  • 对于java中的思考的方向,1必须要看前端的页面,对于前端的页面基本的逻辑,如果能理解最好,不理解也要知道几点。 ...
    神尤鲁道夫阅读 782评论 0 0
  • SpringMVC介绍 Spring web mvc 和Struts2都属于表现层的框架,它是Spring框架的一...
    day_Sunny阅读 734评论 0 0
  • 1、Spring MVC请求流程 (1)初始化:(对DispatcherServlet和ContextLoderL...
    拾壹北阅读 1,941评论 0 12
  • 昏黄的落叶纷纷扬扬地,恣肆在胡说大街上,道路两旁鲜少可见的路灯,歪着脖子畏畏缩缩地吐出微弱的光,光不像光,倒像黑夜...
    吴何阅读 569评论 3 7