当前位置: 首页 > news >正文

第七章:SpringMVC中

第七章:SpringMVC中

7.1:SpringMVC的视图

SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户SpringMVC视图的种类很多,默认有转发视图和重定向视图。

​ 当工程引入jstl的依赖,转发视图会自动转换为JstlView,若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后得到的是ThymeleafView

  1. ThymeleafView

    ​ 当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀。后缀所得到的最终路径,会通过转发的方式实现跳转。

    @RequestMapping("/test/view/thymeleaf")
    public String testThymeleafView() {return "success";
    }
    

    在这里插入图片描述

  2. 转发视图

    SpringMVC中默认的转发视图是InternalResoutceViewSpringMVC中创建转发视图的情况:当控制器方法中所设置的视图名称以forward:为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀forward:去掉,剩余部分作为最终路径通过转发的方式实现跳转。

    @RequestMapping("/test/view/forward")
    public String testInternalResourceView() {return "forward:/test/model";
    }
    

    在这里插入图片描述

  3. 重定向视图

    SpringMVC中默认的重定向视图是RedirectView,当控制器方法中所设置的视图名称以redirect:为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀redirect:去掉,剩余部分作为最终路径通过重定向的方式实现跳转。

    ​ 重定向视图在解析是,会先将redirect:前缀去掉,然后会判断剩余部分是否以/开头,若是则会自动拼接上下文路径。

    @RequestMapping("/test/view/redirect")
    public String testRedirectView() {return "redirect:/test/model";
    }
    

    在这里插入图片描述

  4. 视图控制器view-controller

    当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理方法使用view-controller标签进行表示。

    <!-- 在Springmvc.xml中配置 -->
    <!-- 开启mvc的注解驱动 -->
    <mvc:annotation-driven /><!-- 视图控制器:为当前的请求直接设置视图名称实现页面跳转若设置视图监控器,则只有视图监控器所设置的请求会被处理,其他的请求将全部404,此时必须在配置一个开启mvc的注解驱动的标签-->
    <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
    

7.2:RESTful

  1. RESTful简介

    RESTRepresentational State Transfer,表现层资源状态转移。

    • 资源

      ​ 资源是一种看待服务器的方式,即,将服务器看作由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。一个资源可以有一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。

    • 资源的表述

      ​ 资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器之间转义。资源的表述可以有多种格式。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。

    • 状态转移

      ​ 在客户端和服务器端之间转义(transfer)代表资源状态的表述。通过转移和操作资源的表述,来间接实现操作资源的目的。

  2. RESTful的实现

    ​ 具体说,就是HTTP协议里面,四个表示操作方式的动词:GETPOSTPUTDELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。

    REST风格提倡URL地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为URL地址的一部分,以保证整体风格的一致性。

    操作传统方式REST风格
    查询操作getUserById?id=1user/1 —> get请求方式
    保存操作saveUseruser ----> post请求方式
    删除操作deleteUser?id=1user/1 —> delete请求方式
    更新操作updateUseruser —> put请求方式
  3. HiddenHttpMethodFilter

    ​ 创建一个新的模块,spring_mvc_rest_15,复用spring_mvc_demo_14的依赖、web.xmlspringmvc.xml配置文件、html页面。

    • 使用REST风格完成查询所有的用户信息

      // @RequestMapping(value = "/user", method = RequestMethod.GET)
      @GetMapping("/user")
      public String getAllUser() {System.out.println("查询所有的用户信息 ----> /user ----> get");return "success";
      }
      
    • 使用REST风格完成查询单个的用户信息

      // @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
      @GetMapping("/user/{id}")
      public String getUserById(@PathVariable("id") Integer id) {System.out.println("根据id查询用户信息 ----> /user/" + id + " ----> get");return "success";
      }
      
    • 使用REST风格完成添加用户信息

      // @RequestMapping(value = "/user", method = RequestMethod.POST)
      @PostMapping("/user")
      public String insertUser() {System.out.println("添加用户信息 ----> /user ----> post");return "success";
      }
      
    • 使用REST风格完成修改用户信息

      ​ 由于浏览器只支持发送getpost方式的请求,若要发送putdelete请求,需要在web.xml中配置一个过滤器HiddenHttpMethodFilter,配置了过滤器之后,发送的请求要满足两个条件,才能将请求方式转换为putdelete

      1. 当前请求的请求方式必须为post
      2. 当前请求必须传输请求参数_method_method的值才是最终的请求方式。
      <!-- 设置处理请求方式的过滤器 -->
      <filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
      </filter>
      <filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
      </filter-mapping>
      
      // @RequestMapping(value = "/user", method = RequestMethod.PUT)
      @PutMapping("/user")
      public String updateUser() {System.out.println("修改用户信息 ----> /user ----> put");return "success";
      }
      
      <form th:action="@{/user}" method="post"><input type="hidden" name="_method" value="put"><input type="submit" value="修改用户信息">
      </form>
      
    • 使用REST风格完成删除用户信息

      // @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
      @DeleteMapping("/user/{id}")
      public String deleteUser(@PathVariable("id") Integer id) {System.out.println("删除用户信息 ----> /user/" + id + " ----> put");return "success";
      }
      
    • HiddenHttpMethodFilter原理

      public class HiddenHttpMethodFilter extends OncePerRequestFilter {private static final List<String> ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));public static final String DEFAULT_METHOD_PARAM = "_method";private String methodParam = DEFAULT_METHOD_PARAM;public void setMethodParam(String methodParam) {Assert.hasText(methodParam, "'methodParam' must not be empty");this.methodParam = methodParam;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {HttpServletRequest requestToUse = request;if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {String paramValue = request.getParameter(this.methodParam);if (StringUtils.hasLength(paramValue)) {String method = paramValue.toUpperCase(Locale.ENGLISH);if (ALLOWED_METHODS.contains(method)) {requestToUse = new HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter(requestToUse, response);}private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {private final String method;public HttpMethodRequestWrapper(HttpServletRequest request, String method) {super(request);this.method = method;}@Overridepublic String getMethod() {return this.method;}}
      }
      

7.3:SpringMVC处理ajax请求

创建一个新的模块,spring_mvc_ajax_16,复用spring_mvc_rest_15的依赖、web.xmlspringmvc.xml配置文件。

  1. @RequestBody

    @RequestBody可以获取请求体信息,使用@RequestBody注解标识控制器方法的形参,当前请求的请求体就会为当前注解锁标识的形参赋值。

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head><meta charset="UTF-8"><title>首页</title>
    </head>
    <body>
    <div id="app"><h1>index.html</h1><input type="button" value="测试SpringMVC处理ajax" @click="testAjax()">
    </div><script type="text/javascript" th:src="@{/js/vue.js}"></script>
    <script type="text/javascript" th:src="@{/js/axios.min.js}"></script>
    <script type="text/javascript">var vue = new Vue({el: "#app",methods: {testAjax() {axios.post("/SpringMVC/test/ajax?id=1001",{username:"admin", password:"123456"}).then(response => {console.log(response.data);});}  }})
    </script>
    </body>
    </html>
    
    @RequestMapping("/test/ajax")
    public void testAjax(Integer id,@RequestBody String requestBody,HttpServletResponse response)throws IOException{System.out.println("requestBody: " + requestBody);System.out.println("id: " + id);response.getWriter().write("hello, axios");
    }
    
  2. @RequestBody获取json格式的请求参数

    使用@RequestBody注解将json格式的请求参数转换为java对象,需要以下步骤:

    • 导入jackson的依赖

      <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version>
      </dependency>
      
    • SpringMVC的配置文件中设置:<mvc:annotation-driven />

    • 在处理请求的控制器方法的形参位置,直接设置json格式的请求参数要求转换的java类型的形参,使用@RequestBody注解标识即可。

    <input type="button" value="使用@RequestBody处理json格式的请求参数" @click="testRequestBody()"><br>
    
    testRequestBody() {axios.post("/SpringMVC/test/RequestBody/json",{username: "admin", password: "123456", age: 23, gender: "男"}).then(response=> {console.log(response.data);});
    }
    
    // 根据上面传递的参数自行创建User实体类
    @RequestMapping("/test/RequestBody/json")
    public void testRequestBody(@RequestBody User user, HttpServletResponse response) throws IOException {System.out.println(user);response.getWriter().write("hello, RequestBody");
    }
    
  3. @ResponseBody

    @ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器。

    @RequestMapping("/test/ResponseBody")
    @ResponseBody
    public String testResponseBody() {return "success";
    }
    
    <a th:href="@{/test/ResponseBody}">测试@ResponseBody注解响应浏览器数据</a><br>
    
  4. @ResponseBody响应浏览器josn数据

    使用@ResponseBody注解响应浏览器json格式的数据,需要以下步骤:

    • 导入jackson的依赖
    • SpringMVC的配置文件中设置:<mvc:annotation-driven />
    • 将需要转换为json字符串的java对象直接作为控制器方法的返回值,使用@ResponseBody注解标识控制器方法就可以将java对象直接转换为json字符串,并响应到浏览器。
    • 常用的java对象转换为json的结果
      1. 实体类 ——> json对象
      2. map ——> json对象
      3. list ——> list数组
    <input type="button" value="使用@ResponseBody注解响应json格式的数据" @click="testResponseBody()"><br>
    
    testResponseBody() {axios.post("/SpringMVC/test/ResponseBody/json").then(response => {console.log(response.data);})
    }
    
    @RequestMapping("/test/ResponseBody/json")
    @ResponseBody
    public List<User> testResponseBodyJson() {User user1 = new User(1001, "admin1", "123456", 20, "男");User user2 = new User(1002, "admin2", "123456", 20, "男");User user3 = new User(1003, "admin3", "123456", 20, "男");List<User> list = Arrays.asList(user1, user2, user3);return list;
    }
    
  5. @RestContrller注解

    @RestContrller注解是SpringMVC提供的一个复合注解,标识在控制器的类上,就相当于为添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解。

7.4:文件上传和下载

  1. 文件下载

    ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文使用ResponseEntity实现下载文件的功能。

    @RequestMapping("/test/down")
    public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {//获取ServletContext对象ServletContext servletContext = session.getServletContext();//获取服务器中文件的真实路径String realPath = servletContext.getRealPath("img");realPath = realPath + File.separator + "1.jpg";//创建输入流InputStream is = new FileInputStream(realPath);//创建字节数组,is.available()获取输入流所对应文件的字节数byte[] bytes = new byte[is.available()];//将流读到字节数组中is.read(bytes);//创建HttpHeaders对象设置响应头信息MultiValueMap<String, String> headers = new HttpHeaders();//设置要下载方式以及下载文件的名字headers.add("Content-Disposition", "attachment;filename=1.jpg");//设置响应状态码HttpStatus statusCode = HttpStatus.OK;//创建ResponseEntity对象ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);//关闭输入流is.close();return responseEntity;
    }
    
  2. 文件上传

    ​ 文件上传要求form表单的请求方式必须为post,并且添加enctype="multipart/form-data"SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息。

    • 添加依赖

      <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
      <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version>
      </dependency>
      
    • SpringMVC的配置文件中添加配置

      <!-- 配置文件上传解析器 id必须为multipartResolver -->
      <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      </bean>
      
    • 控制器方法

      @RequestMapping("/test/up")
      public String testUp(MultipartFile photo, HttpSession session) throws IOException {//获取上传的文件的文件名String fileName = photo.getOriginalFilename();//处理文件重名问题String hzName = fileName.substring(fileName.lastIndexOf("."));String uuid = UUID.randomUUID().toString();fileName = uuid + hzName;//获取ServletContext对象ServletContext servletContext = session.getServletContext();//获取当前工程下photo目录的真实路径String photoPath = servletContext.getRealPath("photo");//创建photoPath所对应的File对象File file = new File(photoPath);//判断file所对应目录是否存在if(!file.exists()){file.mkdir();}String finalPath = photoPath + File.separator + fileName;//上传文件photo.transferTo(new File(finalPath));return "success";
      }
      
http://www.lryc.cn/news/107814.html

相关文章:

  • MySQL数据库——DQL操作——基本查询
  • Electron 开发,报handshake failed; returned -1, SSL error code 1,错误
  • 知识区博主转型——兼做知识区和改造区博主!!!!!
  • Resnet与Pytorch花图像分类
  • 【NLP概念源和流】 03-基于计数的嵌入,GloVe(第 3/20 部分)
  • 【React】关于组件之间的通讯
  • item_get-小红薯-商品详情
  • 网络安全进阶学习第十课——MySQL手工注入
  • 2.3 网络安全协议
  • Apache Flink概述
  • django使用mysql数据库
  • MongoDB文档--基本概念
  • 【TypeScript】TS入门及基础学习(一)
  • Dockerfile构建LNMP镜像(yum方式)
  • Flink Windows(窗口)详解
  • AssetBundle学习
  • CompletableFuture原理与实践
  • 8.3 作业
  • c# COM组件原理
  • Java POI 百万规模数据的导入和导出
  • 如何快速用PHP取短信验证码
  • CloudStack 的 AsyncJobManagerImpl
  • OAuth机制_web站点接入微软azure账号进行三方登录
  • Linux ALSA音频工具aplay、arecord、amixer的使用方法
  • 编写一个最简单的Linux服务端和客户端程序
  • openKylin顺利加入RISC-V 基金会,推动架构芯片与操作系统协同发展
  • SSM(Vue3+ElementPlus+Axios+SSM前后端分离)【二】
  • 出现一次的数字(其他数字出现三次,两次)
  • Rust- 智能指针
  • 什么是微服务