专栏首页大话swiftSpringMVC 中的Annotated Controllers

SpringMVC 中的Annotated Controllers

看看第一个controller

@Controller
public class HelloController {

    @GetMapping("/hello")
    public String handle(Model model) {
        model.addAttribute("message", "Hello World!");
        return "index";
    }
}

上面透漏一下信息:是一个GET响应 查找web下的index模版,通过model将数据传递给模版引擎渲染

我们看到了能访问/hello,那么为啥呢?SpringMVC怎么知道有这个文件呢?--答案是通过组件扫描

@Configuration
@ComponentScan("org.example.web")
public class WebConfig {

    // ...
}

上面的代码与xml配置等同

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example.web"/>

    <!-- ... -->

</beans>

总体来说都是基于Spring的IOC容器方式,通过组件扫描将各组件加载称为bean

Request Mapping

采用@Request Mapping实现controller响应controllers的网络请求

下面是具体分类,来响应区分不同的网络方法

    @GetMapping
    @PostMapping
    @PutMapping
    @DeleteMapping
    @PatchMapping

下面是具体的实例参考

@RestController
@RequestMapping("/persons")
class PersonController {

    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}
URI patterns

可以使用@PathVariable匹配参数中添加变量参数来区分数据,比如

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
    // ...
}

同时你也能够在class和Method级别注解声明URI变量,比如

@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {

    @GetMapping("/pets/{petId}")
    public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
        // ...
    }
}

上面中controller下的所有Mapping响应都会加上/owners/{ownerId}前缀,例如上栗中的组合成为:/owners/{ownerId}/pets/{petId}

除此紫外我们还可在Mapping中添加正则匹配:

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String ext) {
    // ...
}
Consumable Media Types

在Mapping注解中我们还可以限制Content-Type

@PostMapping(path = "/pets", consumes = "application/json") 
public void addPet(@RequestBody Pet pet) {
    // ...
}

还可以设置header数据

@GetMapping(path = "/pets", headers = "myHeader=myValue") 
public void findPet(@PathVariable String petId) {
    // ...
}

动态注册Controller响应

@Configuration
public class MyConfig {

    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) 
            throws NoSuchMethodException {

        RequestMappingInfo info = RequestMappingInfo
                .paths("/user/{id}").methods(RequestMethod.GET).build();

        Method method = UserHandler.class.getMethod("getUser", Long.class);

        mapping.registerMapping(info, handler, method); 
    }
}

请求参数

在方法中使用@RequestParam只标注的变量是url中的query数据

@Controller
@RequestMapping("/pets")
public class EditPetForm {
    @GetMapping
    public String setupForm(@RequestParam("petId") int petId, Model model) { 
        Pet pet = this.clinic.loadPet(petId);
        model.addAttribute("pet", pet);
        return "petForm";
    }
}

上栗中的urlquery为:/pets?petId=xxx

与此同时我还可以使用@RequestHeader将header的数据注入到响应的方法中

@GetMapping("/demo")
public void handle(
        @RequestHeader("Accept-Encoding") String encoding, 
        @RequestHeader("Keep-Alive") long keepAlive) { 
    //...
}

Session和Cookie注入

@GetMapping("/demo")
public void handle(@CookieValue("JSESSIONID") String cookie) { 
    //...
}

@RequestMapping("/")
public String handle(@SessionAttribute User user) { 
    // ...
}

请求数据转模型注入(@ModelAttribute

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet, BindingResult result) {
 if (result.hasErrors()) {
        return "petForm";
    }
 } 

这个需要请求参数与Model的属性名称相同,也是十分方便,同时也可做数据监测

文件上传

文件上传通常采用form表单需要multipart/form-data

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(@RequestParam("name") String name,
            @RequestParam("file") MultipartFile file) {

        if (!file.isEmpty()) {
            byte[] bytes = file.getBytes();
            // store the bytes somewhere
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

同样的我们也可将form的文件转换为model

class MyForm {

    private String name;

    private MultipartFile file;

    // ...
}

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(MyForm form, BindingResult errors) {
        if (!form.getFile().isEmpty()) {
            byte[] bytes = form.getFile().getBytes();
            // store the bytes somewhere
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

这个form文件上传会有两个字段:一个是表单名 另一个是文件名

今天就这么多,看英文自己翻译总结还是费点劲,下一篇阅读URL Linkes

本文分享自微信公众号 - 大话swift(gh_ca2266b7cab0),作者:YuLongLi

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 惊鸿一瞥之Kotlin

    看了Google开发者大会之后你啥感觉?一个是flutter真的可以入手啦,另一个就是Kotlin需要看看啦。为啥要看Kotlin呢?因为Google已经帮你想...

    大话swift
  • 万能的Hello World

    4 重点 @RestController 声明一个rest服务 @SpringBootApplication 表明为springboot的开始

    大话swift
  • gin框架之参数获取

    http://127.0.0.1:8080/get/query?b=2&e=1&e=2&f[a]=1&f[b]=2

    大话swift
  • 自定义参数解析器

    开发中,app端给服务端会传基础参数、其他参数,一般基础参数app端都会传给服务端,其他参数则是根据不同接口传不同参数。若以表单的形式提交的数据:

    LiosWong
  • Java-内部类

    如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象(在静态方法内部创建某个内部类的对象),那么必须像在main()方法中那样,具体地指明这个对象的类型...

    桑鱼
  • 十分钟搞懂Java效率工具Lombok使用与原理

    Lombok是一款好用顺手的工具,就像Google Guava一样,在此予以强烈推荐,每一个Java工程师都应该使用它。Lombok是一种Java™实用工具,可...

    java思维导图
  • SpringBoot几个注解MockMvcWireMockSwagger2@JsonViewHibernate Validator异常处理拦截方式上传下载异步处理RESTSpring Security

    只有特定名称或者类型的Bean(通过@ConditionalOnMissingBean修饰)不存在于BeanFactory中时才创建某个Bean

    spilledyear
  • Spring Boot 自动配置的 “魔法” 是如何实现的?

    Spring Boot是Spring旗下众多的子项目之一,其理念是约定优于配置,它通过实现了自动配置(大多数用户平时习惯设置的配置作为默认配置)的功能来为用户快...

    用户1257393
  • Java并发编程(06):Lock机制下API用法详解

    Lock加锁相关结构中涉及两个使用广泛的基础API:ReentrantLock类和Condition接口,基本关系如下:

    知了一笑
  • Spring Boot 自动配置的“魔法”是如何实现的?

    Spring Boot是Spring旗下众多的子项目之一,其理念是约定优于配置,它通过实现了自动配置(大多数用户平时习惯设置的配置作为默认配置)的功能来为用户快...

    Java团长

扫码关注云+社区

领取腾讯云代金券