Spring Controller

举报
武师叔 发表于 2022/08/30 08:48:36 2022/08/30
【摘要】 服务器控制 响应架构Spring Boot 内集成了 Tomcat 服务器,也可以外接 Tomcat 服务器。通过控制层接收浏览器的 URL 请求进行操作并返回数据。底层和浏览器的信息交互仍旧由 servlet 完成,服务器整体架构如下:Server: Tomcat 最顶层容器,代表整个服务器。Service:服务,对应不同的任务。Connector:有多个,用来处理连接相关的事情,并提供...

服务器控制

响应架构

Spring Boot 内集成了 Tomcat 服务器,也可以外接 Tomcat 服务器。通过控制层接收浏览器的 URL 请求进行操作并返回数据。

底层和浏览器的信息交互仍旧由 servlet 完成,服务器整体架构如下:

  • Server: Tomcat 最顶层容器,代表整个服务器。

    • Service:服务,对应不同的任务。

      • Connector:有多个,用来处理连接相关的事情,并提供 Socket 到 Request 和 Response 相关转化。
      • Container:只有一个,用于封装和管理 Servlet ,以及处理具体的 Request 请求。

启动过程

main 方法: 实例化 SpringApplication ,执行run方法

run方法:
配置属性、获取监听器,初始化输入参数、配置环境,输出banner 创建上下文、预处理上下文、刷新上下文、再刷新上下文:context

refreshApplicationContext方法:通过ServletWebServerFactory接口定义了getwebServer方法,通过其创建webServer并返回(创建时做了两件重要的事情:把Connector对象添加到tomcat中,配置引擎)【TomcatServletWebServerFactory是接口其中一个实现类】

TomcatwebServer类中,规定了Tomcat服务器的启动和关闭方法。

而tomcat的启动主要是实例化两个组件:Connector、Container


Controller 实现

Controller 类需要使用 @RestController 或 @Controller 注解标注。

  • @Controller:类中所有方法以 String 形式返回 classpath 路径下同名 html 页面。适用于 JSP/thymeleaf 等动态加载页面。
  • @RestController:类中所有方法以 Map/List 等形式返回 JSON 数据。适用于前后端分离开发。

P.S. @Controller 类中标注 @ResponseBody 的方法,可以起到和 @RestController 类相同的效果。

请求映射

  1. Controller 类中的方法使用 @RequestMapping 注解标注,就可以将指定 URL 请求映射到方法上处理。
@RequestMapping(value = "/hello", method = RequestMethod.GET)     // 参数为 URL 路径和请求方式
@RequestMapping("/hello")                                         // 默认接收所有请求方式

@GetMapping("/hello")                                             // 简写形式的 GET 请求
@PostMapping("/hello")                                            // 简写形式的 POST 请求

// 灵活映射
@RequestMapping("/?/hello")                                       // ? 匹配单字符
@RequestMapping("/*/hello")`:                                    // * 匹配任意数量字符
@RequestMapping("/**/hello"):                                    // ** 匹配任意数量目录
@RequestMapping("/{ID}/hello")`                                   // {} 自动读取 URL 路径动态参数Copy to clipboardErrorCopied
  1. Controller 类也可以通过 @RequestMapping 注解标注,表示路径下的 URL 请求在该类中寻找方法。
@Controller
@RequestMapping("/speak")
public class SpeakController{
    @GetMapping("/hello")
    public String hello(){ return "hello"; } 
}Copy to clipboardErrorCopied

GET 请求参数

GET 请求参数直接附着在 URL 中。对于请求 /test?username=mrjoker&password=123456 ,Controller 方法有以下几种方式接收:

  1. 直接获取参数
@RequestMapping("/test")
public String test(String username, String password){
    return username + password;
}Copy to clipboardErrorCopied
  1. 通过 HttpServletRequest 类来获取参数
@RequestMapping("/test")
public String test(HttpServletRequest request){
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    return username + password;
}Copy to clipboardErrorCopied
  1. 通过自定义对象来获取参数
@RequestMapping("/test")
public String test(User user){
    String username = user.getUsername();
    String password = user.getPassword();
    return username + password;
}Copy to clipboardErrorCopied
  1. 通过 RequestParam 注解来获取参数,实参值赋给形参。
@RequestMapping("/test")
public String test(@RequestParam(value="username",required = false, defaultValue ="mrjoker") String s1, @RequestParam("password") String s2){
    return s1 + s2;
}Copy to clipboardErrorCopied
  1. 通过 PathVariable 注解来动态获取参数,参数直接附着在 URL 中。
@RequestMapping("/test/{username}/{password}")
public String test(@PathVariable("username") String s1, @PathVariable("password") String s2){
    return s1 + s2;
}Copy to clipboardErrorCopied
  1. 通过 ModelAttribute 注解来获取其他方法返回值作为参数,被注释方法会在此 controller 中每个方法执行前被执行。
@Controller 
public class HelloWorldController { 
    @ModelAttribute 
    public void populateModel(@RequestParam String abc, Model model) { 
        model.addAttribute("attributeName", abc); 
    } 

    @RequestMapping(value = "/helloWorld") 
    public String helloWorld() { 
       return "helloWorld"; 
    } 
}Copy to clipboardErrorCopied

POST 请求参数

POST 请求请求参数放置在请求体中,有以下两种格式:

  • Form Data 格式

请求的 Content-Type 为 application/x-www-form-urlencoded

示例:username=mrjoker&password=123456

  • Request Payload 格式

请求的 Content-Type 为 application/json 或者 multipart/form-data

示例:{"username":"mrjoker", "password":"123456"}

  1. AJAX 提交 POST 请求默认使用 Form Data 格式,Spring MVC 会自动解析到对应的 bean 中并获取参数。
// 逐个参数接收
@RequestMapping(value="/test", method=RequestMethod.POST)
private String test(@RequestParam("username") String username, @RequestParam("password") String password){
    return username + password;
}

// 解析为整体接收
@RequestMapping(value="/test", method=RequestMethod.POST)
private String test(User user){
    return user.getUsername() + user.getPassword();
}Copy to clipboardErrorCopied
  1. Vue 提交 POST 请求默认使用 Request Payload 格式,Spring MVC 接收时必须进行处理:

    • 前端解决方案: axios 库可以使用 qs 库将 json 对象转化为 Form Data 格式。
    • 后端解决方案: Spring Boot 在请求参数上加 @RequestBody 注解,将请求正文解析到对应的 bean 中获取参数。

@RequestBody 可以直接以 String 接收前端传过来的 json 数据,也可以用对象自动解析前端传过来的 json 数据。对象里定义 List 属性,可用来接收多条 json 数据。

// String 形式接收
@RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(@RequestBody String user) {
    JSONObject userJson = JSON.parseObject(user);
    String username = userJson.getString("username");
    String password = userJson.getString("password");
    return username + password;
}

// 解析为对象接收
@RequestMapping(value = "/test", method = RequestMethod.POST)
public String updateClusterIdByClientAndQueue(@RequestBody User user) {
    return user.getUsername() + user.getPassword();
}Copy to clipboardErrorCopied

一个请求可以有多个 @RequestParam,但只能有一个 @RequestBody。 URL 内含有参数时,两者可以同时使用。

请求转发和重定向

  1. 请求转发(forward)

    客户端(浏览器)向服务器 A 发送一个 URL 请求,服务器 A 会向另一台服务器 B 获取资源并将此资源响应给浏览器。浏览器的 URL 地址仍然是 A 。

  2. 重定向(Redirect)

    客户端(浏览器)向服务器 A 发送一个 URL 请求,服务器 A 告知浏览器资源在服务器 B,浏览器会重新发送请求到服务器 B。浏览器的 URL 地址切换为 B。

// 请求转发
@RequestMapping("/test1")
public String test1(){
    String type = 'forward';
    return "forward:/test2?type=" + type;
}

// 重定向
@RequestMapping("/test2")
public String test2(){
    String type = 'redirect';
    return "redirect:/test2?type=" + type;
}Copy to clipboardErrorCopied

在拦截器中,常通过修改 HttpSevletRequest 对象实现请求转发。

request.getRequestDispatcher("login").forward(request,response);
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。