Spring Boot的Web开发(学习记录)

application.yaml中修改访问前缀以及映射路径。

spring:
  mvc:
    static-path-pattern: /res/**#但是这个会影响欢迎页面和favicon.ico图标的的加载
  web:
    resources:
      static-locations: [classpath:/haha/]

https://www.webjars.org/可以得到静态资源的maven文件
访问webjars里面的jar包,要用webjars/jquery/3.6.0/jquery.js这样的路径
jquery/3.6.0/jquery.js
是要访问的文件,webjars相当于默认前缀
欢迎页面不能设置访问前缀,不然会导致访问失效
禁用掉所有静态资源规则

spring:
  web:
    resources:
      add-mappings: false

表单提交现在只有post和get方法,怎么发出put和delete请求:
现版本是:表单继续使用post请求,但是再使用一个
<input name="_method" type="hidden" value="DELETE">标签放在这个表单中,就能实现delete提交,把value设置为put就能实现put请求,这个在源码中有体现。这个设置好后还需在properties文件中设置为true,因为底层源码默认为false。

spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true

对于每一个请求的参数,都有required方法,设置成false的话,有没有都行,true就是必须有,没有就报错。
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping这四个是四种请求方式,相当于在@RequestMapping里面的method等于他们这四个
可以修改它默认的_method参数,从原理得知,当@ConditionalOnMissingBean({HiddenHttpMethodFilter.class})这个条件满足时才会new一个,因此我们自己创建一个,因为它的创建不依赖其他的,可设置proxyBeanMethods = false,轻量级,使用以下代码创建后setMethodParam就可以把它改为我们自己想设置的参数。

@Configuration(proxyBeanMethods = false)
public class Webconfig {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter Filter=new HiddenHttpMethodFilter();
        Filter.setMethodParam("_m");
        return Filter;
    }
}

对于网页参数接收的几种方式:
HTML测试代码:

<body>
        <h1>Cqupt欢迎您</h1>
        <form method="post" action="/user">
            <input value="post提交" type="submit">
        </form>
        <form method="get" action="/user">
            <input value="get提交" type="submit">
        </form>
        <form method="post" action="/user">
            <input name="_m" type="hidden" value="DELETE">
            <input value="delete提交" type="submit">
        </form>
        <form method="post" action="/user">
            <input name="_m" type="hidden" value="put">
            <input value="put提交" type="submit">
        </form>
    <ul>
        <a href="/car/1/owner/syf?age=18&interest='篮球'&interest='乒乓'">传参</a>
        <li>@PathVarible(路径变量)</li>
        <li>@RequestHeadler(获取请求头)</li>
        <li>@RequestParam(获取请求参数)</li>
        <li>@CookieValue(获取Cookie值)</li>
        <li>@RequestAttribute(获取request域属性)</li>
        <li>@RequestBody(获取请求体)</li>
        <li>@MatrixVariable(矩阵变量)</li>
    </ul>
    <form action="/save" method="post">
        测试@RequestBody(获取请求体)<br>
        用户名<input name="username"><br>
        邮箱<input name="email">
        <input type="submit" value="提交">
    </form>
    </body>

controller代码:

@RestController
public class ParameterController {
    /**
     * /car/1/owner/syf?age=18&interest='篮球'&interest='乒乓'
     *定义方法时取得的参数里面的Map只能是<String,String>,没加参数用map就相当于把里面的key:value都一一配对存放
     *PathVariable()括号中放GetMapping("/car/{id}/owner/{username}")里{}的参数名,再定义变量就行,取出来的就是这个值
     * PathVariable获取网址信息中参数,RequestHeader获取请求头
     * 当网页中有请求参数时单个的可用RequestParam,当一个interest有多个值可用List集合,也可用一个map把所有参数的值都获取到里面
     */
    @GetMapping("/car/{id}/owner/{username}")//必须按照这个顺序发送参数,{}中是变参,owner是不变的
    public Map<String ,Object> getCar(@PathVariable("id") Integer id, @PathVariable("username") String username,
                                      @PathVariable Map<String,String> map1, @RequestHeader("User-Agent")String header,
                                      @RequestHeader Map<String,String> mapheader, @RequestParam("age")String age,
                                      @RequestParam("interest") List<String> list,@CookieValue("Idea-fc47497d")String cookie,
                                      @CookieValue("Idea-fc47497d") Cookie allKookie){
        Map<String,Object> map=new HashMap<>();
        map.put("id",id);
        map.put("username",username);
        map.put("map1",map1);
        map.put("User-Agent",header);
        map.put("allheader",mapheader);
        map.put("age",age);
        map.put("list",list);
        map.put("Idea-fc47497d",cookie);
        System.out.println(allKookie.getValue());
        return map;
    }
    @PostMapping("/save")
    public Map<String,Object> postMethod(@RequestBody String body){//将请求信息都获取到,key=value&key=value这种形式
        Map<String,Object> map=new HashMap<>();
        map.put("body",body);
        return map;
    }
}

网页转发信息Controller代码:

	//转发到另一个页面 注意!!类上是@Controller,最后显示的是被转发页面要展示的信息
    @GetMapping("/goto")
    public String page(HttpServletRequest request){
        request.setAttribute("msg","成功了");
        request.setAttribute("code","java-开发");
        return "forward:/success";  //转发到 /success请求
    }
    //被转发的加上@ResponseBody
    @ResponseBody
    @GetMapping("/success")
    public Map<String,Object> success(@RequestAttribute("msg")String msg,//不能用Map把RequestAttribute的内容全部放一起
                   @RequestAttribute("code")String code,
                   HttpServletRequest request){
        Map<String,Object> map=new HashMap<>();
        map.put("msg",msg);
        map.put("code",code);
        map.put("msg1",request.getAttribute("msg"));
        map.put("code1",request.getAttribute("code"));
        return map;
    }

矩阵变量:
矩阵变量url中带分号的形式,分号后面为矩阵变量,前面为要访问的路径
在这里插入图片描述

//下面两种方法都可以开启 矩阵变量功能,默认是关闭的
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper=new UrlPathHelper();
                //不移除矩阵变量后面的分号,矩阵变量的功能就能实现 默认是移除
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }

//    @Override
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        UrlPathHelper urlPathHelper=new UrlPathHelper();
//        //不移除矩阵变量后面的分号,矩阵变量的功能就能实现 默认是移除
//        urlPathHelper.setRemoveSemicolonContent(false);
//        configurer.setUrlPathHelper(urlPathHelper);
//    }

Html代码:

    <a href="/cars/sel;low=34;brand=byd,wuling">@MatrixVariable(矩阵变量)</a><br>
    <a href="/cars/sel;low=34;brand=byd,brand=wuling">@MatrixVariable(矩阵变量</a><br>
    <a href="/boss/1;age=20/2;age=25">@MatrixVariable(矩阵变量</a>

java代码:

 	//1、语法/cars/sel;low=34;brand=byd,wuling
    //2、Spring Boot 默认禁用掉了矩阵变量
    //   手动开启:原理。对于路径的处理,UrlPathHelper进行解析
    //    removeSemicolonContent(移除分号)支持矩阵变量的
    //两个变量名一致 就需要加变量名  @MatrixVariable(value = "age",pathVar = "bossid"),只有一个的话直接写矩阵变量名就行
    // 3、矩阵变量必须有url路径变量才能被解析
    //注意!!!!类上要有@ResponseBody标签
    @GetMapping("/cars/{path}")
    public Map<String,Object> car1(@MatrixVariable("low") Integer s, @MatrixVariable("brand")List<String> brands,
                                   @PathVariable("path") String path){
        Map<String,Object> map=new HashMap<>();
        map.put("low",s);
        map.put("brands",brands);
        map.put("path",path);
        return map;
    }
    @GetMapping("/boss/{bossid}/{emplyid}")
    public Map<String,Object> boss1(@MatrixVariable(value = "age",pathVar = "bossid") Integer bossid,
                                    @MatrixVariable(value = "age",pathVar = "emplyid")Integer employid){
        Map<String,Object> map=new HashMap<>();
        map.put("bossid",bossid);
        map.put("emplyid",employid);
        return map;
    }

在这里插入图片描述
html代码:

        //表单可以级联使用例如下表形式
    <form action="/saveuser" method="post">
        姓名:   <input name="username" value="zhangsan"><br>
        年龄:   <input name="age" value="23"><br>
        生日:   <input name="birth" value="1998"><br>
        宠物姓名:<input name="pet.name" value="tom"><br>
        宠物年龄:<input name="pet.age" value="2"><br>
        <input type="submit" value="提交">
    </form>

Controller代码:

    /**
     * 数据绑定: 页面提交的请求数据(get、post)都可以和对象属性进行绑定
     * @param person
     * @return
     * 不能直接访问/saveuser网址,因为没有数据,会报错,要从表单那面提交过来看,报错信息:
     * Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
     */
    @PostMapping("/saveuser")
    public Person Register(Person person){
        return person;
    }

给网页返还json对象代码:

@Controller
public class ResponseTestController {
    //加上ResponseBody就能自动给前端返回数据,但是类上面就不能加了,类上就写Controller,类上加了这里就不加
    //RequestResponseBodyMethodProcessor调用messageConverter 写成了json
    @ResponseBody
    @GetMapping("/test")
    public Person GetPerson(){
        Person person=new Person();
        person.setAge(23);
        person.setBirth("1998");
        person.setPet(new Pet());
        person.setUsername("syf");
        return person;
    }

内容协商

根据客户端接收能力不同,返回不同媒体类型的数据
确定客户端接收什么样的数据是通过请求头的accept字段确定的,看客户端接收的优先级,如果高xml而且服务器能够产生xml就返还,xml的文件依赖:
因为有了parent管理版本,不需要标注版本号。

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

测试浏览器时想观看效果,可通过以下方式实现:

# 内容协商 设置成true后在浏览器搜索栏加上 ?format=xml就能设置想接收什么形式,但是spring boot里面源码就支持json 和 xml 类似http://localhost:8080/test?format=json
#之前是通过请求头的accept字段确定,现在通过请求头中的format的值。相当于我们的参数优先。
spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

响应数据

自定义返回数据类型
1、先创建一个自己想写出数据类型的Convertor,实现HttpMessageConverter。

/**
 * 自定义的Converter
 */
public class MyappMessageConverter implements HttpMessageConverter<Person> {
    @Override//读就是能否读出传过来的参数
    public boolean canRead(Class<?> aClass, MediaType mediaType) {
        return false;
    }
    //只要方法返回的是Person类型就可以写
    @Override
    public boolean canWrite(Class<?> aClass, MediaType mediaType) {
        return aClass.isAssignableFrom(Person.class);
    }

    /**
     * 服务器要统计所有MessageConverter都能写出哪些内容类型,所以要把我们的注入进去
     * 【application/x-myapp】
     * @return
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-myapp");
    }

    @Override
    public Person read(Class<? extends Person> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    /**
     * 自定义协议的写出
     * @param person
     * @param mediaType
     * @param httpOutputMessage
     * @throws IOException
     * @throws HttpMessageNotWritableException
     */
    @Override
    public void write(Person person, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        String data=person.getUsername()+";"+person.getAge()+";"+person.getBirth()+";"+person.getPet();
        OutputStream body=httpOutputMessage.getBody();
        body.write(data.getBytes());
        body.flush();
        body.close();
    }
}

最后在Config配置标签类中添加WebMvcConfigurer 组件重写extendMessageConverters方法,将自己创建的Convertor放进去

@Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            //自定义的信息转换器
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new MyappMessageConverter());
            }      
    }

自定义url使用参数返回类型:

/**
             * 自定义协商策略
             * 用参数在url上定义新的策略达到能够用format=xxx实现
             * 有可能我们添加的自定义功能会覆盖很多默认功能,导致一些默认的功能失效
             * @param configurer
             */
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //填入策略支持的媒体类型
                Map<String, MediaType> mediaTypes=new HashMap<>();
                mediaTypes.put("json",MediaType.APPLICATION_JSON);
                mediaTypes.put("xml",MediaType.APPLICATION_XML);
                //放入新的"x"为新设置的format=x
                mediaTypes.put("x",MediaType.parseMediaType("application/x-myapp"));
                //指定支持解析哪些参数的哪些媒体类型
                ParameterContentNegotiationStrategy strategy=new ParameterContentNegotiationStrategy(mediaTypes);
                //如果只定义了以上就只设置参数策略就失去了请求头的,因为重写了之后自己没有写
                //改变format为for  没有写就默认为 format
                strategy.setParameterName("for");
                //加上默认请求头的
                HeaderContentNegotiationStrategy headstrategy=new HeaderContentNegotiationStrategy();
                configurer.strategies(Arrays.asList(strategy,headstrategy));
            }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syf_wfl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值