第七章:SpringMVC中

news2024/11/17 17:38:39

第七章: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;
      	}
      
      	@Override
      	protected 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;
      		}
      		@Override
      		public 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.coloradmin.cn/o/831626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react中PureComponent的理解与使用

一、作用 它是一个纯组件&#xff0c;会做一个数据的浅比较&#xff0c;当props和state没改变的时候&#xff0c;不会render重新渲染&#xff0c; 改变后才会render重新渲染&#xff0c;提高性能。 二、使用 三、注意 它不能和shouldComponentUpdate生命周期同时使用。因为它…

【网络基础进阶之路】路由器间的静态综合详解

PS&#xff1a;本实验基于华为的eNSP模拟软件进行 题目内容&#xff1a; 完成步骤&#xff1a; 1、对192.168.1.0/24进行子网划分 2、对每一个路由器进行IP的配置 3、开始静态路由的书写&#xff0c;在写之前&#xff0c;我们可以先对每一个路由器写一条通向右边的缺省路由&…

如何解决跨域问题?

一&#xff0c;什么是跨域 域&#xff08;Origin&#xff09;是由协议、域名和端口组成的&#xff0c;只有这三者完全一致的情况下&#xff0c;浏览器才会认为两个网址同源&#xff0c;否则就认为存在跨域。跨域是指在Web开发中&#xff0c;一个网页的JavaScript代码试图访问另…

机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归)

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归)&#xff0c;这几天引爆网络的科技大新闻就是韩国科研团队宣称发现了室温超导材料-LK-99&#xff0c;这种材料…

读MetaGait代码

前置问题 关于分布式&#xff0c;可能是系统、网络等问题我最终还是取消掉了&#xff0c;下面这些尝试使用分布式时报的错姑且记录一下。。。 ############################## module ‘distutils’ has no attribute ‘version’ pip install setuptools59.5.0 No module …

数智保险 创新未来 | GBASE南大通用亮相中国保险科技应用高峰论坛

本届峰会以“数智保险 创新未来”为主题&#xff0c;GBASE南大通用携新一代创新数据库产品及金融信创解决方案精彩亮相&#xff0c;与国内八百多位保险公司高管和众多保险科技公司技术专家&#xff0c;就保险领域数字化的创新应用及生态建设、新一代技术突破及发展机遇、前沿科…

算法通关村—括号匹配问题解析

1. 有效的括号 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。…

网易云音乐扫码登录

简介 尚硅谷的网易云音乐项目无法登录&#xff0c;因为目前网易修改了接口使用手机号和密码登录的话需要先通过认证才可以&#xff0c;所以目前无法使用手机号登录&#xff0c;只能使用二维码登录&#xff0c;接下来我就教大家如何使用 二维码进行登录 实现步骤 1.获取nodejs接…

【Spring Cloud 四】Ribbon负载均衡

Ribbon负载均衡 系列文章目录背景一、什么是Ribbon二、为什么要有Ribbon三、使用Ribbon进行负载均衡服务提供者A代码pom文件yml配置文件启动类controller 服务提供者Bpom文件yml配置文件启动类controller 服务消费者pom文件yml文件启动类controller 运行测试 四、Ribbon的负载均…

Kubespray-offline v2.21.0-1 下载 Kubespray v2.22.1 离线部署 kubernetes v1.25.6

文章目录 1. 目标2. 预备条件3. vcenter 创建虚拟机4. 系统初始化4.1 配置网卡4.2 配置主机名4.3 内核参数 5. 打快照6. 安装 git7. 配置科学8. 安装 docker9. 下载介质9.1 下载安装 docker 介质9.2 下载 kubespray-offline-ansible 介质9.3 下载 kubernetes 介质 10. 搬运介质…

css, resize 拖拉宽度

效果如下&#xff1a; 可直接复制预览查看属性值: 关键样式属性&#xff1a; resize: horizontal; overflow-x: auto; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…

睿讯微带你深度了解汽车交流充电桩

这几年随着新能源汽车的普及&#xff0c;充电桩也越来越多的出现在我们的视野中。新能源纯电汽车就好比一种大号的电子产品&#xff0c;而充电桩则是它不可缺少的子系统&#xff0c;是新能源车主们的必要选择。 汽车充电桩分为直流和交流两种&#xff0c;2022年底全国公共充电桩…

华为防火墙会话表

会话表是设备转发报文的关键表项。所以当出现业务故障时&#xff0c;通常可以通过查看会话表信息&#xff0c;大致定位发生故障的模块或阶段。 当某个业务发生问题&#xff0c;例如流量不通或者断断续续时&#xff0c;通过查看会话表可以得出以下信息&#xff1a; 如果该项业…

Android 死机问题学习笔记

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、死机系统简图二、死机的可能原因三、死机问题需要分析哪些数据四 、Java Backtrace 分析五、常见 Java backtrace 举例六、Native Backtrace七、Ke…

单月涨粉90w,小红书科普视频引发高关注

为洞察小红书平台的内容创作趋势及品牌营销策略&#xff0c;新红推出7月月度榜单&#xff0c;从创作者、品牌、品类多方面入手&#xff0c;解析月榜数据&#xff0c;为从业者提供参考。 爆款笔记涨粉90w 科普视频引发高关注 据7月的『涨粉排行榜』TOP500数据显示&#xff0c;头…

在线LaTeX公式编辑器编辑公式

在线LaTeX公式编辑器编辑公式 在编辑LaTex文档时候&#xff0c;需要输入公式&#xff0c;可以使用在线LaTeX公式编辑器编辑公式&#xff0c;其链接为: 在线LaTeX公式编辑器&#xff0c;https://www.latexlive.com/home 图1 在线LaTeX公式编辑器界面 图2 在线LaTeX公式编辑器…

IDEA用Gradle构建项目时,lombok插件无效的解决办法

Lombok 可用来帮助开发人员消除 Java 的重复代码&#xff0c;尤其是对于简单的 Java 对象&#xff08;POJO&#xff09;&#xff0c;比如说getter/setter/toString等方法的编写。它通过注解实现这一目的。 正确使用姿势 一、安装Lombok插件 菜单栏File -> Settings ->…

C++继承——多继承导致的菱形继承

目录 单继承&#xff1a; 多继承&#xff1a; 菱形继承&#xff1a;菱形继承是多继承的一种特殊情况。 三.菱形继承的两种解决方式区别&#xff1a; 3.1采用作用域解决的菱形继承&#xff1a; 检测器运行图&#xff1a; 反汇编运行图&#xff1a; 3.1菱形虚继承&…

私募证券基金动态-23年7月报

成交量&#xff1a;7月日均8,481.84亿元 2023年7月A股两市日均成交8,481.84亿元&#xff0c;环比下降11.78%、同比下降15.77%。7月整体21个交易日&#xff0c;仅有月初第1个交易日单日成交金额过万亿&#xff0c;且成交量起伏较大&#xff0c;单日成交金额最低仅有6610.11亿元…

深度学习(32)——CycleGAN(1)

深度学习&#xff08;32&#xff09;——CycleGAN&#xff08;1&#xff09; 文章目录 深度学习&#xff08;32&#xff09;——CycleGAN&#xff08;1&#xff09;1. GAN原理2. CycleGAN&#xff08;1&#xff09;原理&#xff08;2&#xff09;核心思想&#xff08;3&#xf…