Spring异常处理
原有处理方式
try{}catch{}
块- 声明throws异常
SpringMVC处理方式
Controller处理可以将错误捕获并定位到一个错误页面jsp页面
全局异常处理
处理所有Controller异常
Spring-mvc.xml内容:
<!--配置全局异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--<prop key="异常类型">视图名</prop>-->
<!--<prop key="java.lang.NumberFormatException">errorPage/500</prop>-->
<!--<prop key="java.lang.NumberFormatException">errorPage/500</prop>-->
<prop key="java.lang.Exception">errorPage/500</prop>
</props>
</property>
</bean>
CalculatorController.java内容:
package biuaxia.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Class Describe:计算器
*
* @author biuaxia
* @date 2018/11/17
* @time 12:48
*/
@Controller
public class CalculatorController {
@RequestMapping("calculator")
public String showCalculator() {
return "calculator";
}
@RequestMapping("add")
public ModelAndView add(String a, String b) {
ModelAndView view = new ModelAndView("calculator");
view.getModel().put("result", Double.parseDouble(a) + Double.parseDouble(b));
view.getModel().put("a", a);
view.getModel().put("b", b);
return view;
}
//@RequestMapping("add")
public ModelAndView addTry(String a, String b) {
ModelAndView view = new ModelAndView("calculator");
try {
view.getModel().put("result", Double.parseDouble(a) + Double.parseDouble(b));
view.getModel().put("a", a);
view.getModel().put("b", b);
return view;
} catch (NumberFormatException e) {
view.setViewName("errorPage/500");
view.getModel().put("errInfo", e.toString());
return view;
}
}
@RequestMapping("del")
public ModelAndView del(String c, String d) {
ModelAndView view = new ModelAndView("calculator");
view.getModel().put("result", Double.parseDouble(c) - Double.parseDouble(d));
view.getModel().put("c", c);
view.getModel().put("d", d);
return view;
}
}
错误页面errorPage/500.jsp内容:
<%--
Created by IntelliJ IDEA.
User: biuaxia
Date: 2018/11/17
Time: 11:33
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<title>错误 - biuaxia</title>
<link href="https://cdn.bootcss.com/amazeui/2.7.2/css/amazeui.min.css" rel="stylesheet">
<style>
.get {
background: #1E5B94;
color: #fff;
text-align: center;
padding: 100px 0;
height: 100%;
}
.get-title {
font-size: 200%;
border: 2px solid #fff;
padding: 20px;
display: inline-block;
}
.footer p {
color: #7f8c8d;
margin: 0;
padding: 15px 0;
text-align: center;
background: #2d3e50;
}
.am-g {
margin: 10% auto;
}
</style>
</head>
<body>
<div class="get">
<div class="am-g">
<div class="am-u-lg-12">
<h1 class="get-title">不知道大佬您在玩什么,居然搞崩溃了我们的服务器!</h1>
</div>
<%--<div class="am-u-sm-12"><p>错误信息:<code>${errInfo}</code></p></div>--%>
<div class="am-u-lg-12">
<a href="index.do" class="am-btn am-btn-primary">返回首页</a>
</div>
</div>
</div>
<!--[if lt IE 9]>
<script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.staticfile.org/modernizr/2.8.3/modernizr.js"></script>
<![endif]-->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/amazeui/2.7.2/js/amazeui.min.js"></script>
</body>
</html>
计算器页面calculator.jsp内容:
<%--
Created by IntelliJ IDEA.
User: biuaxia
Date: 2018/11/17
Time: 11:33
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<title>计算器 - biuaxia</title>
<link href="https://cdn.bootcss.com/amazeui/2.7.2/css/amazeui.min.css" rel="stylesheet">
<style>
.footer p {
color: #7f8c8d;
margin: 0;
padding: 15px 0;
text-align: center;
background: #2d3e50;
}
</style>
</head>
<body>
<header class="am-topbar am-topbar-fixed-top">
<div class="am-container">
<h1 class="am-topbar-brand">biuaxia</h1>
<button class="am-topbar-btn am-topbar-toggle am-btn am-btn-sm am-btn-secondary am-show-sm-only"
data-am-collapse="{target: '#collapse-head'}"><span class="am-sr-only">导航切换</span> <span
class="am-icon-bars"></span></button>
<div class="am-collapse am-topbar-collapse" id="collapse-head">
<ul class="am-nav am-nav-pills am-topbar-nav">
<li><a href="index.do">首页</a></li>
<li class="am-active"><a href="calculator.do">计算器</a></li>
</ul>
<div class="am-topbar-right">
<button class="am-btn am-btn-secondary am-topbar-btn am-btn-sm"><span class="am-icon-pencil"></span> 注册
</button>
</div>
<div class="am-topbar-right">
<button class="am-btn am-btn-primary am-topbar-btn am-btn-sm"><span class="am-icon-user"></span> 登录
</button>
</div>
</div>
</div>
</header>
<div class="am-g am-container" style=" margin-top: 1rem;">
<h2 class="am-text-center">加法运算</h2>
<div class="am-u-lg-12 am-text-center">
<form action="add.do" class="am-form-inline">
<input type="text" class="am-form-field am-round" placeholder="${a}" name="a"/>
+
<input type="text" class="am-form-field am-round" placeholder="${b}" name="b"/>
=${result}
<input type="submit" value="计算">
</form>
</div>
<h2 class="am-text-center">减法运算</h2>
<div class="am-u-lg-12 am-text-center">
<form action="del.do" class="am-form-inline">
<input type="text" class="am-form-field am-round" placeholder="${c}" name="c"/>
-
<input type="text" class="am-form-field am-round" placeholder="${d}" name="d"/>
=${result1}
<input type="submit" value="计算">
</form>
</div>
<div class="am-u-md-6">
<div class="am-panel am-panel-primary">
<div class="am-panel-hd"><h3 class="am-panel-title">第一次提交修改内容(2018年11月17日13:12:03)</h3></div>
<div class="am-panel-bd">
<h3>修改说明</h3>
<p>两个文本输入框若有一个为空则会出现 <span class="am-text-danger">HTTP Status 400 – Bad Request</span> 错误</p>
<h3>解决办法</h3>
<p>添加全局异常处理</p>
<h3>触发该bug说明</h3>
<p>去除CalculatorController.java中的addTry方法标记,即可触发try错误处理</p>
</div>
</div>
</div>
<div class="am-u-md-6">
<div class="am-panel am-panel-primary">
<div class="am-panel-hd"><h3 class="am-panel-title">第二次提交修改内容(2018年11月17日13:12:03)</h3></div>
<div class="am-panel-bd">
<h3>修改说明</h3>
<p>使用Spring MVC的<span class="am-text-danger">ExceptionHandlerExceptionResolver / SimpleMappingExceptionResolver</span>配置(spring-mvc.xml)全局异常处理
</p>
<h3>配置内容</h3>
<p>
<pre class="am-pre-scrollable">
</pre>
</p>
<h3>触发该bug说明</h3>
<p>去除CalculatorController.java中的addTry方法标记,即可触发try错误处理</p>
</div>
</div>
</div>
</div>
<footer class="footer">
<p>© 2014 <a href="http://www.yunshipei.com" target="_blank">AllMobilize, Inc.</a> Licensed under <a
href="http://opensource.org/licenses/MIT" target="_blank">MIT license</a>. by the AmazeUI Team.</p>
</footer>
<!--[if lt IE 9]>
<script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.staticfile.org/modernizr/2.8.3/modernizr.js"></script>
<![endif]-->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/amazeui/2.7.2/js/amazeui.min.js"></script>
</body>
</html>
运行效果图:
运算界面:
出错页面:
我们只需配置一下就等价于各个try的捕获
局部异常处理
上面的处理只能是运行时异常,是处理不到类似于400之类的异常
那么处理某个单独的异常怎么做呢?
在对应的Controller下再新写一个@ExceptionHandler方法
例如我想要减法运算的异常跳转到计算器页面而不是500,并且还有提示
CalculatorController.java内容:
@ExceptionHandler
public ModelAndView exception(Exception e) {
ModelAndView view = new ModelAndView("calculator");
view.getModel().put("errInfo", "数据源有误");
return view;
}
注意:方法参数必须有一个Exception,方法名随意,返回类型可以是ModelAndView或者String
如果全局和局部都存在,那么先走局部
流程:
DispatcherServlet->HandlerMapping->XxController->ExceptionResolver->ViewResolver
使用Spring框架提供的自定义异常
和拦截器性质差不多都得实现一个接口,这里我们实现HandlerExceptionResolver
接口
例如自定义异常类的步骤
MyException.java内容
package biuaxia.mvc.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Class Describe:
*
* @author biuaxia
* @date 2018/11/17
* @time 16:04
*/
public class MyException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
/**
* 可以在这里对异常的单独处理
* 例如写入log文件或者发送短信之类的
*/
ModelAndView view = new ModelAndView();
view.getModel().put("errInfo", e.toString());
return view;
}
}
spring-mvc.xml内容:
<!--配置自带的全局异常处理-->
<!--<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!–<prop key="异常类型">视图名</prop>–>
<!–<prop key="java.lang.NumberFormatException">errorPage/500</prop>–>
<!–<prop key="java.lang.NumberFormatException">errorPage/500</prop>–>
<prop key="java.lang.Exception">errorPage/500</prop>
</props>
</property>
</bean>-->
<!--配置自定义的全局异常处理-->
<bean class="biuaxia.mvc.exception.MyException"></bean>
如果想要牛一点的自定义我们可以在自定义异常类添加属性
MyException.java内容(其余内容不变哈)
private String viewName;
public void setViewName(String viewName) {
this.viewName = viewName;
}
spring-mvc.xml
<!--配置自定义的全局异常处理-->
<bean class="biuaxia.mvc.exception.MyException">
<property name="viewName" value="errorPage/500"></property>
</bean>
异常的处理总结
- 全局异常则在spring-mvc.xml配置文件中的bean->class使用到了
ExceptionHandlerExceptionResolver / SimpleMappingExceptionResolver
类 - 局部异常则需要在对应Controller新建方法,参数列表携带Exception,并且打上标记
@ExceptionHandler
- 自定义异常首先实现HandlerExceptionResolver,然后使用时就在配置文件中追加定义
文件上传
逻辑流程:
/upload.do->CommonsMultipartResolver(commons-fileupload.jar|commons-io.jar)->Controller(File xxx)
使用步骤
- 导入commons-fileupload.jar/commons-io.jar
- 在Spring配置文件追加CommonsMultipartResolver组件的定义
- 文件上传的Controller配置
package biuaxia.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
/**
* Class Describe:
*
* @author biuaxia
* @date 2018/11/17
* @time 16:34
*/
@Controller
public class UploadController {
@RequestMapping("showUpload")
private String showUpload() {
return "showUpload";
}
@RequestMapping("upload")
private ModelAndView upload(MultipartFile mf) {
System.out.println("原始文件名:" + mf.getOriginalFilename());
System.out.println("上传后文件名:" + mf.getName());
System.out.println("文件类型:" + mf.getContentType());
System.out.println("文件大小:" + mf.getSize());
ModelAndView view = new ModelAndView("showUpload");
view.getModel().put("msg", "上传成功");
return view;
}
}
注意,表单的name必须和上传的mf一致!否则收不到文件
当然你可以在需要接受的参数列表指定@RequestParam("mf") MultipartFile userUploadFile
上传界面:
上传路径:
做个小笔记
后面可以查看一下这个网址详细理解文件上传:文件上传那些事:多图上传、大文件上传、断点续传功能实现与分析