SpringMVC从入门到掌握
文章目录
1. SpringMvc的概述
- Spring MVC为展现层提供的基于MVC设计理念的优秀Web框架,是目前最主流的MVC框架之一。
- Spring3.0后全面超越了Struts2,称为最优秀的MVC框架。
- Spring MVC通过一套MVC注解,让POJO称为处理请求的控制器,无需实现任何接口。
- 支持REST风格的Web请求。采用了松散耦合可插拔组件结构,比其它MVC框架更具扩展性和灵活性。
2. SpringMvc的搭建
-
导入依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.1.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.7</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.validation/validation-api --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging --> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.3.2.Final</version> </dependency>
-
配置xml文件
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <!-- SpringMVC配置文件路径 --> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 启动时自动加载配置文件 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 注意:如果没有配置 init-param 设置文件路径,SpringMvc默认回去WEB-INF下查询 servlet-nameservlet.xml -->
-
创建处理类
注解
@Controller // 修饰类为一个控制器 public class HelloWorld { @RequestMapping("/hello") // 修饰方法(或类)的请求路径 public String hello(){ System.out.println("hello spring mvc"); return "hello"; // 视图 } }
<!-- 配置Spring MVC自动扫描的路径 --> <context:component-scan base-package="com.*.controller" /> <!-- 配置视图解析器 将视图返回字符串解析到:/WEB-INF/view/返回值.jsp 下--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 视图前缀 --> <property name="prefix" value="/WEB-INF/view/" /> <!-- 视图后置 --> <property name="suffix" value=".jsp" /> </bean>
接口
public class HelloWorld implements Controller{ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("HelloWorld"); return new ModelAndView("hello"); // 视图 } }
<!-- name:代表访问路径 class:指定控制器类 --> <bean name="/helloworld" class="com.znsd.controller.HelloWorld" />
两种方式,推荐使用注解 (不是必须,分情况而待)
3. SpringMvc的常用注解总结
-
@Component:一个普通的Bean类。
-
@Repository :用于标注持久层DAO类
-
@Service :用于标注业务层类
-
@Controller :用于标注控制器类
-
@RequestMapping:
-
类定义处:提供初步的映射信息,为该类下所有请求方法添加前缀。
-
方法定义处:提供进一步的映射信息,提供方法的请求路径。
@Controller @RequestMapping("world") // 类似Struts2的@Namespace(命名空间) public class HelloWorld { @RequestMapping("/hello") public String hello(){ System.out.println("hello spring mvc"); return "hello"; } }
-
@RequestMapping 的 value、method、params及heads分别表示请求url,请求方法,请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可以让请求更加精确化。
-
在@RequestMapping 中 还支持 Ant风格的URL。
-
?:匹配文件中一个字符。
-
*:匹配文件中任意字符。
-
**:匹配多层路径。
/user/*/create:匹配/user/aaa/create,/user/bbb/crate /user/**/create:匹配/user/create,/user/aaa/bbb/create /user/create??:匹配/user/createaa,/user/createbb
-
-
-
-
@PathVariable:URL模版方式
// @PathVariable:用来映射URL中的占位符。映射的变量名必须和占位符中的名称一致。 @RequestMapping("/delete/{userid}") public String delete(@PathVariable("userid")int userid) { System.out.println("userid=" + userid); return "hello"; }
-
@RequestParam:获取请求参数
// @RequtParam:获取页面传递过来的参数,GET和POST都支持。 @RequestMapping("/testRequestParam") public String testRequestParam(@RequestParam("username")String username, @RequestParam("age")int age){ System.out.println("username=" + username); System.out.println("age=" + age); return "hello"; }
@RequestParam 还有三个属性
- value:指定参数的名称
- required:指定参数是否为必填 (boolean)
- defaultValue:指定参数的默认值
-
@RequestHeader:获取请求头内容
// 请求头包含了若干的属性,用来获取客户端的信息。通过@RequestHeader可以用来获取请求头中的信息 @RequestMapping("/testRequestHeader") public String testRequestHeader(@RequestHeader("Accept-Language") String language){ System.out.println("language=" + language); return "hello"; }
-
@CookiValue:获取客户端Cookie
// @CookieValue:用来获取客户端Cookie信息。 @RequestMapping("/testCookieValue") public String testCookieValue(@CookieValue("JSESSIONID")String sessionid){ System.out.println("sessionid=" + sessionid); return "hello"; }
-
@ResponseBody:标识为Json返回
-
需要导入依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.7</version> </dependency>
@ResponseBody @RequestMapping(value="/testJackson",method=RequestMethod.GET) public Student testJackson() { User user = new User(); user.setName("李相如"); return user; }
-
4. 实体对象绑定请求参数
<!-- name必须和对象属性名一至 -->
<form action="world/user/create" method="post">
姓名:<input type="text" name="name"><br>
密码:<input type="text" name="pass"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交" />
</form>
public class User {
private String name;
private String pass;
private int age;
}
// Spring MVC会直接将页面元素和实体对象进行匹配,自动转换为实体对象.并且支持级联属性。如address.city等。
@RequestMapping(value = "/user/create", method = RequestMethod.POST)
public String createUser(User user) {
System.out.println(user.toString());
return "hello";
}
5. 处理数据模型
Spring MVC提供一下几种途径返回模型数据:
-
ModeAndView:将处理方法的返回类型设置为ModeAndView,方法体即可通过该模型对象添加模型数据。
-
控制器处理方法如果返回ModelAndView,即包含视图信息,也包含模型信息。
-
构造方法:提供了多种构造方法的重载
-
添加模型数据:
- ModelAndView addObject(String attributeName, Object attributeValue);
- ModelAndView addAllObjects(Map modelMap) ;
-
添加视图
-
void setView(View view);
-
void setViewName(String viewName);
@RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ ModelAndView modelAndView = new ModelAndView("hello"); //添加单个值 modelAndView.addObject("h","Hello Spring MVC"); return modelAndView; }
-
-
Map及Model形参:当形参为Map,Model,ModelMap时,处理方法返回时,Map中的数据会自动添加到模型中。
-
Spring MVC在内部使用了一个Model接口存储模型数据。
-
Spring MVC在调用方法前会创建一个隐含的模型对象作为数据模型的存储容器。如果传入的参数为Map或者Model类型,SpringMVC会自动将对象保存到模型数据中。
@RequestMapping("/testMap") public String testMap(Map<String,Object> map){ map.put("mapdata", "map data"); return "hello"; }
-
-
@SessionAttributes:将模型中的某个属性存储到Session中,以便多个请求之间共享这个属性。
-
如果希望在多个请求之间共享某个模型的数据,则可以在控制器类上标注一个@SessionAttributes,SpringMVC会将对应的属性存储到Session中。
-
@SessionAttributes除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些类型放到Session中。
-
@SessionAttributes(types=User.class) :将隐含模型中所有类型为User属性添加到Session中。
-
@SessionAttributes(value={“user1”,“user2”}):将user1对象和user2放入Session中。
// 保存到Session中 @SessionAttributes("user") @Controller @RequestMapping("world") public class HelloWorld { @RequestMapping("/testSession") public String testSession(Map<String,Object> map){ User user = new User(); user.setUsername("zhangsan"); user.setUserpass("123"); user.setAge(20); map.put("user", user); return "hello"; } }
-
-
@SessionAttributes只能用来修饰类。
-
-
@ModelAttribute:方法形参标记该注解后,形参对象就会放到模型中。
-
在方法定义上定义@ModelAttribute注解:
-
SpringMVC调用方法前,会优先调用方法上标注了@ModelAttributes的方法。
-
将@ModelAttributes中的属性保存到map中,可以在执行表单提交生成对象之前,替换执行方法同名的形参。
@ModelAttribute public void before(Map<String, Object> map,User user) { user.setName("123"); user.setPass("123456); map.put("userInfo", user); } @RequestMapping(value="/testModelAttribute") public String testModelAttribute(User user) { student.setName("456"); System.out.println(user); return "success"; }
### 自定义视图
-
-
// 添加一个自定义视图,实现View接口。
@Component //把视图放到IOC容器里面 ,这里视图的名字就是helloView
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.getWriter().println("hello view current time : " + new Date());
}
}
<!-- 通过BeanNameViewResolver定义名称视图解析器。 -->
<!-- BeanNameViewResolver 解析器:使用视图的名字来解析视图 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<!-- order值越小优先级越高 -->
<!-- InternalResourceViewResolver的order值是inter的最大值,所以一般来说都是最后调用的 -->
<property name="order" value="100" />
</bean>
<!-- 在Spring 配置文件中将自定义视图的包添加到自动扫描路径中。 -->
<context:component-scan base-package="com.znsd.springmvc.view" />
@RequestMapping(value="/testCustomView",method=RequestMethod.GET)
public ModelAndView testCustomView() {
return new ModelAndView(new HelloView());
}
6. 关于重定向与转发
-
一般情况下,控制器返回字符串类型的值会被当成逻辑视图名进行处理。
-
如果返回字符串中带有forward:或者redirect:前缀时,SpringMVC会将其进行特殊处理。将forward:和redirect:作为指示符,其后面字符串作为url来处理。
// 当使用转发与重定向时 springmvc不会使用视图解析配置前后缀不会添加,转发可以访问WEB-INF下文件,重定向不能 @RequestMapping("forward") public String testForward() { return "forward:/success.jsp"; // 会完成一个到 success.jsp的转发操作。 } @RequestMapping("redirect") public String testRedirect() { return "redirect:/success.jsp"; // 会完成一个到 success.jsp的重定向操作。 }
7. REST的描述
- 用URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作
- REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口)
- Server提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。“资源”是REST架构或者说整个网络处理的核心。例如:web_service/studentInfo----获取学生信息
- 用HTTP协议里的动词来实现资源的添加,修改,删除等操作。即通过HTTP动词来实现资源的状态扭转
- GET 获取资源/POST 新建资源/PUT 更新资源/DELETE 删除资源
- Server和Client之间传递某资源的一个表现形式,比如用JSON,XML传输文本,或者用JPG,WebP传输图片等。当然还可以压缩HTTP传输时的数据
- 用 HTTP Status Code传递Server的状态信息。比如最常用的 200 表示成功,500 表示Server内部错误等
8. REST的限制与优点
- 客户-服务器(Client-Server)客户端服务器分离 ,
- 提高用户界面的便携性(操作简单)
- 通过简化服务器提高可伸缩性(高性能,低成本)
- 允许组件分别优化(可以让服务端和客户端分别进行改进和优化)
- 无状态(Stateless):客户端的每个请求要包含服务器所需要的所有信息
- 提高可见性(可以单独考虑每个请求)
- 提高了可靠性(更容易从局部故障中修复)
- 提高可扩展性(降低了服务器资源使用)
- 缓存(Cachable)
- 减少交互次数,交互的平均延迟
- 分层系统(Layered System)
- 系统组件不需要知道与他交流组件之外的事情。封装服务,引入中间层,限制了系统的复杂性,提高可扩展性
- 统一接口(Uniform Interface)
- 提高交互的可见性,鼓励单独改善组件
- 支持按需代码(Code-On-Demand 可选)
- 提高可扩展性
9. HTTP请求的四种状态
- GET:获取资源
- POST:新建资源
- PUT:更新资源
- DELETE:删除资源
10. 数据转换器
-
自定义数据转换器
@Component public class MyConverter implements Converter<String, User> { @Override public Student convert(String source) {//前台传过来一串字符串,通过split分割成一个String数组 String [] str = source.split("-"); User user = new User(); user.setName(str[0]); user.setPass(str[1]); return user; } }
-
将自定义的数据转换器放入SpringMvc提供的转换器中
<!-- FormattingConversionServiceFactoryBean 包含了 ConversionServiceFactoryBean ,既可以数据转换也可以数据格式化 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <ref bean="myConverter" /> </set> </property> </bean>
-
将转换器注册到annotation-driven中
<!-- 该配置为springmvc基础配置,很多功能需要该注解来协调,建议配置文件配完后加入该注解 --> <mvc:annotation-driven conversion-service="conversionService" />
-
创建jsp
<a href="handler/testConverter.action?studentInfo=3-第十三-?">testConverter</a>
-
创建测试方法
@RequestMapping(value="/testConverter",method=RequestMethod.GET) public ModelAndView testConverter(@RequestParam("studentInfo") Student student) { System.out.println(student); return new ModelAndView("success"); }
11. 数据校验
注意:springMvc是没有校验的,它使用的校验是Hibernate框架的
-
导入依赖
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.13.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.validation/validation-api --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging --> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.3.2.Final</version> </dependency> </dependencies>
- 在相应字段添加校验注解
@Email private String email;
注解 说明 @Null 必须为null @NotNull 必须不为null @AssertTrue 必须为true @AssertFalse 必须为false @Min(value) 必须为一个数字,其值必须大于等于指定的最小值 @Max(value) 必须为一个数字,其值必须小于等于指定的最小值 @DecimalMin(value) 必须为一个数字,其值必须大于等于指定的最小值 @DecimalMax(value) 必须为一个数字,其值必须小于等于指定的最小值 @Size(max,min) 元素的大小必须在指定范围内 @Digits(int,fraction) 必须是一个数字,其值必须在可接受范围内 @Past 必须是一个过去的日期 @Future 必须是一个将来的日期 @Pattern(value) 其值必须符合指定的正则表达式 hibernate Validator扩展注解
- Hibernate Validator是JSR3.0的一个扩展组件,除支持所有标准的效验注解外,它还支持以下扩展注解
注解 说明 @Email 被修饰的元素必须是电子邮件 @Length 被修饰的元素长度必须在指定的范围内 @NotEmpty 被修饰的元素必须非空 @Range 被修饰的元素必须在合适的范围内 - 编写测试方法
@RequestMapping(value="/testFormat",method=RequestMethod.POST) public String testFormat(@Valid User user, BindingResult result,Map<String, Object> map) { if (result.getErrorCount() > 0) { for (FieldError error : result.getFieldErrors()) { System.out.println("------>"+error.getDefaultMessage()); map.put("errors", result.getFieldErrors()); } } return "login"; }
12. 基于Accept-Language实现国际化
-
编写properties
i18n_zh_CN.properties
resource.name=\u5148\u751F resource.msg=\u4F60\u597D
i18n_en_US.properties
resource.name=先生 resource.msg=你好
- 配置bean
<!-- 国际化 springmvc会自动扫描id为messageSource的bean 然后把该bean的配置介入 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n" /> </bean>
- 创建视图并且导入<%@ taglib uri=“http://java.sun.com/jsp/jstl/fmt” prefix=“fmt”%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test</title> </head> <body> <fmt:message key="resource.describe" /> <fmt:message key="resource.oneself" /> </body> </html>
是跟据当前地区转换页面可以设置浏览器语言查看出效果
13. 基于HttpSession实现国际化(多种手动语言切换)
-
编写properties
i18n_zh_CN.properties
resource.name=\u5148\u751F resource.msg=\u4F60\u597D
i18n_en_US.properties
resource.name=先生 resource.msg=你好
- 配置bean
<!-- 国际化 springmvc会自动扫描id为messageSource的bean 然后把该bean的配置介入 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n" /> </bean> <!-- 自定义国际化 --> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" > <property name="defaultLocale" value="zh_CN" /> <!-- 默认为中文 --> </bean> <mvc:interceptors> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <!-- 需放在拦截器中 --> </mvc:interceptors>
- 创建视图并且导入<%@ taglib uri=“http://java.sun.com/jsp/jstl/fmt” prefix=“fmt”%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test</title> </head> <body> <fmt:message key="resource.describe" /> <fmt:message key="resource.oneself" /> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <!-- start 使用message 标签配置需要显示的国际化文本, locale 对应国际化文件中对应的键的名称 --> <a href="hello.action?locale=zh_CN">Chinese</a> <a href="hello.action?locale=en_US">English</a> </body> </html>
14. 拦截器
-
bean实现拦截器
package com.znsd.springmvc.expand; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class MyInterceptor implements HandlerInterceptor { /** * 进入目标方法之前调用 * 返回true:则继续调用后续的拦截器和目标方法 * 返回false:则不会调用后续的拦截器和目标方法 * 使用场景:权限控制、日志处理、事务... */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor.preHandle()"); return true; } /** * 调用目标方法之后,在渲染页面之前调用 * 使用场景: * 1.需要改变request对象中的值 * 2.需要修改modelAndView中的值 * 3.修改转向的视图 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor.postHandle()"); } /** * 渲染页面完成之后调用 * 使用场景:做一些销毁工作 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor.afterCompletion()"); } }
- 自定义拦截器
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/handler/testInterceptor.action"/> <bean class="com.znsd.springmvc.expand.MyInterceptor" /> </mvc:interceptor> </mvc:interceptors>
15. 文件的上传与下载
- jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="handler/fileupload.action" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="上传" />
</form>
</body>
</html>
- handler
package com.znsd.springmvc.handler;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.ServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("/handler")
public class DemoHandler {
@RequestMapping("/fileupload")
public String fileupload(ServletRequest request, @RequestParam("file") MultipartFile file, Model model)
throws IOException {
if (!file.isEmpty()) {
String imageurl = saveFile(request, file);
model.addAttribute("imageurl", imageurl);
} else {
model.addAttribute("message", "请选择要上传的文件");
}
return "success";
}
// 下载
@RequestMapping("/downFile")
public ResponseEntity<byte[]> testdownFile(HttpSession session) throws IOException {
ServletContext servletContext = session.getServletContext();
InputStream in = servletContext.getResourceAsStream("downloads/down.txt");
byte[] bytes = FileCopyUtils.copyToByteArray(in);
HttpHeaders header = new HttpHeaders();
header.add("Content-Disposition", "attachment;filename=down.txt");
ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(bytes, header, HttpStatus.OK);
return entity;
}
private String saveFile(ServletRequest request, MultipartFile file) throws IOException {
// 获取文件的上传路径
String uploadPath = request.getServletContext().getRealPath("uploads");
System.out.println(uploadPath);
File uploadPathFile = new File(uploadPath);
if (!uploadPathFile.exists()) {
uploadPathFile.mkdirs();
}
// 获取文件名称
String filename = file.getOriginalFilename();
// 截取文件后缀
String fileext = filename.substring(filename.lastIndexOf("."));
// 生成新的随机文件名称
String newfileName = UUID.randomUUID() + fileext;
// 文件保存路径
File savePath = new File(uploadPath + "/" + newfileName);
// 上传文件
file.transferTo(savePath);
return "uploads/" + newfileName;
}
}
16. 异常的处理方式
-
配置xml
<!-- 配置使用SimpleMappingExceptionResolver来映射异常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 给异常命名一个别名 --> <property name="exceptionAttribute" value="ex"></property> <property name="exceptionMappings"> <props> <!-- 一定要异常的全类名。 表示出现异常,就跳转到error.jsp视图 --> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean>
- @ExceptionHandler注解实现异常处理异常类
/** * 全局异常处理类,在项目中推荐使用全局异常处理类去处理所有异常信息 * @author Administrator */ @ControllerAdvice public class ExceptionHandlerAdvice { /** * 在项目总如果没有对异常有页面要求,那么一个异常页面就够了 * 有些项目需要对每一类型的异常都有对象异常页面,比如前台的异常处理、后台异常处理 * @param request * @param response * @param handler * @param ex * @return */ @ExceptionHandler(value = { NullPointerException.class, IndexOutOfBoundsException.class }) public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 如果要将异常传递到视图中(jsp页面),必须使用ModelAndView来进行数据传递 // 不能使用Map形参的方式,否则会报错 System.out.println("ExceptionHandlerAdvice.resolveException()"); Map<String, Object> map = new HashMap<String, Object>(); map.put("ex", ex); ModelAndView mv = new ModelAndView("error", map); return mv; } }
- HandlerExceptionResolver 接口自定义异常处理器
@Component // 将自定义异常类装载到spring容器中 public class CustomeException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Map<String, Object> map = new HashMap<String, Object>(); if (ex instanceof NullPointerException) { map.put("ex", ex); return new ModelAndView("nullPointer", map); // 指定异常对应的视图页面 } if (ex instanceof IndexOutOfBoundsException) { return new ModelAndView("indexOutOf", map); // 指定异常对应的视图页面 } return new ModelAndView("error", map); } }