SpringMVC程序开发

1.什么是 Spring MVC?

官⽅对于 Spring MVC 的描述是这样的:

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,”comes from the name of its source module ( spring-webmvc ), but it is more commonly knownas “Spring MVC”.

官网链接:Spring Framework Documentation :: Spring Framework

翻译为中⽂:Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为“Spring MVC “。

从上述定义我们可以得出两个关键信息:

1. Spring MVC 是⼀个 Web 框架。 2. Spring MVC 是基于 Servlet API 构建的。

1.1 MVC 定义

MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分 为模型、视图和控制器三个基本部分。

  •  Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。

1.2 MVC 和 Spring MVC 的关系

MVC 是⼀种思想,⽽ Spring MVC 是对 MVC 思想的具体实现。

 总结来说,Spring MVC 是⼀个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web 框架,那么当⽤户在浏览器中输⼊了 url 之后,我们的 Spring MVC 项⽬就可以感知到⽤户的请求。

2.为什么要学 Spring MVC?

现在绝⼤部分的 Java 项⽬都是基于 Spring(或 Spring Boot)的,⽽ Spring 的核⼼就是 Spring MVC。也就是说 Spring MVC 是 Spring 框架的核⼼模块,⽽ Spring Boot 是 Spring 的脚⼿架,因此 我们可以推断出,现在市⾯上绝⼤部分的 Java 项⽬约等于 Spring MVC 项⽬,这是我们要学 Spring MVC 的原因。

在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架。

简单来说,咱们之所以要学习 Spring MVC 是因为它是⼀切项⽬的基础,我们以后创建的所有 Spring、Spring Boot 项⽬基本都是基于 Spring MVC 的。

3.怎么学 Spring MVC?

学习 Spring MVC 我们只需要掌握以下 3 个功能:

  1. 连接的功能:将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。
  2. 获取参数的功能:⽤户访问的时候会带⼀些参数,在程序中要想办法获取到参数。
  3. 输出数据的功能:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤户。

对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC。

3.1 Spring MVC 创建和连接

Spring MVC 项⽬创建和 Spring Boot 创建项⽬相同(Spring MVC 使⽤ Spring Boot 的⽅式创建), 在创建的时候选择 Spring Web 就相当于创建了 Spring MVC 的项⽬。

在 Spring MVC 中使⽤ @RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作⽤。

3.1.1 创建 Spring MVC 项⽬

Spring MVC 可以基于 Spring Boot 创建,也就是创建⼀个 Spring Boot 项⽬,勾选上 Spring Web 模块即可,如下图所示:

package com.example.springmvcdome.controller;

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

@Controller
@RequestMapping("/web")
public class WebController {
    @RequestMapping("index")
    public String index(){
//        return "hello,Spring MVC";
        return "/index.html";
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>我是index页面</h1>
</body>
</html>

 

3.1.2 @RequestMapping 注解介绍

@RequestMapping 是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路 由映射的。

路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类 的某个⽅法的过程就叫路由映射。

@RequestMapping 基础使⽤:

import com.example.demo.model.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/p")
public class PersonController {
 @RequestMapping("/index")
 public Object index(Person person){
 // 获取参数
 System.out.println(person.getName() +":"+
 person.getPassword());
 // 执⾏业务...
 return "/index.html";
 }
}

@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + ⽅ 法。

@RequestMapping 也可以直接修饰⽅法,代码实现如下:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody // 定义返回的数据格式为⾮视图(text/html)
public class UserController {
 @RequestMapping("/hi")
 public String sayHi(){
 return "<h1>Hi,Spring MVC.</h1>";
 }
}

 

3.1.3 @RequestMapping 是 post 还是 get 请求?

使⽤ PostMan 测试⼀下,默认情况下使⽤注解 @RequestMapping 是否可以接收 GET 或 POST 请 求?

答:@RequestMapping 同时支持get,post 请求

指定 GET/POST 方法类型

我们可以显示的指定 @RequestMapping 来接收 GET 的情况,如下所示:

package com.example.springmvcdome.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/web")
public class WebController {

    @RequestMapping("/index")
    public String index(){
        return "/index.html";
    }

    @ResponseBody
    @RequestMapping(value = "/indexData",method = RequestMethod.GET)
    public String indexData(){
        return "hello,Spring MVC";
    }
}

 我们可以显示的指定 @RequestMapping 来接收 POST的情况,如下所示:

package com.example.springmvcdome.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/web")
public class WebController {

    @RequestMapping("/index")
    public String index(){
        return "/index.html";
    }

    @ResponseBody
    @RequestMapping(value = "/indexData",method = RequestMethod.POST)
    public String indexData(){
        return "hello,Spring MVC";
    }
}

3.1.4 @GetMapping 和 PostMapping

get 请求的 3 种写法:

// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)
// 写法3
@GetMapping("/index")

post 请求的 3 种写法:

// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.POST)
// 写法3
@PostMapping("/index")

 

3.2 获取参数

3.2.1 传递单个参数

在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参,⽐如以下代码:

//spring接收参数
    @RequestMapping("/get2")
    public String get2(String name){
        return "name:" + name;
    }

程序的执⾏结果:

 传递多个参数

//spring接收多个参数
    @RequestMapping("/get3")
    public String get3(String name,Integer age){
        return "name:" + name + "|age:" + age;
    }

执行结果: 

 

3.2.2 传递对象

并且 Spring MVC 可以⾃动实现参数对象的赋值,⽐如 Person 对象:

package com.example.springmvcdome.model;

import lombok.Data;

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}

传递对象代码实现:

@RequestMapping("/get6")
    public String get6(Student student){
        return student.toString();
    }

最终执⾏结果:

 

3.2.3 表单参数传递/传递多个参数(非对象)

@RequestMapping("/get6")
    public String get6(Student student){
        return student.toString();
    }

 postman执行结果:

 

重要说明:当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置 是不影响后端获取参数的结果。

3.2.4 后端参数重命名(后端参数映射)

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致,⽐如前端传递了⼀个 time 给后端,⽽后端⼜是有 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现 这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值。

代码示例:

@RequestMapping("/get7")
    public String get7(@RequestParam("n") String name){
        return "name:" + name;
    }

执行结果:

 

3.2.5 设置参数必传@RequestParam

我们查看 @RequestParam 注解的实现细节就可以发现,注解实现如下:

 默认为必传参数

非必传参数设置

如果我们的实际业务前端的参数是⼀个⾮必传的参数,我们可以通过设置 @RequestParam 中的 required=false 来避免不传递时报错,具体实现如下:

@RequestMapping("/get7")
    public String get7(@RequestParam(name = "n",required = false) String name){
        return "name:" + name;
    }

3.2.6 @RequestBody 接收JSON对象

代码:

@RequestMapping("/get8")
    public String get8(@RequestBody Student student){
        log.info(student.toString());
        return student.toString();
    }

3.2.7 获取URL中参数@PathVariable

代码示例:

@RequestMapping("/get9/{shopid}")
    public String get9(@PathVariable Integer shopid){
        return "shopid" + shopid;
    }

postman中结果:

 

 

3.2.8 上传⽂件@RequestPart

代码示例:

@RequestMapping("/get10")
    public String get10(@RequestPart MultipartFile file) throws IOException {
        log.info(file.getOriginalFilename());
        file.transferTo(new File("D:/temp/"+file.getOriginalFilename()));
        return "success";
    }

postman中测试:

  

3.2.9 获取Cookie/Session/header

获取 Request 和 Response 对象

@RequestMapping("/param10")
public String param10(HttpServletResponse response, HttpServletRequest requ
est) {
 String name = request.getParameter("name");
 // 获取所有 cookie 信息
 Cookie[] cookies = request.getCookies();
 return name + " 你好.";
}

传统获取 header/cookie 

@RequestMapping("/param10")
@ResponseBody
public String param10(HttpServletResponse response, HttpServletRequest requ
est) {
 String name = request.getParameter("name");
 // 获取所有 cookie 信息
 Cookie[] cookies = request.getCookies();
 String userAgent = request.getHeader("User-Agent");
 return name + ":"+userAgent;
}

3.3 返回数据

默认请求下⽆论是 Spring MVC 或者是 Spring Boot 返回的是视图 (xxx.html),⽽现在都是前后端分离的,后端只需要返给给前端数据即可,这个时候我们就需要使⽤ @ResponseBody 注解了.

3.3.1 返回静态⻚⾯

创建前端⻚⾯ index.html

 

import com.example.demo.model.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/p")
public class PersonController {
 @RequestMapping("/index")
 public Object index(){
 // 执⾏业务...
 // 返回view -> index.html
 return "/index.html";
 }
}

 

3.3.2 返回 text/html

@RequestMapping("/m7")
@ResponseBody
public String method_7() {
 return "<h1>Hello,HTML~</h1>";
}

3.3.3 返回 JSON 对象

@RequestMapping("/get14")
    public Map<String,String> get14(){
        Map<String,String> map = new HashMap<>();
        map.put("k1","v1");
        map.put("k2","v2");
        map.put("k3","v3");
        map.put("k4","v4");
        return map;

    }

 

3.3.4 请求转发或请求重定向

forward VS redirect

return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:

  • forward 是请求转发;
  • redirect:请求重定向。

请求转发和重定向的使⽤对⽐:

package com.example.springmvcdome.controller;

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

@Controller
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/forward")
    public String forward(){
        return "forward:/index.html";
    }

    /**
     * 请求重定向
     * @return
     */
    @RequestMapping("/redirect")
    public String redirect(){
        return "redirect:/index.html";
    }
}

forward 和 redirect 具体区别如下:

1. 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。

2. 请求重定向地址发⽣变化,请求转发地址不发⽣变化。

3. 请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发 有可能造成原外部资源不能访问。

注意:

请求转发如果资源和转发的⻚⾯不在⼀个⽬录下,会导致外部资源不可访问

3.3.5 @ResponseBody 说明

@ResponseBody 返回的值如果是字符会转换成 text/html,如果返回的是对象会转换成 application/json 返回给前端。 @ResponseBody 可以⽤来修饰⽅法或者是修饰类,修饰类表示类中的所有⽅法都会返回 html 或者 json,⽽不是视图。

3.3.6 组合注解:@RestController

@RestController = @Controller + @ResponseBody

3.3.7 查看更多注解

官网:Request Mapping :: Spring Framework

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值