SpringMVC从入门到精通(二)

news2025/1/12 18:39:08

文章目录

  • 6. 响应视图和结果数据
    • 6.1 返回值类型
    • 6.2 springmvc作用域传值
    • 6.3 转发和重定向
    • 6.4 json数据格式的请求与响应
  • 7.SpringMVC 实现文件上传
    • 7.1 文件上传三要素
    • 7.2 文件上传依赖
    • 7.2 文件上传示例(后端需要配置文件解析器)
  • 8. SpringMVC 中的异常处理
    • 8.1 springmvc默认处理异常的方式
    • 8.2 @ExceptionHandler注解进行异常处理
    • 8.3 使用@controlleradvice注解
  • 9. springmvc中的拦截器
    • 9.1 拦截器的作用
    • 9.2 自定义拦截器示例
    • 9.3 拦截器的细节

6. 响应视图和结果数据

6.1 返回值类型

(1)返回字符串类型

  • controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
	@RequestMapping("testString")
	public String testString(){
	    return "success";
	}

(2)返回值void

  • Servlet原始 API 可以作为控制器中方法的参数,所以在 controller方法形参上可以定义request和response,使用request或response指定响应结果:
@RequestMapping("testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception{
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}
@RequestMapping("testVoid1")
public void testVoid1(HttpServletRequest request, HttpServletResponse response) throws Exception{
     response.sendRedirect("/user/testVoid");
}

(3)返回值ModelAndView

  • ModelAndView是SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
  • 在SpringMVC的执行流程中,其中在处理器适配器选择相应的处理器(handler/自己编写的controller)时,会返回一个ModelAndView,我们在此处使用返回值为ModelAndView,它就会替代底层自己构建的ModelAndView
public ModelAndView testModelAndView(){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("username","eric");
    modelAndView.setViewName("success");
    return modelAndView;
}

6.2 springmvc作用域传值

  • ModelAndView底层封装
    • 在 ModelAndView 中有一个属性 Model 实现了java.util下的LinkedHashMap ,当使用Map 或 Model 进行传值时,SpringMVC会将ModelAndView中的ModelMap或Model进行替换,将其替换为我们自定义的Map或Model
      在这里插入图片描述
  • 下列传值操作均将值保存到Request作用域中

(1)使用原生的Request域对象传值

/**
 * 不带返回值类型的controller方法
 * 使用原生的Request对象值传递
 */
@RequestMapping("testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception{
    request.setAttribute("age",18);
    //使用原生的servlet进行转发
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}

(2)使用Map集合传值

/**
 * 带返回值的方法
 * 使用Map集合进行值传递 将map对象作为方法的形式参数
 * @return
 */
@RequestMapping("hello")
public String sayHello(Map<String,Object> map){
    map.put("sname","铁蛋");
    map.put("sage",19);
    return "success";
}

(3)使用Model对象传值

/**
 * 使用Model对象传值
 * @param model
 * @return
 */
@RequestMapping("model")
public String testModel(Model model){
    model.addAttribute("address","西安");
    model.addAttribute("score",19);
    return "success";
}

(4)使用ModelAndView对象传值

/**
 * 使用ModelAndView进行值传递
 * @return
 */
@RequestMapping("testModelAndView")
public ModelAndView testModelAndView(){
    ModelAndView mv = new ModelAndView();
    //存储值
    mv.addObject("username","kobe");
    //设置响应视图
    mv.setViewName("success");
    return mv;
}

6.3 转发和重定向

(1)forward转发

  • controller方法在提供了String类型的返回值之后,默认就是请求转发
  • 它相当于 “request.getRequestDispatcher(“url”).forward(request,response)”。使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法。
  • 转发jsp:
@RequestMapping("testString")
public String testString(){
    //return "success";
    return "forward:/WEB-INF/pages/success.jsp";
}
  • 转发到控制器其他方法
@RequestMapping("testString")
public String testString(){
    return "forward:/user/model";
}

(2)Redirect重定向

  • contrller方法提供了一个 String 类型返回值之后,它需要在返回值里使用:redirect:
  • 重定向jsp:
@RequestMapping("testString")
public String testString(){
    return "redirect:/pages/success.jsp";
}
  • 重定向到控制器其他方法
@RequestMapping("testString")
public String testString(){
    return "redirect:/user/model";
}

6.4 json数据格式的请求与响应

(1)依赖

  • 引入下列依赖后,在Controller接收json格式请求的数据或响应json格式的数据时,使用相关注解SpringMVC会进行数据格式自动转换(pojo《==》json)
    • @RequestBody: 会自动的将前台传递的json格式的数据转换成pojo对象。
    • @ResponseBody: 会自动的将pojo对象以json格式的数据传递给前台。
<dependency>
	  <groupId>com.fasterxml.jackson.core</groupId>
	  <artifactId>jackson-databind</artifactId>
	  <version>2.9.0</version>
</dependency>
<dependency>
	  <groupId>com.fasterxml.jackson.core</groupId>
	  <artifactId>jackson-core</artifactId>
	  <version>2.9.0</version>
</dependency>
<dependency>
	  <groupId>com.fasterxml.jackson.core</groupId>
	  <artifactId>jackson-annotations</artifactId>
	  <version>2.9.0</version>
</dependency>

(2)@ResponseBody响应json数据原理

  • 作用:
    • 该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
  • 响应中文乱码解决
    • 配置字符集转换器
<mvc:annotation-driven >
    <!--设置响应输出字符集-->
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=utf-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

(3)示例

  • 以ajax为例,向服务器端发送json数据格式的请求
    • 发送的必须是json类型格式的数据(发送的data)
    • 若不对contextType不指定json格式数据,后端将会报错(415访问媒体格式不支持)
      在这里插入图片描述
  • 服务器端接收json格式数据,并响应json格式数据
    • 若不添加相应的json依赖,后端会报错(500,数据格式转换异常)
      在这里插入图片描述

7.SpringMVC 实现文件上传

7.1 文件上传三要素

  • 请求方式必须为POST,必须配置enctype
  • 在文件input的type必须为file,且其中的name属性值,要和后端接收问价的形参名称相同,否则需要使用@RequestParam进行转化接收参数
  • 接口参数是MultipartFile类型

7.2 文件上传依赖

<dependency>
	  <groupId>commons-fileupload</groupId>
	  <artifactId>commons-fileupload</artifactId>
	  <version>1.3.1</version>
</dependency>
<dependency>
	  <groupId>commons-io</groupId>
	  <artifactId>commons-io</artifactId>
	  <version>2.4</version>
</dependency>

7.2 文件上传示例(后端需要配置文件解析器)

(1)前端form表单

<%--    在文件input中的name属性值,要和后端接收问价的形参名称相同,否则需要使用@RequestParam进行转化--%>
<form action="/file/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="submit" value="上传文件"/>
</form>

(2)后端controller方法接收

@Controller
@RequestMapping("file")
public class FileController {
    @RequestMapping("upload")
    public String upLoad(MultipartFile file) throws IOException {
//        获取文件名称
        String filename = file.getOriginalFilename();
//        上传文件
        file.transferTo(new File("d:\\",filename));
        return "success";
    }
}

(3)配置文件解析器

  • 配置文件上传解析器: 名称不要随便起,约定优于配置,在底层调用的一般是设置解析器实现的顶层接口
  • CommonsMultipartResolver 顶层接口是 MultipartResolver
<!--    设置文件上传解析器: 名称不要随便起,约定由于配置,在底层调用的一般是设置解析器实现的顶层接口-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <property name="maxUploadSize" value="2097152"></property>
    </bean>

8. SpringMVC 中的异常处理

8.1 springmvc默认处理异常的方式

  • Springmvc默认处理异常的方式和servlet处理异常的方式是一样的。都是为web.xml里面定义错误处理代码和错误处理页面。
  • 配置上述后,当访问发生错误时,根据发生错误的状态码,会自动跳转到配置的页面
  • 示例:在web.xml里面定义错误处理页面
<!--配置错误处理页面-->
<error-page>
  <error-code>400</error-code>
  <location>/error/400.jsp</location>	<!-- 发生错误后,跳转到的页面(父目录是WEB-INF)-->
</error-page>

<error-page>
  <error-code>404</error-code>
  <location>/error/404.jsp</location>
</error-page>

<error-page>
  <error-code>500</error-code>
  <location>/error/500.jsp</location>
</error-page>

8.2 @ExceptionHandler注解进行异常处理

  • 在Controller层某方法上使用@ExceptionHandler注解,当controller发生错误时,异常处理器会接手接下来的处理,在添加了@ExceptionHandler方法中,编写相关处理异常逻辑代码
  • 这种异常处理的方式解决了问题。但是异常处理的代码和控制器代码在一个controller里面定义,违反了代码编写的职责单一性。
    在这里插入图片描述

8.3 使用@controlleradvice注解

  • @controlleradvice 对所有添加了 @Controller 注解的类(处理器/我们平常编写的controller)进行了增强操作(不一定是处理异常,也可能是其他的增强操作,eg: 初始化数据等)
  • 定义一个类,专门进行异常处理(在该类上添加 @controlleradvice 注解)
  • 示例:
    • 异常处理类
@ControllerAdvice
public class ExeceptionAdvice {

//    处理运行时异常
    @ExceptionHandler(RuntimeException.class)
    public ModelAndView execeptionPut(Exception e){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("/error/error");
        modelAndView.addObject("msg",e.toString());
        return modelAndView;
    }
}
  • 任何添加@Controller 注解的类都将被上述类增强
@Controller
@RequestMapping("exeception")
public class ExeceptionController {

    @RequestMapping("test01")
    public String test01(){
//        空指针
        String s=null;
        int length = s.length();
        int num=10/0;
        return "success";
    }
}

9. springmvc中的拦截器

9.1 拦截器的作用

        Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
        用户可以自己定义一些拦截器来实现特定的功能。
        谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
        说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说拦截器与过滤器的区别:
        过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
        拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
        过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
        拦截器它是只会拦截访问的控制器方法(只会拦截接口),如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
        它也是 AOP 思想的具体应用。
        我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

9.2 自定义拦截器示例

(1)编写一个实现HandlerInterceptor接口的实现类

//自定义拦截器
public class MyInterceptor implements HandlerInterceptor {
    /*
    * 预处理,controller方法执行前
    * return true放行,执行下一个拦截器,如果没有,执行controller中的方法
    * return false不放行
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了......前111(第一个拦截器)");
        //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        //true为放行,false为不放行
        return true;
    }

    /*
    * 后处理方法
    * controller方法执行后
    * success.jsp执行之前
    * */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了......后111(第一个拦截器)");
        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
    }

    /*
    * success.jsp页面执行后,该方法会执行
    * 这个页面不能再跳转其他页面了
    * */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了......最后111(第一个拦截器)");
    }
}

(2)在spring配置文件中配置拦截器

<!--配置拦截器-->
<mvc:interceptors>
    <!--配置第一个拦截器-->
    <mvc:interceptor>
        <!--要拦截的具体的方法-->
        <mvc:mapping path="/user/*"/>
        <!--不要拦截的方法-->
        <!--<mvc:exclude-mapping path=""/>-->
        <!--配置拦截器对象(自己实现HandlerInterceptor接口的实现类对象)-->
        <bean class="org.westos.demo.interceptor.MyInterceptor"/>
</mvc:interceptor>

9.3 拦截器的细节

(1)从AOP角度考虑拦截器的执行与配置
在这里插入图片描述
(2)多个拦截器执行顺序

  • 拦截器链执行顺序,类似于栈结构(先进后出)
  • 当存在多个拦截器,外层的拦截器进去之后,一定会执行此外层的 afterCompletion 方法(内层拦截器中断之后也会执行外层的 afterCompletion 方法
    在这里插入图片描述

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

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

相关文章

FMT航点飞行(一)

一、航点飞行前检查&#xff1a; &#xff08;1&#xff09;将飞行器在position模式下启动飞行&#xff0c;移动一个距离&#xff1b;在qgc地面站地图上观察移动的距离&#xff0c;记录大概移动的距离为D&#xff1b;打航向&#xff0c;观察地磁计转向是否正常&#xff1b; &a…

Redisson的看门狗机制究竟有什么用?

Redisson的看门狗机制究竟有什么用&#xff1f; 一、普通的Redis分布式锁的缺陷 基于Redis的分布式锁 Redis Lua 脚本实现分布式锁 二、watchDog的自动延期机制 调用链关系 源码解析 tryLock() tryAcquire() tryAcquireAsync() scheduleExpirationRenewal() 锁…

Nginx+tomcat集群

Nginxtomcat集群 定义&#xff1a;在测试环境中有多个tomcat运行这一个项目&#xff0c;需要nginx管理 2特点&#xff1a;1&#xff0c;增加项目访问能力 2&#xff0c;增加服务器性能 3&#xff0c;实现不同负载均衡 3负载均衡&#xff1a;根据每台服务器的性能分配其能承受住…

【Linux】程序地址空间

目录 地址空间是什么 写时拷贝 地址空间存在的意义 如何管理进程地址空间 地址空间是什么 这是我们常说的c/c程序地址空间&#xff0c;但是这里的空间具体指的是哪里的空间&#xff0c;举一个例子方便理解&#xff1a; 运行结果&#xff1a; 代码运行十秒后子进程修改了全局…

目标检测—DiffusionDet:用于检测的概率扩散模型笔记—DDPM

目录 一、Introduction 二、相关工作 三、方法 1.准备工作 2.架构 3、训练 4.预测过程 四. 实验 1.训练策略 2.main property 3.消融实验 五、代码分析 1.测试 demo.py 2.训练 train-net.py 总结 DiffusionDet&#xff1a;将目标检测问题构建为一个从带噪框到目…

安卓APP源码和设计报告——麻雀笔记

目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 …

四年一次的世界杯来了,看看还剩下哪些赛程呢?

足球世界杯的由来2022年的世界杯目前世界杯的赛程看看排在前十的球员几个疑问&#xff1f;世界杯的由来 足球大家应该知道&#xff0c;是一项体育运动&#xff0c;而且是一项多人的体育运动。 世界杯的诞生&#xff0c;源于1950年的南非公开赛&#xff0c;在当时只有5支队伍参…

微信视频播放点播小程序毕业设计,在线教育视频学习小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

基于微信小程序的毕业设计题目&#xff08;12&#xff09;php在线教育视频点播学习小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板) 项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序视频点播系统&#xff0c;前台用户使用小程序&a…

理解Nodejs中的进程间通信

前置知识 文件描述符 在 Linux 系统中&#xff0c;一切都看成文件&#xff0c;当进程打开现有文件时&#xff0c;会返回一个文件描述符。 文件描述符是操作系统为了管理已经被进程打开的文件所创建的索引&#xff0c;用来指向被打开的文件。 当我们的进程启动之后&#xff0c…

Python学习-8.1.2 标准库(random库的基础与实例)

2.2 random库 使用random库的主要目的是生成随机数 2.2.1 产生随机数 random()函数&#xff1a;生成一个[0.0,1.0)之间的随机小数&#xff0c;左开右闭。 import random print(random.random())#生成一个[0.0,1.0)之间的随机小数 #每次运行random()函数都会产生不同的数据 …

Layer2代币经济学:除了治理 还应该具备什么价值?

为什么我们需要L2&#xff1f; 任何在2021年期间使用以太坊的人都知道&#xff0c;该区块链可能会变得非常拥堵。这是一个典型的问题——需求太多而供应不足。因此&#xff0c;gas费用&#xff08;交易费&#xff09;变得相当昂贵。在牛市高峰期&#xff0c;使用以太坊区块链发…

基于Jenkins的开发测试全流程持续集成实践

今年一直在公司实践CI&#xff0c;本文将近半年来的一些实践总结一下&#xff0c;可能不太完善或优美&#xff0c;但的确初步解决了我目前所在项目组的一些痛点。当然这仅是一家之言也不够完整&#xff0c;后续还会深入实践和引入Kubernetes进行容器编排&#xff0c;以及通过阿…

从js中加载图片和Cannot read property ‘appendChild‘ of null 错误

先写一段代码如下&#xff1b; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title> </title><script>var imgnew Image();img.addEventListener("load",loadHandler);img.src"img/1.jpg"…

【JMeter】命令参数说明

jmeter -n -t xxx.jmx -l result.jtl 非GUI运行xxx.jml脚本写入xxx.jtl结果文件 jmeter -n -t xxx.jmx -l result.jtl -j run.log 非GUI运行xxx.jmx脚本写入xxx.jtl结果文件&#xff0c;日志记录到run.log jmeter -n -t xxx.jmx -R ip1:port1,ip2:port2 -l result.jtl 使用远…

详解 Redis 持久化之掌握 RDB ⽂件的格式,学习如何制作数据库镜像

本文带大家了解一下 Redis 数据一种持久化方式 RDB 的实现。包括 Redis 内存快照 RDB ⽂件的创建时机以及⽣成⽅法。可以让你掌握 RDB ⽂件的格式&#xff0c;学习如何制作数据库镜像。 RDB 创建的入口函数 Redis 创建 RDB 文件的函数有三个&#xff0c;分别是 rdbSave, rdbSa…

知识图谱-KGE-语义匹配-双线性模型-2017:ANALOGY

【paper】 Analogical Inference for Multi-relational Embeddings【简介】 本文是卡耐基梅隆大学的中国学者发表在 ICML 2017 上的工作&#xff0c;提出了 ANALOGY 模型&#xff0c;用于建模实体和关系的推理属性。这个模型应当也算是双线性模型中比较经典的一个了&#xff0c…

Erueka基本使用

SpringCloud Erueka基本使用 Erueka是微服务架构中&#xff0c;可以作为注册中心的技术实现&#xff0c;如下图所示 服务提供者&#xff1a;一次业务中&#xff0c;暴露接口给其它微服务调用&#xff0c;被其它微服务调用的服务。&#xff08;提供接口给其它微服务&#xff09…

一个超好看的音乐网站设计与实现(HTML+CSS)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

vue+vite的创建

1、创建vue3项目 yarn create vite效果&#xff1a; yarn create v1.22.19 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages...success Installed "create-vite3.2.1" with binaries:- crea…

接口管理测试繁琐复杂?何不试试这个神器

一、前言 作为一名测试从业者&#xff0c;深刻的明白接口测试在项目过程中是多么重要的一个环节。通过页面进行的UI测试会因为界面不稳定而导致用例维护非常困难。另外&#xff0c;在检查系统的安全性、稳定性上面也是尤为重要的环节&#xff0c;这些也是无法通过前端测试的&a…