SpringMVC
一、SpringMVC概述
1. 三层架构
服务器端开发程序主要由两种形式构成。一种是基于客户端的C/S架构,另一种是基于浏览器的B/S架构Java语言主要用于开发B/S架构,其中的B/S架构又分为了三层架构。
表现层:WEB层,用于和客户端进行数据交互。表现层一般会采用MVC的设计模型。业务层:处理具体的业务功能的持久层:用于进行数据存储,操作数据库的
2. MVC模型
MVC全称为Model、View、Controller 模型视图控制器,每个部分功能不同Model(模型):数据模型,JavaBean的类,用于进行数据的封装View(视图):指JSP、Html等用于展示数据给用户Controller(控制器):用于接受用于的请求,整个流程的控制器。进行数据校验等。
二、Spring的简单应用
1. SpringMVC实例
进行版本锁定
<!-- 设置配置信息 -->
<properties>
<!-- 设置编码格式 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 设置源码jdk版本 -->
<maven.compiler.source>1.8</maven.compiler.source>
<!-- 设置生成后的jdk版本 -->
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 针对Spring的相关jar包进行版本锁定 -->
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
导入相关坐标
<dependencies>
<!-- 导入Spring相关坐标 -->
<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>
<!-- 导入WEB相关jar包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
在web.xml中对Servlet进行设置
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- SpringMVC的核心控制器 -->
<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>
<!-- 配置servlet启动时就加载对象 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在SpringMVC的配置文件中对Spring和SpringMVC进行设置
引入SpringMVC相关配置的约束头文件 <?xml version="1.0" encoding="UTF-8"?>
<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">
</beans>
对SpringMVC的配置文件进行操作 <?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 设置spring自动扫描的包 -->
<context:component-scan base-package="com.hsh.study" />
<!-- 配置视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 目标页面位于的位置 -->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!-- 目标页面的后缀名 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置SpringMVC开启注解MVC的支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans> 编写index.jsp和Controller控制类
index.jsp的编写 <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>开始的地方</h1>
<a href="${pageContext.request.contextPath}/hello">SpringMVC的使用</a>
</body>
</html>
Controller控制类的编写 @Controller("accountController")
public class AccountController {
@RequestMapping("/hello")
public String sayHello(){
System.out.println("Hello SpringMVC!");
return "success";
}
} 编写跳转成功页面(写在WEB-INF下的pages目录下)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎来到成功界面</title>
</head>
<body>
<h1>欢迎来到成功界面!!!</h1>
</body>
</html>
2. SpringMVC运行过程
当tomcat服务器运行时,因为在web.xml中配置的Servlet中选择了<load-on-startup>标签,所以在tomcat服务器启动时便创建了DispatcherServlet对象,同时执行servlet中的<init-param>加载Spring的springmvc.xml配置文件由于Spring的配置文件中开启了注解扫描,那么Spring将为写的类AccountController创建对象从index.jsp中发出请求后,请求首先到达DispatcherServlet核心控制器,根据配置的@RequestMapping注解找到执行的具体方法根据执行方法的返回值,同时依据Spring配置文件中配置的视图解析器,会去指定目录下寻找指定名称的.jsp文件TomCat拿到结果并返回给用户。
3. SpringMVC中的组件
前端控制器(DispatcherServlet)处理器映射器(HandlerMapping)处理器(Handler)处理器适配器(HandlAdapter)视图解析器(View Resolver)视图(View)
三、请求参数的绑定
1. 请求参数绑定概念
绑定机制
由于表单中提交的数据都是k=v格式的,如:(username=root&password=123),所以SpringMVC的参数绑定过程便是将表单提交的请求参数作为控制器中方法的参数进行绑定的。要求:提交表单的属性值与参数的名称要一致。 支持的数据类型
基本数据类型和字符串类型实体类类型(JavaBean)集合数据类型(List、Map集合等)
2. 基本数据类型和字符串类型
提交表单的属性和参数的名称要要一致区分大小写
3. 实体类型(JavaBean)
提交表单的属性和JavaBean中的属性名称要一致如果一个JavaBean类中包含其他的引用类型,那么表单的属性需要编成:对象.属性 如:user.name
4. 给集合属性封装
JSP页面编写方式:list[0].属性
5. 请求参数中文乱码的解决
在web.xml中配置Spring提供的过滤器类
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置过滤器 -->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
6. 自定义类型转换器
表单提交时任何数据都是字符串类型的,但是Spring框架内部提供了默认进行数据类型转换的方式。Spring同时也可以实现自定义数据的类型转换,实现方式为实现Converter接口
自定义类型转换器 public class StringToDateConverter implements Converter<String, Date> {
/**
* 进行类型转换
* @param source
* @return
*/
@Override
public Date convert(String source) {
// 判断是否为空
if (source == null){
throw new RuntimeException("参数不能为空");
}
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// 解析字符串
Date date = df.parse(source);
return date;
} catch (ParseException e) {
throw new RuntimeException("参数转换异常!");
}
}
}
注册自定义类型转换器,在springmvc.xml配置文件中配置 <!-- 注册自定义类型转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.hsh.study.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!-- 配置SpringMVC开启注解MVC的支持 -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
7. 在控制器中使用原生ServletAPI对象
在控制器方法参数处定义HttpServletRequest和HttpServletResponse对象
四、SpringMVC常用注释
1. @RequestMapping
作用:RequestMapping注解的作用是建立请求Url和处理方法之间的对应关系应用场景:RequestMapping注解可以作用于方法和类上
作用在类上时:一级访问目录作用在方法上时:如果类上没有该注解则为一级目录,否则为二级访问目录在写url路径时可以省略/表示从应用的根目录开始,同时${pageContext.request.contextPath}也可以省略不写,但是路径上不能写/ RequestMapping的属性
path:指定请求路径的urlvalue:value属性和path属性是一样的method:指定方法的请求方式params:指定限制请求参数的条件headers:发送的请求中必须包含的请求头
2. @RequestParam
作用:将请求中的指定名称的参数传递给控制器中的形参赋值(作用于当实体类中的属性名和请求中的属性名不同时)属性:
value:请求参数中的名称required:请求参数中是否必须提供此参数,默认值为true 具体操作:
@RequestMapping("/hello")
public String getForm(@RequestParam(value="username",required=false)String uname){
System.out.println(uname);
return "success";
}
3. @RequestBody
作用:用于获取请求体的内容(get方式无请求体)属性
required:是否必须有请求体,默认值为true 具体操作:
@RequestMapping("/hello")
public String getForm(@RequestBody String body){
System.out.println(body);
return "success";
}
4. @PathVariable
作用:用于绑定url中的占位符的。如url的路径为:/delete/{id} 这之中的{id}就是占位符属性
value:指定url中的占位符名称 3.Restful风格的URL
请求路径一样,根据不同的请求方式去执行后台的不同方法。Restful风格的URL优点:①结构清晰 ②符合标准 ③易于理姐 ④方便扩展 具体操作
@RequestMapping("/hello")
public String getForm(@PathVariable(value="id")String id){
System.out.println(id);
return "success";
}
5. @RequestHeader
作用:获取指定请求头的值属性
value:请求头的名称 具体操作
@RequestMapping("/hello")
public String getForm(@RequestHeader("Accept")String header){
System.out.println(header);
return "success";
}
6. @CookieValue
作用:获取指定Cookie名称的值属性
value:cookie的名称 具体操作
@RequestMapping("/hello")
public String getForm(@CookieValue(value="JSESSIONID")String cookieValue){
System.out.println(cookieValue);
return "success";
}
7. @ModelAttribute
作用
出现在方法上:表示该方法会在控制器方法执行前先执行出现在参数上:获取指定的数据给参数赋值 应用场景
当提交的表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据 具体操作
修饰的方法有返回值 // 作用于方法上时,先执行该方法再执行控制器方法
@ModelAttribute
public User showUser(String name){
User user = new User();
user.setUsername("张三");
user.setAge(12);
user.setMoney(1111);
return user;
}
// 修改用户的操作
@RequestMapping("/updateUser")
public String updateUser(User user){
System.out.println(user);
reutrn "success";
}
修饰的方法无返回值 // 作用于方法上时,先执行该方法再执行控制器方法
@ModelAttribute
public void showUser(String name, Map<String, User> map){
// 模拟从数据库中查询对象
User user = new User();
user.setUsername("李四");
user.setAge(15);
user.setMoney(2222);
// 存入Map集合
map.put("user",user);
}
// 修改用户的操作
@RequestMapping("/updateUser")
public String updateUser(@ModelAttribute(value="user")User user){
System.out.println(user);
reutrn "success";
}
8. @SessionAttribute
作用:用于多次执行控制器方法间的参数共享属性
value:指定存入属性的名称 具体操作
@Controller("helloController")
@RequestMapping("/user")
// 将数据存入Session域对象中
@SessionAttribute(value = {"username", "password", "age"}, types={String.class,Integer.class})
public class HelloController{
// 向session中存入值
@RequestMapping("/save")
public String save(Model model){
System.out.println("向session域中保存数据");
model.setAttribute("username","root");
model.setAttribute("password","123");
model.setAttribute("age",123);
return "success";
}
// 向session中取值
@RequestMapping("/find")
public String find(ModelMap modelMap){
String username = (String) modelMap.get("username");
String password = (String) modelMap.get("password");
Integer age = (Integer) modelMap.get("age");
System.out.println(username + " " + password + " " + age);
return "success";
}
// 清除session中的值
@RequestMapping("/delete")
public String delete(SessionStatus status){
status.setComplete();
return "success";
}
}
五、响应数据和结果视图
1. 返回值分类
字符串
Controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。 // 在springmvc.xml文件中配置视图解析器
<!-- 配置视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 目标页面位于的位置 -->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!-- 目标页面的后缀名 -->
<property name="suffix" value=".jsp"></property>
</bean>
// 字符串返回
@RequestMapping("/hello")
public String sayHello(){
System.out.println("Hello SpringMVC!");
// 指定逻辑视图名,经过视图解析器解析为jsp的物理路径:/WEB-INF/pages/success.jsp
return "success";
} void
当返回值为void时,页面的跳转可以使用原生Servlet中的转发和重定向完成页面的跳转
转发 @RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 使用转发转向页面
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}
重定向 @RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 使用重定向进行跳转
response.sendRedirect( request.getContextPath() + "/Redirect.jsp");
}
直接响应数据 @RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 直接响应数据
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("响应成功!");
return;
} ModelAndView
ModelAndView是SpringMVC中提供的一个对象,该对象可以用控制器方法的返回值。 @RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView(){
ModelAndView mv = new ModelAndView();
// 向request域中添加值
mv.addObject("username","张三");
// 设置跳转的页面
mv.setViewName("success");
return mv;
}
2. 转发和重定向
forward 转发
Controller方法在提供了String类型的返回值后,默认的就是使用请求转发,在返回值中使用:forward: @RequestMapping("/testForward")
public String testForward(){
System.out.println("执行重定向操作!");
return "forward:/WEB-INF/pages/success.jsp";
}
注:如果使用了==forward:== 则路径必须携程实际视图的url,相当于request.getRequestDispatcher(url).forward(request,response);。使用请求转发既可以转发到jsp中,也可以转发到其他控制器中。 Redirect 重定向
Controller方法在提供了String类型的返回值后,在返回值中使用:redirect: @RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("执行重定向操作!");
return "redirect:testForward";
}
注:此语句相当于response.sendRedirect(url)。如果重定向到jsp页面,则jsp的页面必须位于WEB-INF目录下,否则无法找到。
3. ResponseBody响应json数据
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据:json、xml等,并通过Response响应给客户端
首先DispatcherServlet核心控制器会拦截所有的资源,导致了静态资源(html、css、js)都会被拦截,从而无法使用。解决的方法是通过配置springmvc.xml配置文件使得静态资源的访问不进行拦截。
<mvc:resources>标签可以配置不过滤
location:表示webapp目录下的所有文件mapping:表示以/static开头的所有请求路径,如/static/a和/static/b 配置 <!-- 设置静态资源不过滤-->
<!-- 样式 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<!-- 图片 -->
<mvc:resources location="/images/" mapping="/images/**"/>
<!-- javascript -->
<mvc:resources location="/js/" mapping="/js/**"/> 使用@ResponseBody需要使用jackson的jar包
引入jackson的jar包 <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency> 使用ajax请求json时导入JQuery编写前端JS代码和表单
<!------------------------JS代码--------------------------------->
<script src="js/jquery.min.js"></script>
<script>
$(function () {
$("#btn").click(function () {
$.ajax({
type:"post",
url:"account/testJson",
contentType:"application/json;charset=utf-8",
data:'{"name":"张三","money":123.12}',
dataType:"json",
success:function (data) {
alert(data.id);
alert(data.name);
alert(data.money);
}
});
});
});
</script>
<!------------------------HTML代码--------------------------------->
<hr>
<input type="button" id="btn" value="发送Ajax请求得到json响应数据">
<hr>
编写控制器类
@Controller("accountController")
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/testJson")
public @ResponseBody Account testJson(@RequestBody Account account){
System.out.println("执行Json操作!");
System.out.println(account);
account.setId(15);
return account;
}
}
二、SpringMVC实现文件上传
1. 传统的文件上传方式
文件上传的前提
form表单的enctype的取值必须为:multipart/form-data (默认值为application/x-www-form-urlencoded) ==enctype:是表单请求正文的类型==method属性值必须为:post提供文件选择框:<input type="file" /> 文件上传所需jar包
<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>
JSP页面
<form action="user/fileupload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="提交">
</form>
文件上传的控制类
@RequestMapping("/fileupload")
public String fileupload(HttpServletRequest request) throws Exception{
// 获取要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File文件对象
File file = new File(path);
// 判断路径是否存在
if(!file.exists()){
file.mkdirs();
}
// 创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 解析request对象
List<FileItem> list = fileUpload.parseRequest(request);
// 遍历
for (FileItem fileItem : list){
// 判断文件项是否为上传的文件
if(fileItem.isFormField()){
}else{
// 是上传的文件
String filename = fileItem.getName();
// 上传文件
fileItem.write(new File(file, filename));
// 删除临时文件
fileItem.delete();
}
}
return "success";
}
2. SpringMVC上传方式
文件上传所需jar包
<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>
编写控制器类
@RequestMapping("/fileupload2")
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception{
// 获取要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File文件对象
File file = new File(path);
// 判断路径是否存在
if(!file.exists()){
file.mkdirs();
}
// 获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
// 将文件名称唯一化
filename = uuid + "_" + filename;
// 上传文件
upload.transferTo(new File(file,filename));
return "success";
}
编写文件解析器
<!-- 配置文件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/>
</bean>
3. SpringMVC跨服务器方式文件上传
导入开发所需jar包
<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>
编写控制器
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
System.out.println("SpringMVC跨服务器方式的文件上传...");
// 定义图片服务器的请求路径
String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
// 获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
// 把文件的名称唯一化
filename = uuid+"_"+filename;
// 向图片服务器上传文件
// 创建客户端对象
Client client = Client.create();
// 连接图片服务器
WebResource webResource = client.resource(path+filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
4. 上传文件后进行回显
在 springmvc.xml 开启 mvc 注解支持
<!-- 开启springmvc注解支持 -->
<mvc:annotation-driven />
在 springmvc.xml 中配置静态资源不过滤
<mvc:resources location="/img/" mapping="/img/**"/>
<!--我这里文件上传后的目录为 /upload,所以此处不过滤 /upload -->
<mvc:resources location="/upload/" mapping="/upload/**"/>
在文件上传的基础上增加如下代码
@RequestMapping("/fileupload")
public String fileupload(MultipartFile upload, HttpServletRequest request) throws IOException {
String realPath = request.getSession().getServletContext().getRealPath("/upload");
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
filename = uuid + filename;
upload.transferTo(new File(file, filename));
request.getSession().setAttribute("img","/upload/" + filename);
return "success";
}
编写回显到浏览器的页面
<H1>成功</H1>
<img src="${pageContext.request.contextPath}${img}" alt="">
5. SpringMVC 实现下载文件
编写调用下载的界面
<a href="${pageContext.request.contextPath}/test/download?image=cunhua.jpg" >下载此图片</a>
编写文件下载的 Controller
@RequestMapping("/download")
public void download(@RequestParam(name = "image") String image, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 设置响应头
response.setHeader("Content-Disposition", "attachment;filename="+image);
// 获取真实路径
String realPath = request.getSession().getServletContext().getRealPath("/img");
// 读取文件流
FileInputStream is = new FileInputStream(realPath + "/" + image);
//写文件的流
ServletOutputStream os = response.getOutputStream();
//copy
IOUtils.copy(is, os);
//关闭
is.close();
os.close();
}
3. SpringMVC的异常处理
1. 异常处理思路
Controller调用service,service调用dao,异常都是向上抛出,最终由DispathcerServlet找异常处理器进行异常处理。
2. 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 {
/**
* 跳转到具体的错误页面的方法
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
e.printStackTrace();
SysException exception = null;
// 获取到异常对象
if(e instanceof SysException){
exception = (SysException) e;
}else{
exception = new SysException("联系我!");
}
ModelAndView mv = new ModelAndView();
// 存入错误的提示信息
mv.addObject("message",exception.getMessage());
// 跳转的jsp页面
mv.setViewName("error");
return mv;
}
}
配置异常处理器
<!-- 配置异常处理器 -->
<bean id="sysExceptionResolver" class="com.hsh.study.exception.SysExceptionResolver"></bean>
4. SpringMVC的拦截器
1. 概念
SpringMVC的处理器拦截器类类似于Servlet中的过滤器Filter,用于对处理其进行预处理和后处理。
过滤器和拦截器的区别
过滤器是Servlet规范中的一部分,任何Java Web工程都可以使用拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才可以使用过滤器在url-pattern中配置了/*后,可以对所有要访问的资源进行拦截拦截器只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或js都不回进行拦截 自定义拦截器必须实现此接口:HandlerInterceptor
2. 自定义拦截器
创建拦截器并实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor{
/**
* controller方法执行前,进行拦截的方法
* return true放行
* return false拦截
* 可以使用转发或者重定向直接跳转到指定的页面。
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception {
System.out.println("拦截器执行了...");
return true;
}
}
在springmvc中配置拦截器
<!-- 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法进行拦截-->
<mvc:mapping path="/user/*"/>
<!-- 哪些方法不进行拦截
<mvc:exclude-mapping path=""/>
-->
<!-- 注册拦截器对象-->
<bean class="cn.itcast.demo1.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
3. HandlerInterceptor接口中的方法
preHandle方法是controller方法执行前拦截的方法
可以使用request或者response跳转到指定的页面return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。return false不放行,不会执行controller中的方法。 postHandle是controller方法执行后执行的方法,在JSP视图执行前。
可以使用request或者response跳转到指定的页面如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。 postHandle方法是在JSP执行后执行
request或者response不能再跳转页面了