飞道的博客

SpingMVC详解

368人阅读  评论(0)

SpringMVC

1. SpringMVC是什么?

SpringMVC全称Spring Web MVC,Spring Web MVC又简称Spring Web或Spring MVC,它是一个基于Servlet API的框架

一个经典问题:Spring/SpringBoot/SpringMVC的区别

答:我们说的Spring就是Spring farmework ,Spring farmework它里面包含很多模块,它的最早核心功能就是IOC容器,能够去除代码的一个耦合性,SpringBoot在创建之初的目的就是为Spring服务的,就是为了快速开发Spring框架嘛,相比于Spring来说,SpringBoot有很多优点,比如说它内置了tomcat容器,可以更容易地添加依赖,发布也很简单,可以摆脱xml文件,它将Spring的功能升上了一个层次,所以后面大家都很喜欢SpringBoot了,都用SpringBoot了,后面很多插件也都是专门为SpringBoot去做的,但是SpringBoot底层还是基于Spring实现的;SpringMVC全称Spring Web MVC,Spring Web MVC又简称Spring Web或Spring MVC,它是一个基于Servlet API的框架,SpringMVC是随着Spring的诞生而诞生的,它最早是Spring里的一个外部模块而已,就是说Spring它有很多很多模块,其中就有一个是基于http协议,那些request,response这些http请求,这个就是SpringMVC

1.1 MVC定义

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

  • Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。

  • View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。

  • Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据, 控制⽤户输⼊,并向模型发送数据。

最早SpringMvc设计时是返回一个视图,所以默认是返回一个静态页面;
现在前后端分离了,要返回数据了,现在要加注解才能返回数据,

MVC和SpringMVC的联系

MVC是一种思想,SpringMVC是对MVC思想的具体实现,总结来说SpringMVC是一个实现了MVC模式并继承了Servlet API的web框架。

1.2 创建SpringMVC项目

在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架,如下图所 示:

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

3.SpringMVC的主要三个功能

  1. 连接的功能:将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。

  2. 获取参数的功能:⽤户访问的时候会带⼀些参数,在程序中要想办法获取到参数。

  3. 输出数据的功能:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤户。

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

3.1SpringMVC的连接功能

在 Spring MVC 中使⽤ @RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作⽤。 接下来要实现的功能是访问地址:http://127.0.0.1:8080/web/hi,能打印“Hi springMvc”信息。

代码如下:

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")//路由注册,当使用/web可以访问到当前类
public class WebController {
   
    @RequestMapping("/hi")//路由注册,当使用/web/hi可以访问到当前方法
    public Object sayHi() {
   
        return "Hi springMvc";
    }
}

3.1.2注解介绍

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

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

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

@ResponseBody 表示当前类返回的是非静态页面,而是数据

@Controller 表示是一个控制器,要在spring启动时加载并注册

@ResponseBody和@Controller有一个组合注解@RestController,使用@RestController可以代替@ResponseBody和@Controller

3.1.3 @RequestMapping默认可以接收所有http请求

如果没有指定请求方式,@RequestMapping将接收GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT所有的HTTP请求方式。

下面展示 @RequestMapping设置只接收post请求

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
    @RequestMapping(value = "/hello" ,method = RequestMethod.POST)
    public Object sayHello() {
   
        return "Hi SpringMVC";
    }
}

@RequestMapping(value = “/hello” ,method = RequestMethod.POST),这个是关键

3.1.4@GetMapping 和 PostMapping只能默认是GET和POST

GET请求三种写法

// 写法1

@RequestMapping("/index")

// 写法2

@RequestMapping(value = "/index",method = RequestMethod.GET)

// 写法3

@GetMapping("/index")

Post请求两种写法

// 写法1

@RequestMapping(value = "/index",method = RequestMethod.POST)

// 写法2

@PostMapping("/index")

3.2 获取参数功能

3.2.1 传递单个参数

写法一:基于servlet的request来获取参数(不推荐这么写)

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
    
    @RequestMapping("/get1_0")
    public Object getParam1_0(HttpServletRequest request, HttpServletResponse response) {
   
        return "Hi" + request.getParameter("name");//通过servlet里的request获取参数,但是不推荐这样用
    }
}

特殊说明:在Spring MVC中默认内置隐藏了两个参数,一个是Request(HttpServletRequest),一个是Response(HttpServletResponse)对象,所以如果想要使用这两个参数,只需要在方法中申明即可获取到

写法二:在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参(推荐写法)

⽐如以下代码:

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
   
    @RequestMapping("/get1")
    public Object getParam1(Integer age) {
   
       return "value: "+age;
    }
}

3.2.2 获取多个参数

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
    
    @RequestMapping("/get2")
    public Object getParam2(String name,Integer age) {
        return "name:: "+name + " | age:"+ age;
    }
}

Spring MVC中当传递多个参数的时候,传递参数的顺序是不影响程序的执行的,获取参数结果和参数的名称有关,和顺序无关

3.2.3获取对象

Spring MVC 可以⾃动实现参数对象的赋值,但是要设置getter和setter方法,但是只要加@Data注解就自动加了

@Data
public class Student {
   
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
    
    @RequestMapping("/get3")
    public String getParam3(Student student) {
   
        return student.toString();
    }
}

在没有其他注解下,传的参数要和Student里属性名字一样

3.2.4获取表单参数

参数请求的类型:

  • URL传参
  • ajax传参
  • form表单传参

这里以form表单传参为例

用参数来接收form表单的参数

<form method="get" action="web/login">
        <div>
            <h1>登录</h1>
            用户:<input name="name"><br>
            密码:<input name="password"><br>
            <input type="submit" value="提 交">
        </div>
    </form>
@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
   
   @RequestMapping("/login")
    public String login(String name,String password) {
   
        return "<h1>用户名:" +name+" | 密码:"+password+"</h1>";
    }
}

用对象来获取form表单的参数

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
   
    @RequestMapping("/req")
    public String req(User user) {
   
        return user.toString();
    }
}

3.2.5@RequestBody接收JSON对象

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
   
    @RequestMapping("/login3")
    public Map<String,Object> login3(@RequestBody User user) {
   
        Map<String,Object> result = new HashMap<>();
        result.put("name",user.getName());
        result.put("password",user.getPassword());
        return result;
    }
    
}


 

@RequestBody可以用来获取JSON对象

3.2.6 上传文件@RequestPart

使用postman上传文件

后端写代码来接收

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
 
    @RequestMapping("/req2")
    public String req2(String name, @RequestPart("myfile")MultipartFile file) throws IOException {
   
        //保存文件
        file.transferTo(new File("D:/1/img.pong"));
        return "success";
    }

}

3.2.7获取Cookie/Session/Header

浏览器会默认将当前网站的所有cookie发送给后端

原因:http协议无状态

传统获取 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;
}

使用注解获取 Cookie—@CookieValue

@Controller //我是一个控制器,我要在spring启动时加载并注册
@ResponseBody //当前类返回的是非静态页面,因为最早springmvc设计时是返回一个视图,所以默认是返回一个静态页面,要加注解才能返回数据;但是现在前后端分离了,要返回数据了
@RequestMapping("/web")
public class WebController {
   
   
    @RequestMapping("/cookie")
    public String cookie(@CookieValue("name") String name) {
   
        return "cookie"+name;

    }

}

获取Header——@RequestHeader

@RequestMapping("/header")

public String header(@RequestHeader("User-Agent") String userAgent) {
   
 return "userAgent:"+userAgent;
}

Session 存储和获取

Session 存储和 Servlet 类似,是使⽤ HttpServletRequest 中获取的,如下代码所示:

 @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request) {
   
        // 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建session

        HttpSession session = request.getSession(true);
        if(session!=null){
   
            session.setAttribute("username","小卢");
        }
        return "session 存储成功";
    }

获取Session可以使⽤ HttpServletRequest

@RequestMapping("/sess")
@ResponseBody

public String sess(HttpServletRequest request) {
   
 // 如果 session 不存在,不会⾃动创建

 HttpSession session = request.getSession(false);
 String username = "";
 if(session!=null && session.getAttribute("username")!=null){
   
 username = (String) session.getAttribute("username");
 }
 return "username:"+username;
}

也可以使用注解@SessionAttribute

 @RequestMapping("/getSession")
    public String getSession(@SessionAttribute(value = "username",required = false) String name) {
   
        return "username: " + name;
    }

**@SessionAttribute(value = “username”,required = false **:required不设置它,默认是true,如果这个session不存在会报错;如果设置为false,session没有就没有了,不会去报错

3.2.8 使用参数重命名

@RequestMapping("/gettime")
    public String getTime(@RequestParam(value = "t",required = false)String time) {
   
        return "time: "+time;//此时只能识别t参数,并将参数t的值,设置给time变量,此时即使使用time参数,也是读取不到前端的参数的,它现在只认参数名为t的参数
    }

required设置参数是否必传,如果是true就需要必传,不然就会报错;设置为false不传不会报错

3.2.9 特殊的URL地址和获取参数的方式:使用@PathVariable

从url中获取参数

@RequestMapping("/login4/{name}/{password}")
    public String login4(@PathVariable("name") String name,@PathVariable("password") String password) {
   
        return "name: "+name+" | password"+ password;
    }

3.3返回数据

返回数据比较简单,基本上上面获取完代码后都会返回,这里就不展开,主要讲请求重定向和请求转发

3.3.1请求重定向和请求转发

forward VS redirect

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

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

@RequestMapping("/index")

public String index(){
   
 return "redirect:/index.html";
}

// 请求转发

@RequestMapping("/index2")

public String index2(){
   
 return "forward:/index.html";
}


 

举个例子说明一下forward和redirect吧

比如说,小卢同学告诉他妈妈说我想要买新键盘,如果小卢他妈妈说好,我帮你去买,这就是forward请求转发;如果他妈妈给他个地址让他自己去买,这就是请求redirect重定向

也就是说,转发是服务器帮转的,而重定向是让浏览器重新请求另一个地址

forward和redirect具体区别:

  1. 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务端转发
  2. 请求重定向地址发生变化,请求转发地址不发生变化
  3. 请求重定向与直接访问新地址效果一样,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问(请求转发如果资源和转发的⻚⾯不在⼀个⽬录下,会导致外部资源不可访问)

举个例子forward不能访问到外部资源

@Controller

@RequestMapping("/user")

public class UserController {
   
 @RequestMapping(value = "/index")
 public String sayHi(){
   
 return "forward:/index.html";
 }
}

在目录中当请求转向到index.html后,因为hello.js和index.html不在同一个目录,所以会导致获取不到hello.js;改成请求重定向就能获取到


转载:https://blog.csdn.net/HBINen/article/details/128184765
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场