Spring MVC

本文详细介绍了Spring MVC的请求处理流程,包括环境搭建、URL映射、参数绑定、请求转发与重定向。还探讨了JSON数据开发在Spring MVC中的应用,以及如何使用拦截器和处理文件上传。同时,文章还讲解了SSM框架的集成测试和实现Restful URL的方法,并提供了全局异常统一处理的方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Spring MVC

  • 请求处理流程分析
    在这里插入图片描述

     流程:
     	1.首先用户发送请求,请求被SpringMvc前端控制器(DispatherServlet)捕获;
     	2.前端控制器(DispatherServlet)对请求URL解析获取请求URI,根据URI,调用HandlerMapping; 
     	3.前端控制器(DispatherServlet)获得返回的HandlerExecutionChain(包括Handler对象以及Handler对象对应的拦截器);
     	4.DispatcherServlet 根据获得的 HandlerExecutionChain,选择一个合适的HandlerAdapter。
     		(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法);
     	5.HandlerAdapter根据请求的Handler适配并执行对应的Handler;HandlerAdapter(提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 
     		在填充Handler的入参过程中,根据配置,Spring将做一些额外的工作:
     		HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
     		数据转换:对请求消息进行数据转换。如String转换成Integer、Double等数据格式化:数据格式化。 如将字符串转换成格式化数字或格式化日期等。
     		数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中)。
     	6.Handler执行完毕,返回一个ModelAndView(即模型和视图)给HandlerAdaptor。
     	7.HandlerAdaptor适配器将执行结果ModelAndView返回给前端控制器。
     	8.前端控制器接收到ModelAndView后,请求对应的视图解析器。
     	9.视图解析器解析ModelAndView后返回对应View;
     	10.渲染视图并返回渲染后的视图给前端控制器。
     	11.最终前端控制器将渲染后的页面响应给用户或客户端。
    
  • 优势

     1.清晰的角色划分:前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、
       处理器或页面控制器(Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
     2.分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要;
     3.和Spring 其他框架无缝集成,是其它Web框架所不具备的;
     4.可适配,通过HandlerAdapter可以支持任意的类作为处理器;
     5.可定制性,HandlerMapping、ViewResolver等能够非常简单的定制;
     6.功能强大的数据验证、格式化、绑定机制;
     7.利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;
     8.本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
     9.强大的JSP标签库,使JSP编写更容易。
    
  • 环境搭建

     1.开发环境	Idea + Maven + Jdk1.8 + Jetty
     2.pom.xml坐标添加
     3.配置web.xml
     4.spring.xml配置
     5.页面控制器的编写
     6.添加视图页面(在WEB-INF下新建jsp文件夹)
     7.启动jetty服务器
    
  • URL地址映射配置

     @RequestMapping
     通过注解@RequestMapping将请求地址与方法进行绑定,可以在类级别和方法级别声明。
     1.映射单个URL(声明在方法上面)
     	@RequestMapping("")或@RequestMapping(value="")
     	@RequestMapping("/请求路径")与@RequestMapping("请求路径")均可 
     	访问地址:http://ip:port/项目名/方法路径
     	如果有类路径需要写在方法路径前面
     2.映射多个URL(声明在方法上面)
     	@RequestMapping({"",""}) 或 @RequestMapping(value={"",""})
     	支持一个方法绑定多个url的操作
     	访问地址:http://ip:port/项目名/方法路径
     	如果有类路径需要写在方法路径前面
     3.映射URL在控制器上(声明在类上面)
     	表示类中的所有响应请求的方法都是以该地址作为父路径。
     	声明级别:
     		类级别 + 方法级别 (/类路径/方法路径)
     	访问地址:http://ip:port/项目名/类路径/方法路径
     4.设置URL映射的请求方式
     	默认没有设置请求方式,可以通过method属性设置支持的请求方式,如method=RequestMethod.POST;
     	如设置多种请求方式,以大括号包围,逗号隔开即可。
     	访问地址:http://ip:port/项目名/类路径/方法路径(只能使用POST请求访问)
     5.通过参数名称映射URL
     	@RequestMapping(params = "")
     	通过参数的形式访问
     	访问地址:http://ip:port/项目名/url?方法路径
    
  • 参数绑定

     1.基本数据类型
     	参数值必须存在。如果没有指定参数值,也没有设置参数默认值,则会报500异常。
     	通过注解@RequestParam标记一个形参为请求参数。(注解声明在形参的前面) 可以通过注解的属性设置相关内容 。
     	设置参数的默认值 				defaultValue
     	设置参数的参数名(别名)		 	name
     2.包装类型(如果数据是基本类型,建议使用包装类型)
     	客户端请求参数名与方法形参名保持一致,默认参数值为null。
     	设置参数的默认值 				defaultValue
     	设置参数的参数名(别名)		 	name
     3.字符串类型
     	客户端请求参数名与方法形参名保持一致,默认参数值为null。
     	设置参数的默认值 				defaultValue
     	设置参数的参数名(别名)		 	name
     4.数组类型
     	客户端传参形式:ids=1&ids=2&ids=3。
     5.JavaBean类型
     	客户端请求的参数名与JavaBean对象的属性字段名保持一致。
     6.List类型
     	User实体需要定义对应list属性。(对于集合的参数绑定,一般需要使用JavaBean对象进行包装)
     7.Set类型
     	Set和List类似,也需要绑定在对象上,而不能直接写在Controller方法的参数中。
     	绑定Set数据时,必须先在Set对象中add相应的数量的模型对象。
     8.Map类型
     	Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数中。
    
  • 请求转发与重定向
    SpringMVC默认采用服务器内部转发的形式展示页面信息。同样也支持重定向页面。

     1.重定向
     	重定向是发一个302的状态码给浏览器,浏览器自己去请求跳转的网页。地址栏会发生改变。
     	重定向到JSP页面:
     		格式:return "redirect:jsp文件名/别名?传递参数(传递中文参数会出现乱码)";
     		避免中文乱码问题(使用redirectAttributes):
     			@RequestMapping(value="/view04") 
     			public String view04(RedirectAttributes redirectAttributes){ 
     				redirectAttributes.addAttribute("uname","张三"); 
     				redirectAttributes.addAttribute("upwd","123456"); 
     				return "redirect:view.jsp"; 
     			}
     	重定向到Controller:
     		格式:return modelAndView;
     		返回ModelAndView对象(用来封装需要响应到页面的数据和视图名字):
     			@RequestMapping(value="/view07") 
     			public ModelAndView view07(ModelAndView modelAndView){ 
     				modelAndView.addObject("uname","admin"); 
     				modelAndView.setViewName("redirect:test01"); 
     				return modelAndView; 
     			}
     	页面中获取参数值:
     		${param.参数名}
     2.请求转发
     	请求转发,直接调用跳转的页面,让它返回。对于浏览器来说,它无法感觉服务器有没有forward。地址栏不发生改变。可以获取请求域中的数据。
     	请求转发到JSP页面:
     		格式:return "forward:jsp文件名/别名?传递参数";
     		设置请求域(使用addAttribute):
     			@RequestMapping("/view10") 
     			public String view10(Model model){ 
     				model.addAttribute("uname","张三"); 
     				return "forward:view.jsp"; 
     			}
     		默认会去指定目录下找JSP页面(配置文件中设置的):return "/../../view";
     	请求转发到Controller:
     		格式:return modelAndView;
     		@RequestMapping("/view13") public ModelAndView view13(ModelAndView modelAndView){ 
     			modelAndView.setViewName("forward:test01?uname=admin"); 
     			return modelAndView; 
     		}
     	页面中获取数据:
     		获取传递的参数:${param.参数名} 
     		获取请求域的数据:${请求域中设置的名称}
    
  • JSON数据开发
    Json在企业开发中已经作为通用的接口参数类型,在页面(客户端)解析很方便。

     @ResponseBody
     	该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
     	返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用(通常用于ajax请求)。
     @RequestBody
     	该注解用于读取Request请求的body部分数据,使用系统默认配置的 HttpMessageConverter进行解析,
     	然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到controller中方法的参数上。
     使用配置
     	1.添加json相关坐标
     		<!-- 添加json 依赖jar包 -->
     		<dependency>
     			<groupId>com.fasterxml.jackson.core</groupId>
     			<artifactId>jackson-core</artifactId>
     			<version>2.10.0</version>
     		</dependency>
     		<dependency>
     			<groupId>com.fasterxml.jackson.core</groupId>
     		 	<artifactId>jackson-databind</artifactId>
     			<version>2.10.0</version>
     		</dependency>
     		<dependency>
     			<groupId>com.fasterxml.jackson.core</groupId>
     			<artifactId>jackson-annotations</artifactId>
     			<version>2.10.0</version>
     		</dependency>
     	2.修改配置文件
     		   <!-- mvc 请求映射 处理器与适配器配置 -->
     		<mvc:annotation-driven>
     			<mvc:message-converters>
         			<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
         			<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
     			</mvc:message-converters>
     		</mvc:annotation-driven>
     	3.注解使用
     		@ResponseBody 
     			返回的是JOSN格式的数据,返回JavaBean对象 或 返回的是JOSN格式的数据,返回集合
     				注解设置在方法体上 或 注解设置在方法返回对象前,修饰符之后
     		@RequestBody
     		@RequestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded类型的内容,一般情况下来说常用其来处理application/json类型。
     		@RequestBody接受的是一个json格式的字符串,一定是一个字符串。
     		通过@RequestBody可以将请求体中的JSON字符串绑定到相应的bean上,当然,也可以将其分别绑定到对应的字符串上。   	 	
     			规定请求的参数是JOSN格式的字符串 
     				注解设置在形参前面
     				//请求传递JSON格式的数据,返回JSON格式的数据
     				 function fun(){
         				$.ajax({
         					//请求方式 Get|Post
             				type:"post",
             				//请求路径
             				url:"json5",
             				//预期服务器返回的额数据类型
             				data:params,
             				//设置服务器请求类型的数据类型为JSON格式
             				contentType:"application/json;charset=utf-8",
             				//传递给服务器的参数
             				dataType:"json",
             				//回调函数,接收服务器返回的响应的结果 
             				(函数中的形参用来接收服务器返回的数据)
             				success:function (data){
                 				console.log(data);
             				}
         				});
    				 }			
    
  • 拦截器

     主要作用:拦截用户的请求并进行相应的处理。
     定义方式:
     	实现接口:org.springframework.web.servlet.HandlerInterceptor
     	继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
     1.拦截器实现:
     	 1.实现HandlerInterceptor接口
     	 	接口实现类
     	 	实现HandlerInterceptor接口
     	 		public boolean preHandle	在目标Handler(方法)执行前 执行 
     	 			返回true:执行handler方法。
     	 			返回false:阻止目标handler方法执行。
     	 		public void postHandle		在目标Handler(方法)执行后,视图生成前执行
     	 		public void afterCompletion	在目标Handler(方法)执行后,视图生成后执行
     	 	xml配置
     	 		1.使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求。
     	 			<mvc:interceptors> 
     	 			 	<bean class="com.yjxxt.springmvc.interceptor.MyInterceptor01"/> 			
     	 			</mvc:interceptors>
     	 		2 (推荐使用).定义在mvc:interceptor下面,可以自定义需要拦截的请求 。
     	 		  如果有多个拦截器满足拦截处理的要求,则依据配置的先后顺序来执行。
     	 		  	<mvc:interceptors>  
     	 		  		<mvc:interceptor> 
     	 		  			<!-- 通过 mvc:mapping 配置需要拦截的资源。支持通配符。可配置多个。 -->
     	 		  			 <mvc:mapping path="/**"/> 
     	 		  			 <!-- "/**"表示拦截所有的请求。 --> <!-- 通过 mvc:mapping 配置不需要被拦截的资源。支持通配符。可配置多个。 --> 
     	 		  			 <mvc:exclude-mapping path="/url/*"/> 
     	 		  			 <!-- "/url/*"表示放行url路径下的请求。 --> 
     	 		  			 <bean class="com.yjxxt.springmvc.interceptor.MyInterceptor01"/> 
     	 		  		</mvc:interceptor> 
     	 		  	</mvc:interceptors>
     	 2.继承HandlerInterceptorAdapter(实际上最终还是HandlerInterceptor接口实现。)
     		子类实现类
     		继承HandlerInterceptorAdapter适配器
     			public boolean preHandle	在目标Handler(方法)执行前 执行 
     	 			返回true:执行handler方法。
     	 			返回false:阻止目标handler方法执行。
     	 		public void postHandle		在目标Handler(方法)执行后,视图生成前执行
     	 		public void afterCompletion	在目标Handler(方法)执行后,视图生成后执行
     	 	xml配置
     	 		<mvc:interceptors> 
     	 			<mvc:interceptor> 
     	 				<!-- 拦截的资源 --> 
     	 				<mvc:mapping path="/**"/> 
     	 				<!-- 放行的资源 --> 
     	 				<mvc:exclude-mapping path="/url/test01"/> 
     	 				<mvc:exclude-mapping path="/url/test02"/> 
     	 				<bean class="com.yjxxt.springmvc.interceptor.MyInterceptor02"/> 
     	 			</mvc:interceptor> 
     	 		</mvc:interceptors>
     2.多个拦截器实现
     如果有多个拦截器满足拦截处理的要求,则依据配置的先后顺序来执行 
     先配置的拦截器的preHandle方法先执行 
     先配置的拦截器的postHandle、afterCompletion方法后执行
     	代码实现
     		实现HandlerInterceptor接口 或 继承HandlerInterceptorAdapter适配器
     	xml配置
     		<mvc:interceptors> 
     			<mvc:interceptor> 
     				<!-- 拦截所有请求 --> 
     				<mvc:mapping path="/**" /> 
     				<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01" /> 
     			</mvc:interceptor> 
     			<mvc:interceptor> 
     				<!-- 拦截所有请求 --> 
     				<mvc:mapping path="/**" /> 
     				<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02" /> 
     			</mvc:interceptor> 
     		</mvc:interceptors>
     3.拦截器应用 - 非法请求拦截
     使用拦截器完成用户是否登录请求验证功能
     	1.用户控制器
     		@Controller
     		public class UserInfo {
     			//用户登录
     			@RequestMapping("login")
     			public String login(HttpSession session){
     				System.out.println("登录成功");
    	 			User user = new User();
     			user.setId(10);
     			user.setUserName("xiaoming");
     			user.setUserPwd("123");
     			//登录成功后将用户的基本信息存入session作用域中
     			session.setAttribute("user",user);
     			return "success";
     			}
     			//用户添加
     			@RequestMapping("add")
     			public String add(){
     				System.out.println("添加成功");
     				return "success";
     			}
     			//用户修改
     			@RequestMapping("update")
     			public String update(){
     				System.out.println("修改成功");
     				return "success";
     			}
     			//用户删除
     			@RequestMapping("delete")
     			public String delete(){
     				System.out.println("删除成功");
    				 return "success";
     	 		}
     		}
     	2.页面定义(success.jsp)
     		<%@ page contentType="text/html;charset=UTF-8" language="java" %> 
     		<html> 
     			<head>
     				<title>Title</title> 
     			</head> 
     		<body>
     			<h3>欢迎登录!</h3> 
     		</body> 
     		</html>
     	3.非法请求拦截器定义
     		public class LoginInterceptor implements HandlerInterceptor {
     			//在目标方法执行之前 运行/拦截
      			@Override
     			public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     				//通过session对象获取作用域用户的状态
     				User user = (User) request.getSession().getAttribute("user");
     				//判断user数据是否存在
     				if(null == user){
         				//未登录状态 提示用户去访问登录接口
         				// response.sendRedirect(request.getContextPath()+"/WEB-INF/jsp/error.jsp"); //重定向  客户端行为
         				request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request,response); //请求转发  服务器端行为
         				//不执行目标方法
         				return false;
    			 	}
    			 		//用户已登录,执行目标方法
     				return true;
     			}
     		}
     	4.xml配置
     		<!-- 拦截所有请求 --> 
     		<mvc:interceptors> 
     			<mvc:interceptor> 
     				<!-- 拦截所有请求 --> 
     				<mvc:mapping path="/**" /> 
     				<!-- 放行用户登录请求 --> 
     				<mvc:exclude-mapping path="/userInfo/login"/> 
     				<bean class="com.xxxx.springmvc.interceptor.LoginInterceptor" /> 
     			</mvc:interceptor> 
     		</mvc:interceptors>
    
  • 文件上传

     1.环境配置
     	pom.xml中添加
     		<!-- 添加 commons-fileupload 依赖 --> 
     		<dependency> 
     			<groupId>commons-fileupload</groupId> 
     			<artifactId>commons-fileupload</artifactId> 
     			<version>1.3.2</version> 
     		</dependency>	
     	spring.xml修改
     		<!-- 文件上传 --> 
     		<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
     			<!-- 允许文件上传的最大尺寸 --> 
     			<property name="maxUploadSize"> 
     				<value>104857600</value> 
     			</property> 
     			<!--设置文件放入临时文件夹的最大大小限制。 
     			此值是阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件。 --> 
     			<property name="maxInMemorySize"> 
     				<value>4096</value> 
     			</property> 
     		</bean>
     2.代码实现
     	单文件上传
     		页面表单
     			input的type设置为file
     			form表单的method设为post,
     			form表单的enctype设置为multipart/form-data,以二进制的形式传输数据
     			<form action="uploadFile" method="post" enctype="multipart/form-data"> 
     				<input type="file" name="file" /> 
     				<button type="submit"> 提交</button> 
     			</form>
     		代码实现
     			@Controller
     			public class FileUpload {
     				@RequestMapping("uploadFile")
     				public void uploadFile(MultipartFile file,HttpServletRequest request){
     					//判断是否上传了文件
     					if(!file.isEmpty()){
         					//为上传的文件准备一个存放路径
         					String path = request.getServletContext().getRealPath("/");
         					//准备目录
         					File filePath = new File(path + "/upload");
         					//判断目录是否存在
        		 			if(!filePath.exists()){
             					filePath.mkdir();//创建目录
         					}
         					//重新创建文件的名称
         					//获取文件原名称
         					String filename = file.getOriginalFilename();
         					//截取文件的后缀  从最后一个点开始
         					String hzName = filename.substring(filename.lastIndexOf("."));
         					//以时间戳为名称创建一个新的文件名字
         					String newFileName = System.currentTimeMillis() + hzName;
         					try {
             					//上传
             					file.transferTo(new File(filePath, newFileName));
             					System.out.println("上传成功");
         					} catch (IOException e) {
             					e.printStackTrace();
             					System.out.println("上传失败");
        		 			}
     					}
     				}
     			}
     	多文件上传
     		页面表单
     			<form action="uploadFiles" method="post" enctype="multipart/form-data"> 
     				<input type="file" name="files" /> 
     				<input type="file" name="files" /> 
     				<input type="file" name="files" /> 
     				<button type="submit"> 提交</button> 
     			</form>
     		代码实现
     			@Controller
     			public class FileUpload {
     				@RequestMapping("uploadFile")
     				public void uploadFiles(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request){
     					for(MultipartFile file:files){
         					uploadFile(file,request);
     					}
     				}
     				public void uploadFile(MultipartFile file,HttpServletRequest request){
     					//判断是否上传了文件
     					if(!file.isEmpty()){
         					//为上传的文件准备一个存放路径
         					String path = request.getServletContext().getRealPath("/");
         					//准备目录
         					File filePath = new File(path + "/upload");
         					//判断目录是否存在
        		 			if(!filePath.exists()){
             					filePath.mkdir();//创建目录
         					}
         					//重新创建文件的名称
         					//获取文件原名称
         					String filename = file.getOriginalFilename();
         					//截取文件的后缀  从最后一个点开始
         					String hzName = filename.substring(filename.lastIndexOf("."));
         					//以时间戳为名称创建一个新的文件名字
         					String newFileName = System.currentTimeMillis() + hzName;
         					try {
             					//上传
             					file.transferTo(new File(filePath, newFileName));
             					System.out.println("上传成功");
         					} catch (IOException e) {
             					e.printStackTrace();
             					System.out.println("上传失败");
        		 			}
     					}
     				}
     			}
    
  • SSM框架集成与测试

     1.环境配置
     	配置pom.xml
     		修改JDK版本为11
     		添加坐标依赖
     		设置资源目录和插件
     	配置web.xml
     	配置servlet-context.xml
     	配置spring.xml
     	配置mybatis.xml
     	配置db.properties
     	添加log4j.properties
     2.添加源代码
     	java下创建
     	com.xxxx.ssm.controller
     		添加UserController.java
     	com.xxxx.ssm.service
     		添加UserService.java
     	com.xxxx.ssm.mapper
     		添加UserMapper.xml映射文件
     	com.xxxx.ssm.dao
     		添加UserDao.java接口
     	com.xxxx.ssm.po
     		添加JavaBean文件User.java
     	添加hello.jsp视图文件,用来展示查询的用户信息
    
  • RestFul URL

     Restful风格的API是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。
     在Restful风格中,用户请求的url使用同一个url,用请求方式:
     	GET(SELECT):从服务器查询,可以在服务器通过请求的参数区分查询的方式。
     	POST(CREATE):在服务器端新建一个资源,调用insert操作。
     	PUT(UPDATE):在服务器端更新资源,调用update操作。
     	PATCH(UPDATE):在服务器端更新资源(客户端提供改变的属性)。(目前jdk7未实现,tomcat7不支持)。
     	DELETE(DELETE):从服务器端删除资源,调用delete语句。
     SpringMVC是通过@RequestMapping及@PathVariable注解提供的RestFul URL。
     映射地址配置:
     	1.准备环境
     		po目录下新建Account.java实体类
     		dao目录下新建AccountDao.java接口类
     		mapper目录下新建AccountMapper.xml映射文件
     		service目录下新建AccountService.java
     	2.URL映射地址配置
     		get请求,执行查询操作
     			@GetMapping("account/{id}") 
     			@ResponseBody public Account queryAccountById(@PathVariable Integer id){ 
     				return accountService.selectById(id); 
     			}
     		delete请求,执行删除操作
     			@DeleteMapping("account/{id}") 
     			@ResponseBody public Map<String,Object> deleteAccount(@PathVariable Integer id){ 
     				int result = accountService.delAccount(id); 
     				Map<String,Object> map=new HashMap<String,Object>(); 
     				if(result == 1 ){ 
     					map.put("msg","success"); 
     					map.put("code",200); 
     				} else { 
     					map.put("msg","error"); 
     					map.put("code",500); 
     				}
     				return map; 
     			}
     		 post请求,执行添加操作
     		 	@PostMapping("account") 
     		 	@ResponseBody public Map<String,Object> saveAccount(@RequestBody Account account){ 
     		 		int result = accountService.saveAccount(account); 
     		 		Map<String,Object> map=new HashMap<String,Object>(); 
     		 		if(result == 1 ){ 
     		 			map.put("msg","success"); 
     		 			map.put("code",200); 
     		 		} else { 
     		 			map.put("msg","error"); 
     		 			map.put("code",500);
     		 		}
     		 		return map; 
     		 	}
     		 put请求,执行更新操作
     		 	@PutMapping("account") 
     		 	@ResponseBody public Map<String,Object> updateAccount(@RequestBody Account account){ 
     		 		int result = accountService.updateAccount(account); 
     		 		Map<String,Object> map=new HashMap<String,Object>(); 
     		 		if(result == 1 ){ 
     		 			map.put("msg","success"); 
     		 			map.put("code",200); 
     		 		} else { 
     		 			map.put("msg","error"); 
     		 			map.put("code",500); 
     		 		}
     		 		return map; 
     		 	}
    
  • 全局异常统一处理

     由于每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。
     所以通过SpringMVC提供的全局异常处理机制,能够将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。
     全局异常处理的3种方式:
     	1.使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver
     	优点:集成简单、有良好的扩展性、对已有代码没有入侵性。
     	缺点:该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。
     		1.配置SimpleMappingExceptionResolver对象
     			<!-- 配置全局异常统一处理的 Bean (简单异常处理器) --> 
     			<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 
     				<!-- 页面在转发时出现异常,设置默认的错误页面 (error代表的是一个视图) --> 
     				<property name="defaultErrorView" value="error"></property> 
     				<!-- 异常发生时,设置异常的变量名 --> 
     				<property name="exceptionAttribute" value="ex"></property> 
     			</bean>
     		可以在处理异常的页面获取异常信息:${ex}
     		2.使用自定义异常
     			参数异常
     				public class ParamsException extends RuntimeException { 
     					private Integer code = 300; 
     					private String msg = "参数异常!";
     					构造器;
     					Get和Set方法;
     				}
     			业务异常
     				public class BusinessException extends RuntimeException { 
     					private Integer code=400; 
     					private String msg="业务异常!";
     					构造器;
     					Get和Set方法;
     				}
     		3.设置自定义异常与页面的映射
     			<!-- 设置自定义异常与页面的映射 --> 
     			<property name="exceptionMappings"> 
     				<props> 
     					<!-- key:自定义异常对象的路径; 标签中设置具体的处理页面的视图名--> 
     					<prop key="com.xxxx.ssm.exception.BusinessException">buss_error</prop> 
     					<prop key="com.xxxx.ssm.exception.ParamsException">params_error</prop> 
     				</props> 
     			</property>
     	2.实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器(推荐使用)
     	优点:集成简单、有良好的扩展性、对已有代码没有入侵性等,
     	同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。
     		1.实现HandlerExceptionResolver接口
     			@Component 
     			public class GlobalExceptionResolver implements HandlerExceptionResolver { 
     				@Override 
     				public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) { 
     					ModelAndView mv = new ModelAndView("error"); 
     					mv.addObject("ex","默认错误信息"); 
     					return mv; 
     				} 
     			}
     		2.自定义异常处理
     			@Component 
     			public class GlobalExceptionResolver implements HandlerExceptionResolver { 
     				@Override 
     				public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) { 
     					ModelAndView mv = new ModelAndView("error"); 
     					mv.addObject("ex","默认错误信息"); 
     					// 判断是否是自定义异常 
     					if (ex instanceof ParamsException) { 
     						mv.setViewName("params_error"); 
     						ParamsException e = (ParamsException) ex; 
     						mv.addObject("ex", e.getMsg()); 
     					}
     					if (ex instanceof BusinessException) {
     						mv.setViewName("business_error"); 
     						BusinessException e = (BusinessException) ex; 
     						mv.addObject("ex", e.getMsg()); 
     					}
     					return mv; 
     				} 
     			}
     	3.使用@ExceptionHandler注解实现异常处理
     	优点:集成简单、有扩展性好(只需要将要异常处理的Controller类继承于BaseController即可)、不需要附加Spring配置。
     	缺点:该方法对已有代码存在入侵性(需要修改已有代码,使相关类继承于BaseController),在异常处理时不能获取除异常以外的数据。
     		页面处理器继承BaseController
     			public class BaseController { 
     				@ExceptionHandler 
     				public String exc(HttpServletRequest request,HttpServletResponse response,Exception ex){ 
     					request.setAttribute("ex", ex); 
     					if(ex instanceof ParamsException){ 
     						return "error_param"; 
     					}
     					if(ex instanceof BusinessException){ 
     						return "error_business"; 
     					}
     					return "error"; 
     				} 
     			}
     未捕获异常的处理
     	全面而有效的异常处理机制。
     	修改web.xml文件
     		<!-- 出错页面定义 --> 
     		<error-page> 
     			<exception-type>java.lang.Throwable</exception-type> 
     			<location>/500.jsp</location> 
     		</error-page> 
     		<error-page> 
     			<error-code>500</error-code> 
     			<location>/500.jsp</location> 
     		</error-page> 
     		<error-page> 
     			<error-code>404</error-code> 
     			<location>/404.jsp</location> 
     		</error-page>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值