SpringMVC系列之技术点定向爆破二

SpringMVC的运行流程

图片

  • 客户端发送请求

  • tomcat接收对应的请求

  • SpringMVC的核心调度器DispatcherServlet接收到所有请求

  • 请求地址与@RequestMapping注解进行匹配,定位到具体的类和具体的处理方法(封装在Handler中)

  • 核心调度器找到Handler后交给HandlerAdapter执行具体的Handler

  • 执行后Controller将具体的执行结果(ModelAndView)返回给HandlerAdapter

  • 核心调度器把ModelAndView交给视图解析器,视图解析器找到具体的jsp封装到View对象中

  • View视图把jsp转换成html内容再交给核心调度器

  • 核心调度器把html内容返回给客户端。

RequestMapping注解

在Controller中通过RequestMapping注解来定义匹配请求的URL。

  • RequestMapping注解可以定义在类的上方,作为类的中多个方法的统一URL前缀。

  • RequestMapping注解定义在方法的上方,作为此次请求具体要执行的方法的限定。

/**
@Author: 索尔
*/
@Controller //声明这是一个控制器
@RequestMapping("/hello") //访问路径,等价于url-pattern
public class HelloController {
    @RequestMapping("/test1") //访问路径
    public String hello1(){
        System.out.println("hello world");//具体的业务逻辑
        return "redirect:/index.jsp"; //跳转:/index.jsp
    }
}

RequestParam注解

RequestParam注解往往和RequestMapping注解配合使用,用来绑定请求参数和处理方法的参数。

我们来看下RequestParam注解的源码:

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";
    @AliasFor("value")
    String name() default "";
    boolean required() default true;
    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
  • @RequestParam(required = false/true,value = “参数名”,defaultValue = “”) 其中name和value等效这里用value,推荐使用value。

  • value:用于重命名参数,若使用了value,则前端请求时该参数必须与value相同

  • required:用来制定该参数是否必须传入

    • true:默认值,前端请求时默认必须传入

    • false:前端请求时可以不传,不传时后端收到的是null

  • defaultValue:如果设置了defaultValue,则required不会使用默认值true,而自动为false。当没有穿参数时,就使用默认值。

接收复杂类型的参数

  • 设计User类,包含了多种复杂类型。

/**
@Author: 索尔
*/
public class User {
 private int id;
 private String name;
 private String[] hobbies;
 private Address address;
 private List<String> schools;
 private List<User> family;
 private Map<String,String> scores;
 ...
}
  • 设计Controller的处理方法,接收复杂类型的参数并打印

 /**
     * 接收复杂类型的参数
     * @return
     */
    @RequestMapping("/test3")
    public String test3(User user){
        System.out.println(user);
        return "redirect:/index.jsp";
    }

使用SpringMVC直接接收来自jsp发起的Get或着Post请求。

  • 设计存放表单的jsp页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
   <form action="${pageContext.request.contextPath}/demo/test3" method="post">
       id:<input type="text" name="id"> <br/>
       姓名:<input type="text" name="name"><br/>
       爱好:<input type="checkbox" name="hobbies" value="阅读">阅读</input>
            <input type="checkbox" name="hobbies" value="看片">看片</input>
            <input type="checkbox" name="hobbies" value="音乐">音乐</input><br/>
       所在城市:<input type="text" name="address.city">所在街道:<input type="text" name="address.street"><br/>
       毕业院校:<input type="text" name="schools[0]"><input type="text" name="schools[1]"><br/>
       家庭成员:
         父亲:<input type="text" name="family[0].name">
         母亲:<input type="text" name="family[1].name"><br/>
       成绩:
         计算机:<input type="text" name="scores['计算机']">
         大学英语:<input type="text" name="scores['大学英语']"><br/>
       <input type="submit" value="注册"/>
   </form>
</body>
</html>

注意List、Map、实体类中的实体类的参数命名方式。当填入表单数据后,程序可以收到指定类型的参数。

  • 页面设定的参数内容:

图片

  • 后端接收到的结果:

User{id=1010, name='小王', address=Address{city='杭州', street='上城'}, hobbies=[读书, 看片], schools=[北京大学, 清华大学], family=[User{id=0, name='张三', address=null, hobbies=null, schools=null, family=null, scores=null}, User{id=0, name='李四', address=null, hobbies=null, schools=null, family=null, scores=null}], scores={大学英语=100, 计算机=90}}

解决Post请求参数中文乱码问题

如果参数中包含中文,则会出现乱码问题。使用过滤器解决Post请求参数中文乱码问题。

web.xml文件中配置过滤器:

<!--编码过滤器,解决乱码问题-->
    <filter>
        <filter-name>characterFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置编码格式为utf8-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <!--对request请求进行编码-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--对response响应进行编码-->
        <init-param>
            <param-name>foreResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!--配置要过滤的servlet-->
    <filter-mapping>
        <filter-name>characterFilter</filter-name>
        <servlet-name>mvc</servlet-name>
    </filter-mapping>

获得请求头数据

在JavaWeb中,需要繁琐的操作才能获得请求头数据。SpringMVC提供了快速获得请求头数据的方法。

@RequestMapping("/getHeader")
    public String getHeader(@RequestHeader("User-agent") String userAgent){
        System.out.println(userAgent);
        return "redirect:/index.jsp";
    }

获取Cookie数据

同样的,JavaWeb获得Cookie的方式也非常繁琐。SpringMVC提供了@CookieValue来快速获得Cookie中的数据。

 @RequestMapping("/getCookie")
    public String getCookie(@CookieValue("JSESSIONID") String jsessionid){
        System.out.println(jsessionid);
        return "redirect:/index.jsp";
    }

访问静态资源

在springmvc中,所有的请求都会被SpringMVC的核心处理器DispatcherServlet来处理,对于静态资源的请求也不例外。因此,需要告知SpringMVC,对于静态资源的请求不要去做处理,而是直接响应静态资源即可。通过springmvc的配置,完成静态资源的放行。

<!--配置访问静态资源-->
    <mvc:annotation-driven/>
    <!--将url中的路径映射到指定的资源文件夹-->
    <mvc:resources mapping="/images/**" location="/images/" />

另一种处理静态资源的方法:DispatcherServlet处理不了,则交给DefaultServlet处理。

 <!--配置访问静态资源-->
    <mvc:annotation-driven/>
    <!--另一种处理静态资源的方法:DispatcherServlet处理不了,则交给DefaultServlet处理-->
    <mvc:default-servlet-handler />

配置视图解析器

为了返回指定的视图,需要告知视图解析器如何获取指定视图。

<!-- 视图解析器
             作用:1.捕获后端控制器的返回值="index"
                  2.解析:在返回值的前后 拼接 ==> "/index.jsp"
         -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <!-- 前缀 -->
                <property name="prefix" value="/"></property>
                <!-- 后缀 -->
                <property name="suffix" value=".jsp"></property>
        </bean>

文件下载

文件上传和下载是处理复杂数据类型的另一种方式。首先我们来看下如何实现文件的下载。

文件下载的核心逻辑是通过封装响应消息,将下载内容发送给客户端。

@RequestMapping("/download")
    public ResponseEntity<byte[]> download(HttpServletRequest request) throws Exception {
       //设置下载文件信息
       ServletContext context = request.getServletContext();
       String realPath = context.getRealPath("/images/img.jpeg");
       //创建输入流
       FileInputStream fis = new FileInputStream(realPath);
       byte[] bytes = new byte[fis.available()];
       //读取文件内容,存入到字节数组中
       fis.read(bytes);
       fis.close();
       //封装下载内容到响应消息中
       HttpHeaders headers = new HttpHeaders();
       headers.set("Content-Disposition","attachment;filename=imp.jpeg");
       return new ResponseEntity<byte[]>(bytes,headers, HttpStatus.OK);
   }

文件上传

文件上传的核心逻辑是读到客户端传递来的字节数据,再通过Java程序存入到指定位置。

文件上传需要引入第三方组件Commons-fileupload的支持。

<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • 编写上传界面

<body>
    <form enctype="multipart/form-data" action="${pageContext.request.contextPath}/upload" method="post">
        文件:<input type="file" name="uploadFile" />
        <br/>
        <input type="submit" value="上传">
    </form>
</body>
  • 在spring中注册上传组件

<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <property name="maxUploadSize" value="#{1024
*1024*
16}"></property>
    </bean>
  • 编写后端上传接口

 @PostMapping("/upload")
    public String upload(MultipartFile uploadFile) throws IOException {
        System.out.println(uploadFile.getOriginalFilename());
        String path = "/Users/zeleishi/Documents/code/springmvc-demo1/out/upload/"+uploadFile.getOriginalFilename();
        File file = new File(path);
        uploadFile.transferTo(file);
        return "success";
    }

总结

这一篇文章我们攻克了SpringMVC部分关键技术,建议小伙伴同时收藏SpringMVC系列三篇博文,攻克SpringMVC将变得轻而易举。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/265037.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode刷题笔记】前缀树

208. 实现 Trie (前缀树) 解题思路: 1. 前缀树 Map实现 ,使用一个 Map<Character, Trie> 来存储 每个字符 对应的 若干子节点 ,在构造函数中初始化 根节点 root 为 当前对象实例 , 在 插入

idea运行tocmat报错

1.检查环境变量是否配置正确。 网上有许多配置tomcat环境变量的方法&#xff0c;这里不再赘述。 2.判断是否有该情况&#xff1a; 在tomcat的bin目录下有三个bat文件(startup.bat,shutdown.bat,catalina.bat)&#xff0c;随意双击一个&#xff0c;会报出上述错误。但是右键使…

c语言:输出一个正方形|练习题

一、题目 输入长度num&#xff0c;输出一个边长为num的正方形 二、思路分析 1、输出的正方形分为三部分&#xff0c;包括&#xff1a; 2、第一行、中间的num-2行&#xff0c;以及最后一行 三、代码图片【带注释】 四、源代码【带注释】 #include <stdio.h> //思路&#…

【大数据】NiFi 中的 Controller Service

NiFi 中的 Controller Service 1.Service 简介1.1 Controller Service 的配置1.1.1 SETTING 基础属性1.1.2 PROPERTIES 使用属性1.1.3 COMMENT 页签 1.2 Service 的使用范围 2.全局参数配置3.DBCPConnectionPool 的使用样例4.在 ExcuseGroovyScript 组件中使用 Service 1.Servi…

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)-简化升级版

文章目录 前言正文一、项目简介二、核心代码2.1 pom.xml 依赖配置2.2 ExcelHeadMapFactory2.3 ExcelDataLinkedHashMap2.4 自定义注解 ExcelExportBean2.5 自定义注解 ExcelColumnTitle2.6 建造器接口 Builder2.7 表格工具类 ExcelUtils2.8 GsonUtil2.9 模版类 ExportDynamicCo…

【每日一题】得到山形数组的最少删除次数

文章目录 Tag题目来源解题思路方法一&#xff1a;最长递增子序列 写在最后 Tag 【最长递增子序列】【数组】【2023-12-22】 题目来源 1671. 得到山形数组的最少删除次数 解题思路 方法一&#xff1a;最长递增子序列 前后缀分解 根据前后缀思想&#xff0c;以 nums[i] 为山…

最新ChatGPT网站系统源码+AI绘画系统+支持GPT语音对话+详细图文搭建教程/支持GPT4.0/H5端系统/文档知识库

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…

TYPE C 接口知识详解

1、Type C 概述 Type-C口有4对TX/RX分线&#xff0c;2对USBD/D-&#xff0c;一对SBU&#xff0c;2个CC&#xff0c;另外还有4个VBUS和4个地线。 当Type-C接口仅用作传输DP信号时&#xff0c;则可利用4对TX/RX&#xff0c;从而实现4Lane传输&#xff0c;这种模式称为DPonly模式…

C++ 检测 是不是 com组件 的办法 已解决

在日常开发中&#xff0c;遇到动态库和 com组件库的调用 无法区分。检测是否com组件的办法 在头部文件&#xff0c;引入文件 如果能编译成功说明是 com组件&#xff0c;至于动态库如何引入&#xff0c;还在观察中 #import "TerraExplorerX.dll" no_namespace, nam…

云原生之深入解析基于FunctionGraph在Serverless领域的FinOps的探索和实践

一、背景 Serverless 精确到毫秒级的按用付费模式使得用户不再需要为资源的空闲时间付费。然而&#xff0c;对于给定的某个应用函数&#xff0c;由于影响其计费成本的因素并不唯一&#xff0c;使得用户对函数运行期间的总计费进行精确的事先估计变成了一项困难的工作。以传统云…

TCP_滑动窗口介绍

简介 TCP协议中有两个窗口&#xff0c;滑动窗口和拥塞窗口&#xff0c;两者均是一种流控机制&#xff1b;滑动窗口是接收方的流控机制&#xff0c;拥塞窗口是发送方的流控机制。 本文介绍滑动窗口&#xff0c;接收方为TCP连接设置了接收缓存。当TCP连接接收到正确、按序的字节…

Mybatis3系列课程8-带参数查询

简介 上节课内容中讲解了查询全部, 不需要带条件查, 这节我们讲讲 带条件查询 目标 1. 带一个条件查询-基本数据类型 2.带两个条件查询-连个基本数据类型 3.带一个对象类型查询 为了实现目标, 我们要实现 按照主键 查询某个学生信息, 按照姓名和年级编号查询学生信息 按照学生…

MyBatis中延迟加载,全局和局部的开启使用与关闭

文章目录 MyBatis中延迟加载&#xff0c;全局和局部的开启使用与关闭1、问题提出2、延迟加载和立即加载延迟加载立即加载 3、三种对应的表关系中的加载4、打开全局延迟加载&#xff08;实现一对一的延迟加载&#xff09;5、实现一对多的延迟加载&#xff08;将上面设置的全局延…

渲染控制之条件渲染

目录 1、使用规则 2、更新机制 3、使用if进行条件渲染 4、if ... else ...语句和子组件状态 5、嵌套if语句 ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态&#xff0c;使用if、else和else if渲染对应状态下的UI内容。 1、使用规则 支持if、else和else if语句…

pip 常用指令 pip list 命令用法介绍

&#x1f4d1;pip 常用命令归类整理 pip list 是一个用于列出已安装的 Python 包的命令。这个命令会显示出所有已安装的包&#xff0c;以及它们的版本号。 pip list 命令有以下参数 -o, --outdated&#xff1a;列出所有过时的包&#xff0c;即有新版本可用的包。-u, --uptod…

DPDK单步跟踪(3)-如何利用visual studio 2019和visual gdb来单步调试dpdk

准备工作 因为时间的关系&#xff0c;我想到哪说到哪&#xff0c;可能没那么高的完成度。 但其实有心的人&#xff0c;看到这个标题&#xff0c;就关了本文自己能做了。 why和how to build debug version DPDK,见前两篇。这里我们准备开始。 首先&#xff0c;你有一台linux机…

什么是“人机协同”机器学习?

“人机协同”&#xff08;HITL&#xff09;是人工智能的一个分支&#xff0c;它同时利用人类智能和机器智能来创建机器学习模型。在传统的“人机协同”方法中&#xff0c;人们会参与一个良性循环&#xff0c;在其中训练、调整和测试特定算法。通常&#xff0c;它的工作方式如下…

《软件方法(下)》8.2.4 类和属性的命名

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 8.2 建模步骤C-1 识别类和属性 8.2.4 类和属性的命名 8.2.4.2 关于DDD话语中的“通用语言” DDD&#xff08;领域驱动设计&#xff09;话语中有“通用语言&#xff08;Ubiquitous L…

【JAVA面试题】什么是代码单元?什么是码点?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 目录 前言 思路 代码单元&#xff08;Code Unit&#xff09;&#xff1a; 码点&#xff08;Code Point&#xff09;&#xff1a; 作…

vscode | python | remote-SSH | Debug 配置 + CLIP4Clip实验记录

安装Extension 本地安装Remote-SSH、python 远程服务器上安装Python 难点&#xff1a;主机和远程服务器上安装Python扩展失败&#xff0c;可能是网络、代理等原因导致解决方法&#xff1a; 主机在官方网站下载Python扩展&#xff1a;https://marketplace.visualstudio.com/it…