SpringMVC——请求参数的绑定 封装对象 常用注解 执行方法的响应类型 文件上传 异常处理 拦截器
SpringMVC基本概念MVC设计模型Model模型JavaBeanView视图JSPController控制器ServletSpringMVC和Strut2的优劣分析共同点它们都是表现层框架,都是基于 MVC 模型编写的。它们的底层都离不开原始 ServletAPI。它们处理请求的机制都是一个核心控制器。区别Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
SpringMVC基本概念
MVC设计模型
- Model模型 JavaBean
- View视图 JSP
- Controller控制器 Servlet
SpringMVC和Strut2的优劣分析
共同点
- 它们都是表现层框架,都是基于 MVC 模型编写的。
- 它们的底层都离不开原始 ServletAPI。
- 它们处理请求的机制都是一个核心控制器。
区别
- Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
- Spring MVC 是基于方法设计的,而 Struts2 是基于类
- Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
- Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
- (JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean 的属性上面,就可以在需要校验的时候进行校验了。)
- Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高
入门案例
搭建环境
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
执行流程
入门案例的执行流程
- 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,
就会加载springmvc.xml配置文件- 开启了注解扫描,那么HelloController对象就会被创建
- 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解
找到执行的具体方法- 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件(方法的返回值就是指定目录下的JSP文件名)
- Tomcat服务器渲染页面,做出响应
springmvc.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--开启注解扫描--> <context:component-scan base-package="com.atgw"/> <!--视图解析器对象--> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!--开启注解SpringMVC框架注解支持--> <mvc:annotation-driven/> </beans>
web.xml
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcherServlet</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> <load-on-startup>1</load-on-startup><!--在开启服务器的时候就加载上面的springmvc.xml--> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
ControllerHolle
程序//控制器类 @Controller public class HelloController { @RequestMapping(path = "/hello") public String sayHello(){ System.out.println("Hello StringMVC"); return "success"; } }
RequestMapping注解
当RequestMapping
注解在类和类下的方法上都有的时候,在请求的路径上要同时写全路径
//控制器类
@Controller
@RequestMapping(path = "/user")
public class HelloController {
@RequestMapping(path = "/testRequestMapping")
public String testRequestMapping(){
System.out.println("测试RequestMapping");
return "success";
}
}
下面要写全路径(类的加上方法的path)
<a href="user/testRequestMapping">RequestMapping超链接</a>
作用
-
value
:用于请求指定的url,它和path属性的作用是一样的 -
method
:用于指定请求方式(Get,Post等)@RequestMapping(value = "/testRequestMapping",method = {RequestMethod.POST}) public String testRequestMapping(){ System.out.println("测试RequestMapping"); return "success"; }
-
params
:用于指定限定请求参数的条件,它支持简单的表达式,要求请求参数的key和value必须和配置的一模一样@RequestMapping(value = "/testRequestMapping",params = {"username=admin","password"}) public String testRequestMapping(){ System.out.println("测试RequestMapping"); return "success"; }
<a href="user/testRequestMapping?username=admin&password=123">RequestMapping超链接</a>
-
发送请求中必须包含指定的请求头
请求参数的绑定
在请求的路径中传入参数,我们可以在控制器类中的方法中写入参数并获取(底层是通过反射实现的)
ParamController
程序
@Controller
@RequestMapping(path = "/user")
public class ParamController {
@RequestMapping(path = "/testParam")
public String testParam(String username,String password){
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
return "success";
}
}
param.jsp
<a href="user/testParam?username=yiersansiwu&password=456321">Param请求</a>
封装到JavaBean对象中
User
类
public class User {
private String uname;
private Integer age;
}
Account
类
public class Account implements Serializable {
private String username;
private String password;
private Double money;
//引用类型
private User user;
}
param.jsp
<form action="user/saveAccount" method="post">
<%--下面的name属性要和封装的JavaBean对象的属性名一致--%>
用户名:<input type="text" name="username"><br/>
密码:<input type="text" name="password"><br/>
金额:<input type="text" name="money"><br/>
用户姓名:<input type="text" name="user.uname"><br/>
用户年龄:<input type="text" name="user.age"><br/>
<input type="submit" value="提交"><br/>
</form>
配置中文乱码的过滤器
web.xml
文件
<!--配置中文乱码的过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
封装集合类型
Account
类
public class Account implements Serializable {
private String username;
private String password;
private Double money;
private List<User> list;
private Map<String,User> map;
}
param.jsp
<form action="user/saveAccount" method="post">
<%--下面的name属性要和封装的JavaBean对象的属性名一致--%>
用户名:<input type="text" name="username"><br/>
密码:<input type="text" name="password"><br/>
金额:<input type="text" name="money"><br/>
用户姓名1:<input type="text" name="list[0].uname"><br/>
用户年龄1:<input type="text" name="list[0].age"><br/>
用户姓名2:<input type="text" name="map['one'].uname"><br/>
用户年龄2:<input type="text" name="map['one'].age"><br/>
<input type="submit" value="提交"><br/>
</form>
Account{username='gao123', password='123456', money=999.0, list=[User{uname='熊大', age=9}], map={one=User{uname='熊二', age=8}}}
自定义类型转换器
先创建一个类型转换器(实现Converter<String, Date>
接口)
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
//判断是否为空
if (s == null){
throw new RuntimeException("您还没有传入数据!");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
//字符串转换成日期
return df.parse(s);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误!");
}
}
}
springmvc.xml
配置自定义类型转换器
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.atgw.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--开启注解SpringMVC框架注解支持-->
<mvc:annotation-driven conversion-service="conversionService"/><!--配置类型转换器生效-->
获取Servlet原生的API
//获取servlet原生的API
@RequestMapping(path = "/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
System.out.println(request);
HttpSession session = request.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
System.out.println(response);
return "success";
}
<a href="user/testServlet">Servlet原生的API</a>
常用注解
RequestParam
注解
@Controller
@RequestMapping("/anno")
public class AnnoController {
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name = "name") String username){
System.out.println(username);
return "success";
}
}
<<a href="anno/testRequestParam?name=高先生">Anno链接</a>
当请求的路径中的参数name
和控制器类的方法获取的参数名不一致时,我们可以添加@RequestParam(name = "name")
注解来配置
RequestBody
注解
用于获取请求体的内容,直接使用得到的是key=value&key=value结构的数据
因为
Get
请求没有请求体,所以Get
请求不适用
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println(body);
return "success";
}
<form action="anno/testRequestBody" method="post">
用户姓名:<input type="text" name="username"><br/>
用户年龄:<input type="text" name="age"><br/>
<input type="submit" value="提交"><br/>
</form>
结果:
username=gao123&age=12
PathVaribale
注解
Restful风格的URL
一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
- 请求路径一样,可以根据不同的请求方式去执行后台的不同方法
- restful风格的URL优点
- 结构清晰
- 符合标准
- 易于理解
- 扩展方便
【GET】 /users # 查询用户信息列表 【GET】 /users/1001 # 查看某个用户信息 【POST】 /users # 新建用户信息 【PUT】 /users/1001 # 更新用户信息(全部字段) 【PATCH】 /users/1001 # 更新用户信息(部分字段) 【DELETE】 /users/1001 # 删除用户信息
@RequestMapping("testRequestVariable/{sid}")
public String testPathVariable(@PathVariable(name = "sid") String id){
System.out.println(id);
return "success";
}
<a href="anno/testRequestVariable/10">RequestVariable注解</a>
RequestHeader
注解
获取请求头的值
//获取RequestHeader注解中value值对应的请求头
@RequestMapping("testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "accept") String header){
System.out.println(header);
return "success";
}
<a href="anno/testRequestHeader">testRequestHeader注解</a>
结果:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
CookieValue
注解
获取Cookie的值
//获取Cookiev值
@RequestMapping("testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookie){
System.out.println(cookie);
return "success";
}
<a href="anno/testCookieValue">testCookieValue注解</a>
结果:
5800F99C212F2A64740BB9B558ED6803
ModelAttribute
注解
作用
- 出现在方法上:表示当前方法会在控制器方法执行前线执行
- 出现在参数上:获取指定的数据给参数赋值。
应用场景
- 当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。
<form action="anno/testModelAttribute" method="post">
用户名:<input type="text" name="uname"><br/>
年龄:<input type="text" name="age"><br/>
<input type="submit" value="提交">
</form>
有返回值
@RequestMapping(value = "/testModelAttribute")
public String testModelAttribute(User user){
System.out.println("testModelAttribute........");
System.out.println(user);
return "success";
}
//该方法会先执行
@ModelAttribute
public User showUser(String uname){
System.out.println("showUser方法执行了");
//通过User查询数据库(模拟)
User user = new User();
user.setUname(uname);//uname是从表单中获取的
user.setAge(20);//如果表单没有此项,则会采用从数据库中获取的
user.setDate(new Date());
return user;
}
无返回值
@RequestMapping(value = "/testModelAttribute")
public String testModelAttribute(@ModelAttribute("123") User user){
System.out.println("testModelAttribute........");
System.out.println(user);
return "success";
}
//该方法会先执行
@ModelAttribute
public void showUser(String uname, Map<String,User> map){
System.out.println("showUser方法执行了");
//通过User查询数据库(模拟)
User user = new User();
user.setUname(uname);//uname是从表单中获取的
user.setAge(20);//如果表单没有此项,则会采用从数据库中获取的
user.setDate(new Date());
map.put("123",user);
}
结果:
showUser方法执行了
testModelAttribute........
User{uname='gao123', age=12, date=Fri Feb 05 19:48:36 CST 2021}
SessionAttributes
注解
用于多次执行控制器方法间的参数共享
@Controller
@RequestMapping("/anno")
@SessionAttributes(value = {"msg"})//把msg=美美存入到Session域
public class AnnoController {
@RequestMapping(value = "/testSessionAttributes")
public String testSessionAttributes(Model model){
//底层会存储到request域对象中
model.addAttribute("msg","美美");
return "success";
}
}
<a href="anno/testSessionAttributes">SessionAttributes注解</a>
登陆成功页面获取域对象的值
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
${requestScope}<br/>
${sessionScope}
Session域中的数据同样也可以在其他的方法中获取
//从Session域获取值
@RequestMapping(value = "/getSessionAttribute")
public String getSessionAttribute(ModelMap modelMap){
System.out.println(modelMap.get("msg"));
return "success";
}
执行方法的响应
返回类型是void
因为返回类型是void,所以就不能再对应指定目录下的响应文件了
采取下面的方法
-
请求转发(一次请求)
@RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{ //编写请求转发的程序 request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response); return; }
<a href="user/testVoid">testVoid方法</a>
-
重定向(两次请求)
//重定向(WEB-INF里面的内容不能直接请求) response.sendRedirect(request.getContextPath()+"/index.jsp");
-
直接响应
@RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{ //编写请求转发的程序 //request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response); //重定向(WEB-INF里面的内容不能直接请求) // response.sendRedirect(request.getContextPath()+"/index.jsp"); // return; //设置中文乱码 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); //直接响应 response.getWriter().print("你好"); return; }
使用关键字forward
和redirect
进行页面跳转
使用上面的方式进行页面跳转时,就不使用视图解析器对象了
//使用关键字forward和redirect来进行页面跳转
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
//请求转发
// return "forward:/WEB-INF/pages/success.jsp";
//重定向(重定向不能访问WEB-INF里面的内容)
return "redirect:/index.jsp";
}
<a href="user/testForwardOrRedirect">testForwardOrRedirect</a>
过滤静态资源
我们在
web.xml
文件中配置了前端控制器,它会对所有的资源进行拦截过滤,导致我们的静态资源(webapp目录下的css,js,images目录)不能正常使用,所以我们在springmvc.xml
文件中对前端控制器进行配置,让其对静态资源不进行拦截
springmvc.xml
文件
<!--前端控制器,哪些静态资源不拦截(webapp目录下的资源)-->
<mvc:resources mapping="/js/**/" location="/js/"></mvc:resources>
<mvc:resources mapping="/css/**/" location="/css/"></mvc:resources>
<mvc:resources mapping="/images/**/" location="/images/"></mvc:resources>
下面静态资源可以正常访问
<script src="js/jquery.min.js"></script>
<script>
//页面加载
$(function () {
$("#btn").click(function () {
alert("Hello btn");
});
});
</script>
返回类型是ModelAndView类型
//返回值是ModelAndView类型
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
//模拟从数据库中查询出对象
User user = new User();
user.setUsername("O(∩_∩)O哈哈~");
user.setAge(20);
user.setPassword("234");
//把user对象存储到mv对象中,也会把user对象存入到request对象
mv.addObject("user",user);
//跳转到哪个页面
mv.setViewName("success");
return mv;
}
<a href="user/testModelAndView">testModelAndView</a>
上面的操作也会把user对象存入到request对象
success.jsp
页面
${requestScope.user}<br/>
${requestScope.user.username}<br/>
${requestScope.user.password}<br/>
${requestScope.user.age}<br/>
响应Json数据之发送Ajax请求
response.jsp
<script src="js/jquery.min.js"></script>
<script>
//页面加载
$(function () {
$("#btn").click(function () {
//发送Ajax请求
$.ajax({
//编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"向飒飒","password":"123","age":30}',
dataType:"json",
type:"post",
success:function (data) {
//data服务器响应的json数据
}
});
});
});
</script>
//模拟异步请求响应
@RequestMapping("/testAjax")
public void testAjax(@RequestBody String body){//获取请求体
System.out.println("testAjax方法执行了");
System.out.println(body);
}
后台响应数据之后(封装修改)做出回传响应
//模拟异步请求响应
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){//获取请求体
System.out.println("testAjax方法执行了");
//客户端发送ajax请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
//作出相应,模拟查询数据库,修改数据之后返回
user.setUsername("山地车");
user.setAge(50);
//返回相应
return user;
}
ajax
做出响应
success:function (data) {
//data服务器响应后端的json数据
alert(data.toString());
alert(data.username);
alert(data.password);
alert(data.age);
}
文件上传
原理
传统方式
文件上传坐标
<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>
<h3>文件上传</h3>
<a></a>
<form action="user/fileupload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br/>
<input type="submit" value="上传">
</form>
//文件上传
@RequestMapping(value = "/fileupload1")
public String fileupload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
System.out.println(path);
//判断该路径是否存在
File file = new File(path);
if (!file.exists()){
//创建该文件夹
file.mkdirs();
}
//解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for (FileItem item : items){
//进行判断,当前item对象是否是文件上传项
if (item.isFormField()){
//说明是普通表单项
}else {
//说明上传文件项
//获取上传文件名
String filename = item.getName();
//把文件名设置成唯一值(使用UUID)
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" +filename;
//完成文件上传
item.write(new File(path,filename));
//删除临时文件
item.delete();
}
}
return "success";
}
springmvc方式
<h3>springmvc方式文件上传</h3>
<a></a>
<form action="user/fileupload2" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br/>
<input type="submit" value="上传">
</form>
//springmvc方式文件上传
@RequestMapping(value = "/fileupload2")
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("SpringMVC文件上传");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
System.out.println(path);
//判断该路径是否存在
File file = new File(path);
if (!file.exists()){
//创建该文件夹
file.mkdirs();
}
//获取上传文件名
String filename = upload.getOriginalFilename();
//把文件名设置成唯一值(使用UUID)
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" +filename;
//完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
springmvc跨服务器上传文件
坐标
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
<h3>跨服务器方式文件上传</h3>
<a></a>
<form action="user/fileupload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br/>
<input type="submit" value="上传">
</form>
//跨服务器方式文件上传
@RequestMapping(value = "/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器文件上传");
//定义上传文件的服务器路径
String path = "http://localhost:9090/uploads/";
//获取上传文件名
String filename = upload.getOriginalFilename();
//把文件名设置成唯一值(使用UUID)
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" +filename;
//创建客户端对象
Client client = Client.create();
//和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
//完成文件上传
webResource.put(upload.getBytes());
return "success";
}
SpringMVC的异常处理
自定义异常类
public class SysException extends Exception {
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
自定义异常处理器
public class SysExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) {
//获取到异常对象
SysException e = null;
if (ex instanceof SysException){
e = (SysException)ex;
}else {
e = new SysException("系统正在维护...");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());//获取错误信息
mv.setViewName("error");
return mv;
}
配置异常处理器
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="com.atgw.exception.SysExceptionResolver">
</bean>
@Controller
@RequestMapping(value = "/user")
public class UserController {
@RequestMapping("/testException")
public String testException() throws Exception{
System.out.println("testException执行了");
try {
//模拟异常
int a = 10/0;
}catch (Exception e){
//打印异常信息
e.printStackTrace();
//抛出自定义异常信息
throw new SysException("查询所有用户出现错误了");
}
return "success";
}
}
<a href="user/testException">异常处理</a>
友好提示页面error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
${errorMsg}
拦截器
SpringMVC拦截器类似于Servlet开发中的过滤器,用于处理器进行预处理和后处理
- 过滤器对所有的资源都可以拦截
- 拦截器只能对
Controller
进行拦截
MyInterceptor1
自定义拦截器
//自定义拦截器
public class MyInterceptor1 implements HandlerInterceptor {
/*
预处理,controller方法执行前
return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
return false 不放行,权限检查
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1拦截器执行了...前");
//不放行时,请求转发到error.jsp页面
//request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/*
controller方法执行后,success.jsp方法执行前
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("controller方法执行后,success.jsp方法执行前");
//如果在这里进行页面跳转的话,比如跳转到error.jsp页面,success.jsp页面会执行,但是不会跳转到success.jsp
}
/*
success.jsp页面之后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("success.jsp页面之后");
}
}
springmvc.xml
配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--配置第一个拦截器-->
<mvc:interceptor>
<!--要拦截的具体方法-->
<mvc:mapping path="/user/*"/><!--控制类里面的方法-->
<!--不要拦截的方法-->
<!--<mvc:exclude-mapping path=""/>-->
<!--配置拦截器对象(自定义的拦截器或者已经提供的)-->
<bean class="com.atgw.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
index.jsp
<h3>拦截器</h3>
<a href="user/testInterceptor">拦截器</a>
UserController
程序
@Controller
@RequestMapping(value = "/user")
public class UserController {
@RequestMapping("/testInterceptor")
public String testInterceptor() {
System.out.println("testInterceptor执行了");
return "success";
}
}
更多推荐
所有评论(0)