SpringBoot2-8 Web3 注解 ctrl+F9快速部署 @PathVariable @RequestHandler @MethodAttribute @RequestParam

四种方式

1)注解7个

   @PathVariable @RequestHandler @MethodAttribute @RequestParam @MatrixVariable

   @CookieValue @RequestBody

例1:@RequestParam

@RestController
public class HelloController {

    @RequestMapping("/1.png")
    public String hello(@RequestParam String userName){
          return "静态请求"+userName;

    }

页面请求 http://localhost:8080/1.png?userName=libai  注意?后面的大小写很重要

2)ServletAPI

     WebRequest   ServletRequest   MultipartRequest  HttpSession  javax.servlet.http.PushBuilder

Principal  InputStream   Reader  HttpMethod  Local  TimeZone  ZoneId

举例

   

 @RequestMapping("/1.png")
    public String hello(HttpSession httpSession){
          return "静态请求"+httpSession;

    }

      

 3)复杂参数

   Map Errors/BindingResult Model  RedirectAttributes  ServletResponse

SessionStatus UriComponentsBuilder    ServletUriComponentsBuilder 

举例

 @RequestMapping("/1.png")
    public String hello(Model model){
          return "静态请求"+model;  //model 是页面可以拿到请求域中的数据

    }

4)自定义对象参数

  可以自动类型转换与格式化,可以级联封装

举例:页面提交过来的k v键值对都会被封装到person

  @RequestMapping("/1.png")
    public String hello(Person  person){
          return "静态请求"+person;  //model 是页面可以拿到请求域中的数据

    }

举例

1.例1  @PathVariable  

   用@PathVariable Map<String,String> pv 会自动把请求参数封装到pv

@RestController
public class ParameterTestController {
   // @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
    @GetMapping("/car/{id}/owner/{username}")  //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
    public Map<String,Object> getCar(@PathVariable("id") Integer id,         //获取路径上的id
                                     @PathVariable("username") String name,
                                     @PathVariable Map<String,String> pv){  //除了以上两个方式,还可以把路径上所有key value提取
        Map<String,Object> map=new HashMap<>();
        map.put("id",id);//把获得的id值放到map
        map.put("name",name);
        map.put("pv",pv);
        return map;
    }
}

浏览器请求

http://localhost:8080/car/1/owner/%E6%9D%9C%E7%94%AB

输出,可见 

 2.例2  获取请求头里面的参数

     打算获取如下信息

Response Header中的Host     User-Agent:

 

在controller请求参数中增加

 @RequestHeader("User-Agent")  String userAgent, //获取请求头
@RequestHeader Map<String,String> header     //把请求头都放到一个Map<String,String>
@RestController
public class ParameterTestController {
   // @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
    @GetMapping("/car/{id}/owner/{username}")  //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
    public Map<String,Object> getCar(@PathVariable("id") Integer id,         //获取路径上的id
                                     @PathVariable("username") String name,
                                     @PathVariable Map<String,String> pv, //把路径参数自动封装到Map pv,注意必须是string,string
                                       @RequestHeader("User-Agent")  String userAgent, //获取请求头
                                     @RequestHeader Map<String,String> header


    ){  //除了以上两个方式,还可以把路径上所有key value提取
        Map<String,Object> map=new HashMap<>();
        map.put("id",id);//把获得的id值放到map
        map.put("name",name);
        map.put("pv",pv);
        map.put("userAgent",userAgent);
        map.put("header",header);

        return map;
    }
}

执行

例3  获取请求参数

  html:  ?后面的就是请求参数  索多个用&分开

<a href="car/3/owner/白居易?age=18&interest=basketball&interest=football">/car/{id}/owner/{username}</a>

controller方法请求参数增加

@RestController
public class ParameterTestController {
   // @GetMapping("/car?id=1") //获取id为1的car,这样比较麻烦,改为以下
    @GetMapping("/car/{id}/owner/{username}")  //请求方式为car/1 就是获取1号汽车,可能有多个参数第二个就是username
    public Map<String,Object> getCar(@PathVariable("id") Integer id,         //获取路径上的id
                                     @PathVariable("username") String name,
                                     @PathVariable Map<String,String> pv, //把路径参数自动封装到Map pv,注意必须是string,string
                                     @RequestHeader("User-Agent")  String userAgent, //获取请求头
                                     @RequestHeader Map<String,String> header,
                                     @RequestParam("age") Integer age,
                                     @RequestParam("interest") List<String> interest,
                                     @RequestParam Map<String,String> params


                                     ){  //除了以上两个方式,还可以把路径上所有key value提取
        Map<String,Object> map=new HashMap<>();
        map.put("id",id);//把获得的id值放到map
        map.put("name",name);
        map.put("pv",pv); //pv是map
        map.put("userAgent",userAgent);
        map.put("header",header);//header是map
        map.put("age",age);
        map.put("interest",interest);
        map.put("params",params);//params是map

        return map;
    }
}

 输出

 例4  获取cookie

    也就是要获取

      

 修改controller方法参数

  注意可以使用Cookie这个对象 ,实现response回传cookie

  // @CookieValue("_ga") String _ga
                                     @CookieValue("JSESSIONID") String sessionId,//一般方式获取cookievalue,JSESSIONID是页面上实际存在的cookie name
                                     @CookieValue("JSESSIONID") Cookie cookie  //定义Cookie对象,



 map.put("sessionId",sessionId);
        map.put("cookie",cookie);
        System.out.println(cookie.getName()+"---->"+cookie.getValue()); //证明把cookie想发回去,可以用response

     

  

--------------------------以上是 Get请求-----------

------------------------------------以下是Post请求--------------------------------

例5 获取表单提交内容@RequestBody

       (获取请求体,只有POST请求才有,比如表单)

  修改html

    

<form action="/save" method="post">
    测试@RequestBody获取数据<br/>
    用户名:<input name="userName" /><br/>
    邮箱:<input name="email" />
    <input type="submit" value="提交">
</form>

新建一个PostMapping  controller

  @PostMapping("/save")
    public Map<String,Object> postVerify(@RequestBody  String content){
       Map<String,Object> map=new HashMap<>();
       map.put("content",content);
         return map;

    }

 表单提交后

发现表单Request请求会有Payload带过来

 例6 请求属性@RequestAttribute

       获取Request域中保存的属性,主要用于页面转发

新建2个controller:第1个RequestController  第2个 Success

    当页面请求http://localhost:8080/goto时会使用 return "forward:/success" 进行转发

注意冒号后面不要有空格,不然出现white Page

@Controller
public class RequestController {
    @GetMapping("/goto")
    public String goToPage(HttpServletRequest request){   //参数是原生Request
         request.setAttribute("msg","成功了");
         request.setAttribute("code","200");
          return "forward:/success"; //转发到本项目下success目录
    }

     @ResponseBody
     @GetMapping("/success") //下文用map主要是为了打印方便
    public Map Success(@RequestAttribute("msg") String msg2,//方法一,可以取出request.setAttribute内容
                       @RequestAttribute("code") Integer code2,
                       HttpServletRequest request   //第二种方法,这是把原生请求再拿过来,里面自然也包含其属性
                           ){

        Object msg1=request.getAttribute("msg");  //原生请求
        Map<String,Object> map=new HashMap<>();
        map.put("reqMethod",msg1);
        map.put("annotation_msg",msg2);

       return map;
    }
}

验证结果

例6 @MatrixVariable(获取矩阵变量:绑定在路径中)

    页面阿请求路径带参数有两种方式

   1)链接中用? &这些来,使用@PathVariable来处理

<a href="car/3/owner/白居易?age=18&interest=basketball&interest=football">/car/{id}/owner/{username}</a>

2)矩阵变量绑定在路径中,以分号隔开

<a href="/cars/sell;low=33; brand=Panda,Aodi,BaoMa">@MatrixVariable(矩阵变量)</a>

或者

<a href="/cars/sell;low=33;brand=Changcheng;brand=Wuling;brand=Jialing">@MatrixVariable(矩阵变量)</a>

3)或者层级关系的

   如果使用正常路径写法   /boss/1/2  这个代表1号老板下的2号员工

 可以写为如下方式1号老板age比如大于30的2号员工比如age大于15;两层都有age属性

<a href="/boss/1;age=30/2;age=15">@MatrixVariable(矩阵变量)/boss/{bossId}/{empId}</a>

1;age=30 是一个整体,分号前面是访问路径,分号后面是矩阵变量,多个变量又以分号区分

2;age=15也是一个整体

4)适用场景:cookie被禁用,如何找到session里面的内容

session保存原理:

 session.set(a,b)-->生成一个jssesionId-->保存在cookie-->每次发请求都会携带cookie

一旦cookie被禁用,找不到jessionid也就找不到seesion对象

这时候可以这样访问 :  /abc;jessionid=xxxxx  这就是url重写,把原来cookie的内容使用矩阵变量的方式传递过来;主要是用请求参数的方式和正常的就无法区分,所以专门用矩阵变量方式传递

所以分号后面的都是矩阵变量内容

    5)

测试点击页面链接

<a href="/cars/sell;low=33; brand=Panda,Aodi,BaoMa">@MatrixVariable(矩阵变量)</a></br>

出现

报错没有找到 low变量,原因在于springboot默认禁用矩阵变量,路径中出现了%20

springboot底层是Spring MVC,搜索到 WebMvcConfiguration类

以下用于配置映射

 UrlPathHelper 是url 路径帮助器,进入发现

private boolean removeSemicolonContent = true;   用于移除分号

 进入removeSemicolonContent

下面有方法:如果分号被移除,分号后面的参数会被截掉

  public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
        this.checkReadOnly();
        this.removeSemicolonContent = removeSemicolonContent;
    }

总之对于路径处理都是使用UrlPathHelper进行解析的

        removeSemicolonContent移除分号内容就是决定要不要支持矩阵变量,因为矩阵变量要用分号

修改配置,原理参照 下面单独一级目录:    如何更改SpringMVC自动配置,三种方法

package com.i7i8i9.boot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;


@Configuration(proxyBeanMethods = false)  //false代表组件之间没有依赖,可以快速编译
public class WebConfig /* implements WebMvcConfigurer */{
    @Bean
    public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
        HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
        hiddenHttpMethodFilter.setMethodParam("_mm");
        return  hiddenHttpMethodFilter;

    }
  @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override   //new的时候实现一个需要的方法
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper=new UrlPathHelper();
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
  }

//    @Override  //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        UrlPathHelper urlPathHelper=new UrlPathHelper();
//        urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
//        configurer.setUrlPathHelper(urlPathHelper);
//    }
}

更改cotroller

package com.i7i8i9.boot.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class RequestController {
    @GetMapping("/goto")
    public String goToPage(HttpServletRequest request){   //参数是原生Request
         request.setAttribute("msg","成功了");
         request.setAttribute("code","200");
          return "forward:/success"; //转发到本项目下success目录
    }

     @ResponseBody
     @GetMapping("/success") //下文用map主要是为了打印方便
    public Map Success(@RequestAttribute("msg") String msg2,//方法一,可以取出request.setAttribute内容
                       @RequestAttribute("code") Integer code2,
                       HttpServletRequest request   //第二种方法,这是把原生请求再拿过来,里面自然也包含其属性
                           ){

        Object msg1=request.getAttribute("msg");  //原生请求
        Map<String,Object> map=new HashMap<>();
        map.put("reqMethod",msg1);
        map.put("annotation_msg",msg2);

       return map;
    }

   // a href="/cars/sell;low=33;brand=Panda,Aodi,BaoMa"
   // @GetMapping("/cars/sell")  //  /cars/sell会带很多矩阵变量而不是请求参数
    @GetMapping("/cars/{path}")
   public Map carSell(@MatrixVariable("low") Integer low,
                       //@MatrixVariable("brand") List<String> brand,
                       @PathVariable("path") String path){  //主要是为了看看path究竟是什么
        System.out.println(path);
       Map<String,Object> map=new HashMap<>();
       map.put("low",low);
      // map.put("brand",brand);
       map.put("path",path);
        return map;
    }
}

重新运行,打开网页

,去除缓存页面  Whitelabel Error Page

  百思不得其解,

1)验证1:在controller打印path,发现输出是正确的:  

     

    去掉分号后面的,则出现

 

    看上去是没有解析到分号后面的参数,怀疑是urlPathHelper问题,但是搜索

@GetMapping("/cars/{path}")   urlPathHelper都没有看出异常,一晚无解

      有的时候带第一个分号是有效的http://localhost:8080/cars/sell;low=33;加上brand=panda,aodi,baoma则不再提示low找不到,而是提示list brand找不到,怀疑是list不对,controller去掉该变量,则又返回提示404

2)早晨重启电脑,还是404,打算再搜索MatrixVariable寻找完整代码,发现

     controller跟别人不一样的是@Controller,尝试改成@RestController后重新运行问题解决

 

如何更改SpringMVC自动配置,三种方法

1)不使用@EnableWebMVC

   使用@Configuration+WebMvcConfigurer自定义规则

      @Configuration代表在容器中

搜索WebMvcConfigurer,其是一个接口。里面定义了configurePathMatch方法

      

 其实在自动配置WebMvcAutoConfiguration类,中也是实现了该接口

我们自己可以写一个配置类实现

方法1:直接使配置类继承WebMvcConfigurer  ,同时由于jdk8只需改写要实现的方法
package com.i7i8i9.boot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;


@Configuration(proxyBeanMethods = false)  //false代表组件之间没有依赖,可以快速编译
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
        HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
        hiddenHttpMethodFilter.setMethodParam("_mm");
        return  hiddenHttpMethodFilter;

    }


    @Override  //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper=new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

方法2在配置类里面加@Bean WebMvcConfigure

package com.i7i8i9.boot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;


@Configuration(proxyBeanMethods = false)  //false代表组件之间没有依赖,可以快速编译
public class WebConfig /* implements WebMvcConfigurer */{
    @Bean
    public HiddenHttpMethodFilter HiddenHttpMethodFilter(){
        HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
        hiddenHttpMethodFilter.setMethodParam("_mm");
        return  hiddenHttpMethodFilter;

    }
  @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override   //new的时候实现一个需要的方法
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper=new UrlPathHelper();
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
  }

//    @Override  //重写需要的WebMvcConfigurer方法,jdk8不许要全部重写
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        UrlPathHelper urlPathHelper=new UrlPathHelper();
//        urlPathHelper.setRemoveSemicolonContent(false); //默认的去除分号RemoveSemicolonContent是true,所以此处要new一个新的urlPathHelper
//        configurer.setUrlPathHelper(urlPathHelper);
//    }
}

2)urlhepler很有用

    进入其类,

 ctrl+F12查看其方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值