spring mvc高级技术实例详解
作者:嗜血蚂蚁 发布时间:2022-10-11 12:50:15
Spring MVC高级技术包括但不限于web.xml配置、异常处理、跨重定向请求传递数据
1、web.xml文件的配置
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ContextLoaderListener是根容器,DispatcherServlet是子容器。父容器中管理的bean可以被子容器引用,反之,不行。它们都从各自的xml文件初始化自己的上下文
ContextLoaderListener如果未指定contextConfigLocation参数,则默认加载的配置文件为/WEB-INF/applicationContext.xml
DispatcherServlet如果未指定contextConfigLocation参数,则根据<servlet-name>元素指定的名称,在/WEB-INF/文件夹下寻找配置文件appServlet-servlet.xml
2、处理异常
Spring提供了多种方式将异常转换为响应
特定的 Spring异常会自动映射为指定的HTTP状态码
异常上可以添加@ResponseStatus注解,将异常映射为某一个HTTP状态码
在方法上可以添加@ExceptionHandler注解,使其用来处理异常
1)特定的 Spring异常会自动映射为指定的HTTP状态码
如果在控制器中抛出了异常,该异常不在列表中,又没有指定HTTP状态码,则默认为状态码为500
2)异常上可以添加@ResponseStatus注解,将异常映射为某一个HTTP状态码
@Controller
public class HelloController {
@RequestMapping("/home")
public String home(){
System.out.println("执行home");
throw new MyException();
// return "home"; //返回一个字符串,即逻辑视图名
}
}
package com.cn.Exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
public class MyException extends RuntimeException{
}
浏览器访问 http://localhost:8080/home
修改自定义异常
package com.cn.Exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "抛出异常的原因")
public class MyException extends RuntimeException{
}
浏览器访问 http://localhost:8080/home
3)在方法上可以添加@ExceptionHandler注解,使其用来处理异常
该方式是按照处理请求的方式处理异常,@ExceptionHandler注解的方法返回值为字符串表示逻辑视图名
package com.cn.Exception;
public class MyException2 extends RuntimeException{
}
@Controller
public class HelloController {
@RequestMapping("/home")
public String home(){
System.out.println("执行home");
throw new MyException2();
// return "home"; //返回一个字符串,即逻辑视图名
}
@ExceptionHandler(MyException2.class)
public String handleMException(){
System.out.println("处理异常逻辑");
return "fail";
}
}
访问http://localhost:8080/home,后台输出
浏览器页面
@ExceptionHandler注解的方法可以处理同一个控制器中所有处理器方法所抛出的异常(注解指定的异常),注解定义如下
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}
spring也支持为控制器添加通知,那么该通知对于所有的控制器中所有的处理器方法抛出的异常都起作用,实现如下
@ControllerAdvice 所标注的类会被组件扫描实例化,交给容器管理。最为实用的一个场景是将所有@ExceptionHandler标注的方法收集到一个类中,这样所有的控制器异常就能在一个地方进行一致处理。以下HandleException类定义表明在控制器中的处理器抛出MyException2类的异常,就会被handleMException方法处理,最终跳转fail.jsp页面
package com.cn.advice;
import com.cn.Exception.MyException2;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class HandleException {
@ExceptionHandler(MyException2.class)
public String handleMException(){
System.out.println("处理异常逻辑");
return "fail";
}
}
3、跨重定向请求传递数据
如果是forward转发请求,那么处理器方法业务处理完成后,该方法所指定的模型数据会复制到请求中,作为请求的一部分,转发到下一个处理器,下一个处理器可以从请求中获取上一个处理的模型数据;
如果是redirect重新向,原始请求就结束了,并且会重新发起一个GET请求。因此原始请求中的模型数据也就消失了,在请求到达下一个处理器,没有任何的模型数据,需要模型数据必须自己处理。
针对重定向传递数据,有两种方案:
使用URL模板以路径变量和/或查询参数的形式传递数据
使用flash属性传递数据
1)使用URL模板以路径变量和/或查询参数的形式传递数据
@Controller
public class HelloController {
@RequestMapping("/home2")
public String home2(Model model){
model.addAttribute("id","12324131343256");
model.addAttribute("name","pick");
return "redirect:home3/{id}"; //含有redirect的字符串,表示重定向到另一个处理器;
//如果含有forward的字符串,表示转向到另一个处理器
}
@RequestMapping("/home3/{id}")
public String home3(@PathVariable String id, Model model){
System.out.println("传递的ID="+id);
model.addAttribute(new User());
return "home";
}
}
浏览器访问localhost:8080/home2,抓包得访问的url。从以下可以看出,处理器完成后重定向时,模型中的数据填充到了路径变量中,路径变量中没有的key,则以查询参数的形式赋在url之后,组成了新的url访问。
2)使用flash属性传递数据
重定向时候,采用1)中的方式传递数据,仅仅能够传递简单的数据,不能传递对象。如何将对象也能传递到下一个处理器呢?可以将要传递到下一个处理器的数据放入用户会话中,然后在下一个处理器从会话的取出来,并删除会话中的该数据。然而,spring提供了将数据发送为flash属性的功能,不需要我们管理这些数据,flash属性会一致携带这些数据直到下一次请求才消失。
Spring提供RedirectAttributes是Model接口的子接口,除了提供Model的所有功能,还提供了几个方法用来设置flash属性。
@Controller
public class HelloController {
@RequestMapping("/home2")
public String home2(RedirectAttributes model){
model.addAttribute("id","12324131343256");
model.addFlashAttribute("user",new User("liming","123456"));//设置flash属性,也可以 model.addFlashAttribute(new User("liming","123456"))
//则通过值得类型自行推断出key为user
return "redirect:home3/{id}";
}
@RequestMapping("/home3/{id}")
public String home3(@PathVariable String id, RedirectAttributes model){
System.out.println("传递的ID="+id);
if (model.containsAttribute("user")) {
System.out.println("传递的对象:" + model.getFlashAttributes().get("user"));
}
return "home";
}
}
异常测试
在controller、service、dao中任意一处需要手动抛出异常。
如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。
在商品修改的controller方法中抛出异常 .
在service接口中抛出异常:
如果与业务功能相关的异常,建议在service中抛出异常。
与业务功能没有关系的异常,建议在controller中抛出。
上边的功能,建议在service中抛出异常。
来源:https://www.cnblogs.com/shixiemayi/p/9569338.html


猜你喜欢
- 1.向上转型 向下转型2.强制类型转换的应用应用多态性时由于引用为父类类型,导致编译时只能调用父类中声明的属性和方法。子类特有的属性和方法不
- Java 回调函数概要: 所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个
- 本文实例为大家分享了Android自定义View倒计时圆的具体代码,供大家参考,具体内容如下创建attr<?xml version=&
- Maven --> Gradle首先安装gradle:Mac安 * rew install gradleUbuntu安装apt inst
- MyBaties的基本配置标签1-全局配置文件(xxx.properties)引入的两种方式resource:引入类路径下的资源url:引入
- 一、信号量(Semaphore)信号量(Semaphore)是由内核对象维护的int变量,当信号量为0时,在信号量上等待的线程会堵塞,信号量
- 概述什么是动态编程?动态编程解决什么问题?Java中如何使用?什么原理?如何改进?(需要我们一起探索,由于自己也是比较菜,一般深入不到这个程
- 将字符串转换为ASCII编码数组,只要是中文字节码就是ASCII编码63即"?",所以可以由此来进行判断class St
- 使用stream判断两个list元素的属性并输出/*** 使用stream判断两个list中元素不同的item*/@Testpublic v
- 这篇文章主要介绍了Java如何基于ProcessBuilder类调用外部程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的
- 实现常驻通知栏时遇到的问题:无论如何就是不显示通知,查看日志发现貌似报错了:2020-06-28 14:11:34.923 6387-638
- 时间轴,顾名思义就是将发生的事件按照时间顺序罗列起来,给用户带来一种更加直观的体验。京东和淘宝的物流顺序就是一个时间轴,想必大家都不陌生,如
- 为了创建比例大小的子View,可以将LinearLayout的宽度和高度设为fill_parent, 而将子View的宽度或是高度设为0,然
- 欢迎访问我的GitHub这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demo
- 在使用 SpringMVC 上传文件时,接收到的文件格式为 MultipartFile,但是在很多场景下使用都需要File格式的文件,记录下
- 实例如下所示:package test;import java.util.ArrayList;import java.util.Collec
- 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作。同时,这个问题在Stack Overflow
- 现在很多app的首页都有一个倒计时控件,比如说3秒或者5秒自动跳转界面,或者点击控件直接跳过首先,自定义控件CircleProgressba
- 前言其实不管是哪种滑动方式,基本思想都是类似的:当点击事件传递到View时,系统记下触摸点的坐标,手指移动的时候,系统记下移动后的坐标,并计
- 概要: ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-P