> 技术文档 > Spring Web MVC_spring-webmvc

Spring Web MVC_spring-webmvc

目录

一.什么是 MVC?

二.什么是Spring MVC

 三.使用Spring MVC

        1.建立连接

                @RequestMapping 路由映射

                 @RequestMapping注释定义详解:

                @RestController               

        2.请求

                a.传递单个参数,并且在@RequestMapping中限制请求方法是GET

                b.传递多个参数

                c.后端参数重命名

                d.传递对象

                e.传递数组

                f.传递集合

                h.传递Json数据 

                i.获取url中的参数

                j.上传文件

                k.Cookie和Session 

                        获取Cookie:

                获取Session: 

                获取Header: 

        3.响应

                返回静态页面@Controller:

                详解@RestController和@Controller:

                返回数据@ResponsBody:

                返回HTML代码段:

                        返回Json:

                        设置返回的状态码:

                设置响应的Header:


一.什么是 MVC?

        MVC 是一种软件架构模式,是一种思想

                全称是 Model View Controller,它是软件工程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分:

                        M:Model(模型)

                        V: View(视图)

                        C: Controller(控制器)

                它的核心思想是将应用程序分为三个部分,各司其职,从而让代码结构更清晰、职责更明确、便于维护和扩展。    

二.什么是Spring MVC

        MVC是一种软件架构设计思想,而Spring MVC是MVC这种设计思想的具体实现。

        Spring Web MVC:Spring Web MVCSpring Framework 的一个子模块,它是基于 MVC(Model-View-Controller)设计模式的 Web 应用开发框架。

        Spring Web MVC 是构建在 Servlet API 上的原始 Web 框架,从一开始就包含在 Spring 框架中。正式名称“Spring Web MVC”来自其源模块的名称,但它通常被称为“Spring MVC”。

                现在的后端人员并不设计前端页面的开发,所有View层现在基本上不返回页面了,现在View层返回的是数据。 

 三.使用Spring MVC

        这个就是Spring MVC框架:

          使用Spring MVC主要分为三步:建立连接,请求和响应 

        1.建立连接

                @RequestMapping 路由映射

                        用将一个HTTP请求路径,映射到方法上,任何HTTP请求方式都可以接收,但是GET方法默认从查询参数中获取,POST方法默认从Body中获取。

                当用户输入127.0.0.1:8080/HelloController/hello,就可以调用这个方法 。 

                注意:

                        @RequestMapping的URL路径最前面加不加/都可以,Spring程序启动时,会进行判断,如果前面没有/,Spring会自动拼接一个/:

@RequestMapping(\"user\")@RestControllerpublic class UserController { @RequestMapping(\"sayHi\") public String sayHi(){ return \"hello,Spring MVC\"; }}

                        使用/可以形成多级路径:

@RequestMapping(\"/user/m1\")@RestControllerpublic class UserController { @RequestMapping(\"/say/hi\") public String sayHi(){ return \"hello,Spring MVC\"; }}
                 @RequestMapping注释定义详解:

                @RestController               

                        既然@RequestMapping是用于路由映射的注解,那么@RestController是干什么的呢 ?

                        Spring会对所有的类进⾏扫描, 如果类加了注解@RestController, Spring才会去看这个类里面的方法有没有加 @RequestMapping 这个注解。

        2.请求

                Postman的安装及其使用https://blog.csdn.net/weixin_52159554/article/details/149093259?sharetype=blogdetail&sharerId=149093259&sharerefer=PC&sharesource=weixin_52159554&spm=1011.2480.3001.8118

                a.传递单个参数,并且在@RequestMapping中限制请求方法是GET
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;//设置公共路由为ParamController,且限定该方法只能由GET请求方法调用@RequestMapping(value = \"/ParamController\", method = RequestMethod.GET)@RestControllerpublic class ParamController { @RequestMapping(\"/paramOne\") public String paramOne(String param){ return param; }}

                在限制请求方法为GET的时候在使用POST方法请求时 :

                        当使用GET方法请求时: 

                                在请求时,使用和路径映射方法的形参相同名称的查询参数,后端就可以接收到响应的值:

                b.传递多个参数
//2.传递多个参数 @RequestMapping(\"/paramTwo\") public String paramTwo(String param1,String param2 ){ return \"接收到的参数是param1:\"+param1+\",param2:\"+param2; }

                        如果使用基本数据类型,如果在请求的时候没有传递对应的参数,在会报错: 

                        如果使用包装类,如果没有传递对应的查询参数,则会自动赋值为null: 

                c.后端参数重命名
//3.后端参数重命名 @RequestMapping(\"/paramThree\") public String paramThree(@RequestParam(\"param1\") String str, Integer param2){ return \"接收到的参数是str:\"+str+\",param2:\"+param2; }

                        如果对参数进行了重命名,这个参数就变为必传参数了,此时如果不传这个参数是会报错的: 

                        将@RequestParam 的required设置为false就可以了,此时这个参数就不是必传参数了: 

                d.传递对象

                       此时只需要创建一个用于接收参数类,并且用其接收查询参数,Spring会将接收到的查询参数,封装为方法中指定的对象。

                       对象中的成员变量可以不传递参数,会有默认的初始化的。

//4.传递一个对象 @RequestMapping(\"/paramFour\") public String paramFour(ParamInfo paramInfo){ return \"接收到的参数是:\" + paramInfo.toString(); }

                        定义一个用于接收查询参数的类: 

public class ParamInfo { private String param1; private String param2; public String getParam1() { return param1; } public void setParam1(String param1) { this.param1 = param1; } public String getParam2() { return param2; } public void setParam2(String param2) { this.param2 = param2; } @Override public String toString() { return \"ParamInfo{\" + \"param1=\'\" + param1 + \'\\\'\' + \", param2=\'\" + param2 + \'\\\'\' + \'}\'; }}

                e.传递数组

                        此时只需要在请求时将,传递的查询参数全部设置为指定的数组名就可以了:

//5.传递一个数组 @RequestMapping(\"/paramFive\") public String paramFive(String[] param1){ return \"接收到的参数是:\" + Arrays.toString(param1); }

                        还可以:         

                                谷歌浏览器可以这样写,其他浏览器可能需要转义字符。

                f.传递集合
 //6.传递一个集合 @RequestMapping(\"/paramSix\") public String paramSix(@RequestParam List paramList){ return \"接收到的参数是:\" + paramList; }

                        加@RequestParam Spring会将接收到的查询参数,封装为一个集合: 

                h.传递Json数据 

                        Json本质上就是一个表示对象的字符串,所以在后端通常使用对象来接收Json数据。

 //7.传递Json @RequestMapping(\"/paramSeven\") public String paramSeven(@RequestBody ParamInfo paramInfo){ return \"接收到到参数是:\" + paramInfo.toString(); }

                i.获取url中的参数

                        单个参数:

 //8.获取url中的参数 @RequestMapping(\"/paramEight/{param}\") public String paramEight(@PathVariable Integer param){ return \"接收到的参数是:\" + param; }

                        多个参数: 

//8.获取url中的参数 @RequestMapping(\"/paramEight/{param1}/{param2}\") public String paramEight(@PathVariable Integer param1,@PathVariable Integer param2){ return \"接收到的参数是:\" + param1; }

                j.上传文件
@RequestMapping(\"/paramNine\") public boolean paramNine(@RequestPart MultipartFile file) throws IOException { file.transferTo(new File(\"E:/\" + file.getOriginalFilename())); return true; }

                k.Cookie和Session 

                Cookie和Sessionhttps://blog.csdn.net/weixin_52159554/article/details/148929907?spm=1001.2014.3001.5502

                        获取Cookie:

                                使用Servlet获取:

 @RequestMapping(\"/getCookieOne\") public String getCookieOne(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { System.out.println(cookie.getName() + \":\" + cookie.getValue()); } return \"获取Cookie成功!\"; }

                HttpServletRequest 和 HttpServletResponse是Spring的内置对象: 

                        注释的方式获取:

@RequestMapping(\"/getCookieTwo\") public String getCookieTwo(@CookieValue String aaa, @CookieValue String bbb, @CookieValue String ccc){ return \"aaa:\" + aaa + \" \" +\"bbb:\" + bbb + \" \" +\"ccc:\" + ccc; }

                获取Session: 

                        Servlet方式:

                                伪造Session:

                                        在服务器中Session是可以保存在内存或者数据库中的:

@RequestMapping(\"/setSession\") public boolean setSession(HttpServletRequest request){ HttpSession session = request.getSession(); if(session != null){ session.setAttribute(\"userName\", \"张三\"); return true; } return false; }

                                        获取Session: 

 @RequestMapping(\"/getSessionOne\") public String getSessionOne(HttpServletRequest request){ HttpSession session = request.getSession(false); if(session != null){ String userName = (String) session.getAttribute(\"userName\"); return \"获取到的Session是:\" + userName; } return null; }

                         注释的方式获取Session:

                                伪造Session:

@RequestMapping(\"/setSession\") public boolean setSession(HttpServletRequest request){ HttpSession session = request.getSession(); if(session != null){ session.setAttribute(\"userName\", \"张三\"); session.setAttribute(\"userAge\", 30); return true; } return false; }

                                获取Session: 

@RequestMapping(\"/getSessionTwo\") public String getSessionTwo(@SessionAttribute String userName,@SessionAttribute String userAge){ return userName + \":\" + userAge; }
@RequestMapping(\"/getSessionThree\") public String getSessionThree(HttpSession session){ if(session != null){ String userName = (String) session.getAttribute(\"userName\"); Integer userAge = (Integer) session.getAttribute(\"userAge\"); return userName + \":\" + userAge; } return null; }

                获取Header: 
@RequestMapping(\"/getHeaderOne\") public String getHeader(HttpServletRequest request){ String userAgent = request.getHeader(\"user-agent\"); return \"userAgent\" + userAgent; } @RequestMapping(\"/getHeaderTwo\") public String getHeaderTwo(@RequestHeader(\"User-Agent\") String userAgent){ return \"userAgent\" + userAgent; }

        3.响应

                返回静态页面@Controller:

                        在Spring Boot项目中,网页一般保存在:

                        HTML代码如下:

   Document 
Hello,Spring MVC,我是index页面。

                        当我们将HTML网页保存在这个路径后,在浏览器中输入相应的ip地址和端口号加上网页文件名,是可以访问到这个静态页面的: 

                        此时的后端代码是:

@RequestMapping(\"/htmlController\")@RestControllerpublic class StaticHtmlController { @RequestMapping(\"/html\") public String getHtml(){ return \"/index.html\"; }}

                        此时的运行结果是:

                        我们最开始的期望是获取静态的HTML页面,结果却发现,页面未正确返回,http把“/index.html”当做了http响应正文的数据,那Spring MVC如何才能识别出来index.html 是一个静态页面呢?

                        此时需要将@RestController替换成@Controller:

                详解@RestController和@Controller:

                        @Controller:

                                在最一开始,对于一个网站,几乎都是前后端结合开发的,所以后端也需要返回页面,但是随着发展,网站的功能和规模越来越大,在结合开发就会导致后期维护非常的繁琐,所以就将前后端分离开发了,所以现在后端只需要在原来返回视图的地方返回数据就可以了。 

                                所以我们在前面使用的@RestController是用于返回数据的, 我们观察这个注释的定义可以发现:

                                除了上面的元注释,@RestController = @Controller + @ResponsBody。

                                @Controller: 定义一个控制器,Spring框架启动时加载,把这个对象交给Spring管理。

                                @ResponseBody:定义返回的数据格式为非视图,返回一个test/html信息。

               所以当Controller层的类中的方法全都是返回数据的时候,直接在类上加@RestController就可以了,如果一个类中既有静态页面又有数据,就使用@Controller + @ResponsBody这两个注释配合使用。 

                @Controller只能用于修饰类。

                使用了@Controller就不可以在使用@RestController了。

                如果在既有数据返回又有页面返回的类中,只使用了@Controller,此时访问返回数据的方法时,就会报错,因为没有@ResponsBody注释,Spring就会认为这个方法返回的是页面,从而就会去找这个页面,但是是找不到的,所以就会报错。

                

                返回数据@ResponsBody:

                        @ResponsBody既可以修饰方法又可以修饰类,修饰类的时候就表面这个类下面的方法都是返回数据的,修饰方法时只表示这个方法是返回数据的。

                        @RestponsBody不可以单独使用。

                        此时这种情况是因为,没有@Controller或RestController来告诉Spring容器,你需要来帮我托管这个类,所以Spring压根就不知道在方法中调用了@RequestMapping,所以就会导致找不到网页。 

                返回HTML代码段:

                        当后端返回String类型的数据时,会自动变为HTML代码。

                        后端在返回数据时,如果数据中包含HTML代码,也会被浏览器解析:

@RequestMapping(\"/HelloController\")@Controllerpublic class HelloController { @ResponseBody @RequestMapping(\"/hello\") public String sayHello() { return \"

Hello,HTML~

\"; }}

                        返回Json:

                                当返回的数据是对象或者map的时候,会自动变为Json字符串:

import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;@RequestMapping(\"/HelloController\")@Controllerpublic class HelloController { @ResponseBody @RequestMapping(\"/hello\") public HashMap sayHello() { HashMap map = new HashMap(); map.put(\"hello\", \"world\"); map.put(\"sayHello\", \"sayHello\"); map.put(\"sayGoodbye\", \"sayGoodbye\"); return map; }}

                        设置返回的状态码:
import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;@RequestMapping(\"/HelloController\")@Controllerpublic class HelloController { @ResponseBody @RequestMapping(\"/hello\") public String sayHello(HttpServletResponse response) { response.setStatus(404); return \"设置状态码成功\"; }}

                设置响应的Header:

@RequestMapping(\"/HelloController\")@Controllerpublic class HelloController { @ResponseBody @RequestMapping(value = \"/hello\") public String sayHello() { return \"{\'ok\':1}\"; }}

@RequestMapping(\"/HelloController\")@Controllerpublic class HelloController { @ResponseBody @RequestMapping(value = \"/hello\",produces = \"application/json;charset=utf-8\") public String sayHello() { return \"{\'ok\':1}\"; }}