• SpringBoot——关于Controller的简单使用


    映射注解

    @Controller和@RestController

    这两个都是用来标注类为controller的,不同之处在于@Controller标记的类默认返回视图,@RestController标记的类返回的是数据(字符串,json数据等等),之前为了达到@RestController的效果,需要在@Controller标记的类中使用@ResponseBody标签(@RestController = @Controller + @ResponseBody),@ResponseBody可以加在类或者方法上(指定全类或者某个方法返回数据);

    @RequestMapping()以及细化的@xxxxxMapping

    @RequestMapping()用于指定请求路径的映射,可以使用在类或者方法上(控制在整个类的作用域或者方法的作用域,例如可以为类中的方法设置一个总的父级路径);

    @RequestMapping()注解可设置的参数:

    • consumes:设定Content-Type缩小请求范围,只处理指定content-type的请求,可以直接使用字符串或者数组或者MediaType定义好的类型,也支持“*”通配符匹配(例如:consumes = "text/plain"、consumes = {"text/plain", "application/*"}、consumes = MediaType.IMAGE_JPEG_VALUE),可以使用“!”进行否定指定该类型之外的(consumes = "!text/plain");该参数可以用在类和方法上,并且方法上的会覆盖类上的设定;
    • headers:设定header缩小请求范围,可以指定header(headers = "My-Header=myValue"),也可以用“!=”指定排除(headers = "My-Header!=myValue"),也可以不设置值指定必须拥有该名称的header(headers = "My-Header"),或者使用“!”指定不能有该名称的header(headers = "!My-Header"),也支持“*”通配符(headers = "content-type=text/*"),也可以配置多个header(headers = {"myheader1=abc", "!myheader2"});该参数可以用在类和方法上,当用在类上时,所有方法都继承该参数,即在执行方法前先验证类上的header限制;
    • method:设定http请求的方法缩小请求范围,支持:GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE;该参数可以用在类和方法上,当用在类上时,所有方法都继承该参数,执行方法前先验证类上的method;
    • name:为映射分配一个名字;该参数可以用在类和方法上,当类和方法都使用name时,组合名字是使用“#”连接起来的;
    • params:设定请求的参数缩小请求范围,参数跟headers的设置类似,也支持“a=1”、“a!=1”、“a”、“!a”;该参数可以用在类和方法上,当用在类上时,所有方法继承该参数,在执行方法前先验证类上的params限制;
    • path:映射路径(等同value参数),支持Ant-style格式通配符(?匹配任何单字符、*匹配0或任意数量的字符、**匹配0或任意数量的目录),在方法上也支持相对类中path的路径,也支持使用占位符("/{my_path}"),支持配置多个路径(path = {"/abc", "/def"});该参数可以用在类和方法上,当用在类上时,所有方法继承该path;没有显式配置路径映射方法的都会映射到空路径;
    • produces:设置媒体类型,可以设置多个,其中一个必须配合请求里的可接受的媒体类型,通常是从Accept标头里提取的;如果媒体类型带有参数(像“charset=UTF-8”)并且请求里的媒体类型也带有参数,则参数的值必须匹配;也可以使用“!”匹配指定媒体类型之外的其他所有Accept配置类型的请求;该参数可以用在类和方法上,并且方法级的会覆盖掉类级的;
    • value:path的别名,@RequestMapping("/test")等同于@RequestMapping(path = "/test");

    还有一些特定方法的专用的映射:@GetMapping、@PostMapping、@DeleteMapping、@PatchMapping、@PutMapping,只接受指定method的请求,相当于@RequestMapping加method参数,其他的参数跟@RequestMapping的基本一致;

    另外要注意路径映射的唯一性,例如:不能出现两个完全一样的@PostMapping("/abc"),但可以出现@RequestMapping("/abc")和@PostMapping("/abc")并存的情况,这时"/abc"的post请求被分到第二个上,其他method的请求分到第一个;@PostMapping(value = "/aaa", params = "a")和@PostMapping(value = "/aaa", params = "b")也可以共存,带参数a的执行第一个,带参数b的执行第二个,但是如果post请求里既有a又有b参数则会造成歧义返回错误;很多情况下启动时不会报异常,只在请求的时候异常;

    参数注解

    controller方法的参数有使用注解和不使用注解两种方式,可用的注解:

    @RequestParam

    该注解可以接收请求地址里?后面用&连接的参数,可以接收post的form表单数据(通常content-type为multipart/form-data),也可以接收浏览器原生form表单数据(content-type为application/x-www-form-urlencoded,数据按照key=val&key=val编码,并进行URL转码);

    @RequestParam可设置的参数:

    • defaultValue:当未提供参数或者参数为空时,设置一个默认值,当提供默认值时会默认required为false;
    • name:给参数绑定一个名字;(等同value)
    • required:设置参数是否是必须,默认true(不传递参数会异常);如果参数非必须可设置为false,或者提供一个defaultValue;
    • value:name的别名;

    该注解通常可以省略,通常用于参数名不一致、需要默认值、必传的时候;

    参数可以一个一个独立的写,也可以封装到一个Bean对象里(get和set方法),另外bean也可以跟独立的参数同时支持,bean里的参数名也可以跟独立的参数同名,都能读取到值,也可以同名不同类型(例如bean里a的是int,独立的a参数也可以是String);如果是内部类的bean主要是static的;

    关于参数类型,一般用String接收,有时也可以用数值,用数值时要确保传来的值能转换成数值(传来的都是String,会自动转对应数值类型),对于String类型的参数会将能读取到的3处的值合并在一起,中间用逗号隔开,对于数值类型只会读取最优先的一个;三种数据来源的读取优先顺序:form-data > 请求地址里?后的 > x-www-form-urlencoded;

    @RequestParam的form表单也可以用来接收文件,利用MultipartFile类可以接收文件;

    接收文件的Demo:

    1. @RequestMapping("/aaa")
    2. public String a(@RequestParam MultipartFile myfile) {
    3. String filename = myfile.getOriginalFilename();
    4. System.out.println(filename);
    5. File dest = new File(filename);
    6. try {
    7. Files.write(dest.toPath(), myfile.getBytes());
    8. } catch (IOException e) {
    9. e.printStackTrace();
    10. }
    11. return "ABC";
    12. }

    测试结果:

    @RequestBody

    通常用于接收post请求体的数据,一般是json数据,也可以是字符串或数值;

    @RequestBody可设置的参数:

    • required:设置body内容是否是必须,默认true(不传递body会异常);如果想要body为空时传递null,则设该值为false;

    @RequestBody只能有一个,通常接收json数据使用自定义类,将各个字段放到一个类中,字段属性使用@JsonProperty注释或者使用getter()setter(),如果是内部类也需要static class;

    关于@JsonProperty可设置的项:

    • access:可选属性,用于改变访问器(getter)和构造器(构造函数里、setter)的可见性,或者由其他私有或者其他可见性控制(例如private getter);默认Access.AUTO完全由其他可见性和注解控制;可用的值:Access.AUTO、Access.READ_ONLY、Access.READ_WRITE、Access.WRITE_ONLY;
    • defaultValue:设置默认值;
    • index:设置属性的数值索引,使用二进制表示,可能用于其他语言或者工具;
    • required:设置属性是否必须,默认false,只用于创建属性的时候验证,对于其他setter等方式不验证;
    • value:设置属性的名字,默认值为“”,将尝试使用注释的属性名;(构造方法没有默认属性名可用,空字符串是非法的值)

    @PathVariable

    用于获取url地址里的参数,跟@RequestMapping设置的路径里的{}搭配使用;

    @PathVarialbe可设置的参数:

    • name:为路径参数绑定一个名字(对应路径url里{}里的名字);(等同value)
    • required:设置路径参数是否必须,默认true(不传递路径参数会异常);如果希望没有路径参数时传递null则可以设置为false;
    • value:name别名;

    @RequestHeader

    用于获取请求的header;

    @RequestHeader可设置的参数:

    • defaultValue:设置默认header的值,设置会将required默认为false;
    • name:设置header的名字;
    • required:设置header是否必须,默认true;
    • value:name别名;

    @CookieValue

    用于获取cookie值;

    @CookieValue可设置的参数:

    • defaultValue:设置默认cookie值,设置会将required默认为false;
    • name:设定绑定cookie的名字;
    • required:设置cookie是否必须,默认true;
    • value:name别名;

    另外,注解可以一同使用,用来同时读取请求地址上的路径参数、地址?后的参数、消息体的内容、header、cookie等等;

    关于返回值

    可以返回任意数据,也可以不返回数据;可以返回字符串,数值,集合,对象等可序列化的值,复杂类型的返回值会被转换成json数据返回;

    返回自定义的对象,类里的属性需要至少有一个是可公开可访问的,没有可访问属性会报错;需要序列化返回给调用接口的属性可以使用public修饰属性,或者使用public的getter方法,或者使用@JsonProperty标签里的access控制(可以用默认的AUTO或者READ_ONLY、READ_WRITE都可),其他没有修饰的属性不会返回;

    测试Demo:

    配置文件test5.properties:

    1. server.port=8899
    2. server.servlet.context-path=/test5controller
    3. result.ok=okay

    启动类:

    1. /**
    2. * 2022年11月3日上午10:57:27
    3. */
    4. package testspringboot.test5controller;
    5. import org.springframework.boot.SpringApplication;
    6. import org.springframework.boot.autoconfigure.SpringBootApplication;
    7. import org.springframework.context.annotation.PropertySource;
    8. /**
    9. * @author XWF
    10. *
    11. */
    12. @SpringBootApplication
    13. @PropertySource("test5.properties")
    14. public class Test5Main {
    15. /**
    16. * @param args
    17. */
    18. public static void main(String[] args) {
    19. SpringApplication.run(Test5Main.class, args);
    20. }
    21. }

    controller类:

    1. /**
    2. * 2022年11月3日上午11:02:28
    3. */
    4. package testspringboot.test5controller;
    5. import java.util.HashMap;
    6. import java.util.Map;
    7. import org.springframework.beans.factory.annotation.Value;
    8. import org.springframework.web.bind.annotation.GetMapping;
    9. import org.springframework.web.bind.annotation.PathVariable;
    10. import org.springframework.web.bind.annotation.PostMapping;
    11. import org.springframework.web.bind.annotation.RequestBody;
    12. import org.springframework.web.bind.annotation.RequestMapping;
    13. import org.springframework.web.bind.annotation.RequestMethod;
    14. import org.springframework.web.bind.annotation.RequestParam;
    15. import org.springframework.web.bind.annotation.RestController;
    16. import com.fasterxml.jackson.annotation.JsonProperty;
    17. import testspringboot.test.MyParams;
    18. import testspringboot.test.MyResult;
    19. /**
    20. * @author XWF
    21. *
    22. */
    23. @RestController
    24. @RequestMapping(value = "/myController")
    25. public class MyController {
    26. @Value(value = "${result.ok}")
    27. private String ok;
    28. //处理/和/test0两个请求,并指定必须为PUT请求,并且参数必须有a不能有b,参数c必须为C,参数d不能为D或者不存在d
    29. @RequestMapping(value = {"/", "/test0"}, method = RequestMethod.PUT, params = {"a", "!b", "c=C", "d!=D"})
    30. public void test0(@RequestParam String a, @RequestParam(required = false) String d ) {//有@RequestParam String d则必须要有d参数,可以用required设置非必须
    31. System.out.println("a=" + a);
    32. System.out.println("d=" + d);
    33. }
    34. @RequestMapping(value = "/test1/{x1}/{x2}")
    35. public String test1(@PathVariable String x1, @PathVariable String x2) {
    36. System.out.println("x1=" + x1);
    37. System.out.println("x2=" + x2);
    38. return "test1 ok";
    39. }
    40. //处理get请求
    41. @GetMapping(value = "/test2{num}")
    42. public int test2(@PathVariable("num") int x) {
    43. System.out.println("x=" + x);
    44. return x;
    45. }
    46. //处理post请求
    47. @PostMapping(value = "/test3/form")
    48. public Map test3(@RequestParam("Name") String name, @RequestParam("No") String no) {
    49. System.out.println(String.format("Name=%s,No=%s", name, no));
    50. Map m = new HashMap<>();
    51. m.put("K1", name.toUpperCase());
    52. m.put("K2", no.toUpperCase());
    53. return m;
    54. }
    55. @PostMapping(value = "/test4")
    56. public Result test4(@RequestBody Params params) {
    57. System.out.println("params=" + params);
    58. return new Result(100, "Finished");
    59. }
    60. static class Params{//内部类参数需要指定static
    61. @JsonProperty("name")//指定json字段
    62. String name;
    63. @JsonProperty("age")
    64. int age;
    65. public Params() {//内部类参数需要构造方法
    66. ;
    67. }
    68. @Override
    69. public String toString() {
    70. return "Params [name=" + name + ", age=" + age + "]";
    71. }
    72. }
    73. class Result{
    74. @JsonProperty("ResultCode")
    75. int code;
    76. @JsonProperty("CodeDescription")
    77. String desc;
    78. public Result(int code, String desc) {
    79. super();
    80. this.code = code;
    81. this.desc = desc;
    82. }
    83. }
    84. @PostMapping(value = "/test5")
    85. public MyResult test5(@RequestBody MyParams p) {
    86. System.out.println("MyParams=" + p);
    87. return new MyResult(200, ok);
    88. }
    89. }
    1. /**
    2. * 2022年11月3日上午11:24:23
    3. */
    4. package testspringboot.test5controller;
    5. /**
    6. * @author XWF
    7. *
    8. */
    9. public class MyParams {
    10. public String stringParam;
    11. public int intParam;
    12. @Override
    13. public String toString() {
    14. return "MyParams [stringParam=" + stringParam + ", intParam=" + intParam + "]";
    15. }
    16. }
    1. /**
    2. * 2022年11月3日上午11:24:32
    3. */
    4. package testspringboot.test5controller;
    5. /**
    6. * @author XWF
    7. *
    8. */
    9. public class MyResult {
    10. public long code;
    11. public String description;
    12. public MyResult(long code, String description) {
    13. super();
    14. this.code = code;
    15. this.description = description;
    16. }
    17. }

    测试结果:

    test0

     

    test1

    test2

    test3

    test4

    test5

  • 相关阅读:
    【Flink 监控系列】Flink 自定义 kafka metrics reporter 上报 metrics 到 kafka
    Kotlin 优点
    618购物狂欢节有哪些数码好物值得抢购?年终必备神器清单大揭秘!
    UPC2022暑期个人训练赛第23场(Credit Card Payment)
    CustomNavBar 自定义导航栏视图
    java集合之常用集合类——list集合
    Diffusers 一岁啦 !
    商业银行的绿色信贷、小微企业贷款余额等指标数据(2011-2020年)
    【电商运营】社交媒体营销策略该如何制定?
    数字逻辑设计(1)
  • 原文地址:https://blog.csdn.net/FlyLikeButterfly/article/details/127994737