SpringMVC总结
Posted lyang-a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC总结相关的知识,希望对你有一定的参考价值。
SpringMVC
??Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单。这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中。
??Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。
两个核心:
??处理器映射:选择使用哪个控制器来处理请求.
??视图解析器:选择结果应该如何渲染.
Servlet有哪些功能:
??1. 根据URL 找到Servlet : 解析请求 -----> 找到对应的Servlet
??2. 处理请求 : 获取请求的头信息 获取请求的数据
??3. 响应 : JSP html JSON Servlet:
????1. 将JSP内容,根据格式渲染HTML页面
????2. 将HTML内容,直接渲染成HTML页面
????3. JSON数据解析 : 字符串 resp.setContentType ("text/json;charset=UTF-8") :封装了JSON对象 javascript对象
????4. Servlet解析,调用
??????解析:解析
??????渲染:告诉浏览器 数据格式
?????Servlet :
??????1.解析URL
??????2.处理请求
??????3.处理数据
??????4.渲染视图
??尽可能职能是单一的,但是此时Servlet自身职能相对较多. 地址 各种if
??其二,本身Servlet 每个只能处理一个请求 。Service,当请求多时,需要定义多个Servlet
??对象多,代码复用性降低,性能也会降低。
基于Servlet可能存在的问题:
??Servlet调用Service:AService??BService : 业务处理.
??Spring对Servlet进行了封装:SpringMVC,这个框架只充当控制层.
SpringMVC原理图
springMVC架构流程:
? 1. 用户发送请求到前端控制器DispatcherServlet
? 2. DispatcherServlet 收到请求调用 HanderMapping 处理器映射器
? 3. 处理器映射器根据请求 URL 找到具体的处理器,生成处理器对象及处理器拦截器(若有则生成)一并返回给 DispatcherServlet
? 4. DispatcherServlet 通过 HandlerAdapter 处理器适配器调用处理器
? 5. 执行处理器 Controller (也叫后端控制器)
? 6. Controller 执行完成后返回 ModeAndView
? 7. HandlerAdapter 将 controller 执行结果 ModeAndView 返回给 DispatcherServlet
? 8. DispatcherServlet 将 ModeAndView 传给 ViewReslover 视图解析器
? 9. ViewReslover 解析后返回具体 View
-
DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)
-
DispatcherServlet 响应用户
springmvc 的三大组件:
??处理器映射器(HanderMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewReslover)
springMVC流程原理:
??客户端(浏览器)发送请求到DispatcherServlet(调度器),DispatcherServlet(调度器)收到请求后,根据请求调用HandlerMapping(处理器映射器),HandlerMapping(处理器映射器)根据请求的URL找到具体的处理器,处理器生成处理器对象返回给DispatcherServlet(调度器),DispatcherServlet(调度器)通过HandlerAdapter(处理器适配器)调用Handler(处理器),Handler(处理器)处理相应的Service(业务层)业务逻辑,Handler(处理器)处理完成后找到ModelAndView(模型视图处理器)对象(Model是返回的数据对象(解析数据),View是一个逻辑上的View)传给ViewResolver(视图映射器)查找对应的View(逻辑视图)进行视图渲染(实际视图),DispatcherServlet(调度器)把返回的Model传给View,通过View响应给客户端(浏览器)。
1. DispatcherServlet接口:
??Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。
2. HandlerMapping接口:
??能够完成客户请求到Controller映射。
3. Controller接口:
??需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。
??Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。
??从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。
4. ViewResolver接口:
??Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。
SpringMVC使用
- 下载相关jar包,由于SpringMVC是Spring提供的框架,Spring的jar中,,包含SpringMVC相关jar包
spring-web-4.3.24.RELEASE.jar
spring-webmvc-4.3.24.RELEASE.jar
- 配置DispatcherServlet,让这个Servlet处理所有请求
<!-- 配置DispatcherServlet 调度器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置SpringMVC的映射器需要的文件 -->
<init-param>
<!-- 处理器映射器文件属性名 -->
<param-name>contextConfigLocation</param-name>
<!-- 具体的处理器文件 -->
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 配置启动时机 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
- 定义处理器Handler
方式一:
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
public class Controller01 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("name", "Hello Spring MVC");
//跳转到 info.jsp
request.getRequestDispatcher("info.jsp").forward(request, response);
}
}
方式二:
package com.sxt.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class Controller02 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
// 设置model数据
modelAndView.addObject("name", "Hello Spring MVC");
// 设置视图地址
modelAndView.setViewName("info.jsp");
return modelAndView;
}
}
- 配置处理器,让调度器通过处理器映射器找到处理器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 处理器的配置文件 -->
<!-- 注册处理器 -->
<bean name="/controller01.do" class="com.sxt.controller.Controller01"></bean>
<bean name="/controller02.do" class="com.sxt.controller.Controller02"></bean>
<!-- 扫描注解 -->
<context:component-scan base-package="com.sxt"></context:component-scan>
<!-- 让 mvc 注解生效 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
- 请求
http://127.0.0.1:8080/springmvc/controller01.do
注解版
注解方式:
<!-- 扫描注解 -->
<context:component-scan base-package="com.sxt"></context:component-scan>
<!-- 让 mvc 注解生效 -->
<mvc:annotation-driven></mvc:annotation-driven>
定义处理器
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Controller03 {
@RequestMapping("/hello.do")
public void hello(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "Hello Spring MVC");
req.getRequestDispatcher("info.jsp").forward(req, resp);
}
@RequestMapping("/hello1.do")
public ModelAndView hello1() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name", "Hello Spring MVC");
modelAndView.setViewName("info.jsp");
return modelAndView;
}
@RequestMapping("/hello2.do")
public String hello2(Model model) {
model.addAttribute("name", "Hello Spring MVC");
return "info.jsp";
}
}
SpringMVC初始化流程:
DispatcherServlet : --- init
DispatcherServlet 中没有init 方法
|--- DispatcherServlet的父类:FrameworkServlet
|--- FrameworkServlet 没有init方法 : FrameworkServlet的父类
|--- HttpServletBean 中init方法 : initServletBean () :
|--- FrameworkServlet.initServletBean()
|--- FrameworkServlet:initWebApplicationContext()
|---FrameworkServlet.createWebApplicationContext() : 加载 springmvc的配置文件,且初始化handler对象
|--- FrameworkServlet.onRefresh() : DispatcherServlet.onRefresh(WebApplicationContext)
|--- DispatcherServlet.initStrategies(ApplicationContext) : 初始化DispatcherServlet 从DispatcherServlet.properties 进行默认的配置
@RequestMapping
@GetMapping/@PostMapping
value/path : 映射地址:
??该注解可以使用在类上面,也可以使用在方法上面.映射地址,是按照类上面该注解的value/path属性值与方法上面value/path属性进行拼接,组成URL路径.
method : 支持的请求方式.若不写,则默认GET和POST请求都支持.
在Spring新的版本中,使用 @PostMapping代理method为post,@GetMapping代替了method为get
params:限定请求中必须含有的参数
headers:限定请求中必须包含的请求头信息
consumes:限定请求的数据格式
produces:限定返回的数据格式
数据绑定-获取请求参数
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="user/add.do">
<p>用户名:<input type="text" name="userName1"/></p>
<p>密码:<input type="text" name="password"/></p>
<p>年龄:<input type="text" name="age"/></p>
<input type="submit" value="提交">
</form>
<hr>
<form action="user/add2.do">
<p>用户名:<input type="text" name="userName"/></p>
<p>密码:<input type="text" name="password"/></p>
<p>年龄:<input type="text" name="age"/></p>
<input type="submit" value="提交">
</form>
<hr>
<form action="user/add3.do">
<p>用户名:<input type="text" name="userName1"/></p>
<p>密码:<input type="text" name="password1"/></p>
<p>年龄:<input type="text" name="age1"/></p>
<input type="submit" value="提交">
</form>
<hr>
<form action="user/add4.do">
<p>用户名:<input type="text" name="userName1"/></p>
<p>密码:<input type="text" name="password1"/></p>
<p>年龄:<input type="text" name="age1"/></p>
<input type="submit" value="提交">
</form>
<h2>map</h2>
<form action="user/add5.do">
<p>用户名:<input type="text" name="userName1"/></p>
<p>密码:<input type="text" name="password1"/></p>
<p>年龄:<input type="text" name="age1"/></p>
<input type="submit" value="提交">
</form>
<h2>list</h2>
<form action="user/add6.do">
<p>爱好:
<input type="checkbox" name="like" value="篮球"/>
<input type="checkbox" name="like" value="足球"/>
<input type="checkbox" name="like" value="羽毛球"/>
<input type="checkbox" name="like" value="乒乓球"/>
</p>
<input type="submit" value="提交">
</form>
<h2>格式化</h2>
<form action="user/add7.do">
<p>用户名:<input type="text" name="userName"/></p>
<p>密码:<input type="text" name="password"/></p>
<p>生日:<input type="text" name="age"/></p>
<input type="submit" value="提交">
</form>
<h2>格式化</h2>
<form action="user/add8.do">
<p>用户名:<input type="text" name="userName"/></p>
<p>密码:<input type="text" name="password"/></p>
<p>生日:<input type="text" name="age"/></p>
<input type="submit" value="提交">
</form>
</body>
</html>
package com.sxt.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import com.sun.xml.internal.ws.client.RequestContext;
import com.sxt.pojo.User;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 简单的数据类型绑定
* 在SpringMVC中,获取请求参数参数,只需要方法中形式参数的名称与请求的数据的name属性值一致,就可以自动的绑定相关参数 且简单数据类型可以自动进行数据转换.
* @param userName
* @param password
* @param age
* @return: void
*/
@RequestMapping("/add.do")
public void add(String userName,String password,Integer age) {
System.out.println(userName);
System.out.println(password);
System.out.println(age);
}
/**
* 获取请求的参数,且将其封装到对象中
* 1. 创建对象
* 2.属性注入 根据set方法进行属性注入
* @param user
* @return: void
*/
@RequestMapping("/add2.do")
public void add(User user) {
System.out.println(user);
}
/**
* 请求参数名称和形式参数名称不一致时 可以使用@RequestParam 别名
* @param userName
* @param password
* @param age
* @return: void
*/
@RequestMapping("/add3.do")
public void add3(@RequestParam("userName1")String userName,@RequestParam("password1")String password,@RequestParam("age1")Integer age) {
System.out.println(userName);
System.out.println(password);
System.out.println(age);
}
/**
* name/value 参数别名
* required : 是否是必须传递的参数 默认是true
* defaultValue : 当这个参数没有的时候的默认值
* @param userName
* @param password
* @param age
* @return: void
*/
@RequestMapping("/add4.do")
public void add4(@RequestParam(name="userName1",required = false,defaultValue = "我是默认值")String userName,@RequestParam("password1")String password,@RequestParam("age1")Integer age) {
System.out.println(userName);
System.out.println(password);
System.out.println(age);
}
/**
* 使用Map接收请求参数
* @param map
* @return: void
*/
@RequestMapping("/add5.do")
public void add4(@RequestParam Map<String,Object> map) {
System.out.println(map);
}
/**
* 接收数组格式的参数
* @RequestParam("参数名称")
* @param like
* @return: void
*/
@RequestMapping("/add6.do")
public void add6(@RequestParam("like")List<String> like) {
System.out.println(like);
}
/**
* 将字符串格式化 时间对象
* @param userName
* @param password
* @param age
* @return: void
*/
@RequestMapping("/add7.do")
public void add6(String userName,String password,@DateTimeFormat(pattern = "yyyy-MM-dd")Date age) {
System.out.println(userName);
System.out.println(password);
System.out.println(age);
}
@RequestMapping("/add8.do")
public void add6(User user) {
System.out.println(user);
}
/**
* 内置对象的注入
* @return: void
*/
@RequestMapping("/httpObj.do")
public void httpObj(HttpServletRequest req,HttpServletResponse resp,HttpSession session,Model mode) {
System.out.println(mode);
System.out.println(req);
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes req1 = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
System.out.println(req1.getRequest().getServletContext());
System.out.println(requestAttributes);
System.out.println(resp);
System.out.println(session);
}
}
WebUtil
package com.sxt.util;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public class WebUtil {
/**
* 获取当前请求对象
* @return
* @return: HttpServletRequest
*/
public HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
return servletRequestAttributes.getRequest();
}
/**
* 获取当前Session
* @return
* @return: HttpSession
*/
public HttpSession getSession() {
return getRequest().getSession();
}
/**
* 获取当前ServletContext 容器
* 当项目直接启动时,可能需要向ServletContext 设置全局参数
* 如果直接使用 request.getServletContext() 会空指针异常
* 所以需要根据WebApplicationContext 获取
* @return
* @return: ServletContext
*/
public ServletContext ServletContext() {
HttpServletRequest request = getRequest();
// 若当前请求存在 则直接从当前请求中获取ServletContext
if(request != null) {
return request.getServletContext();
}else {
// 若不存在则根据WebApplicationContext 获取当前ServletContext
return ContextLoader.getCurrentWebApplicationContext().getServletContext();
}
}
}
编码过滤器
<filter>
<filter-name>charset</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>charset</filter-name>
<!-- 此时配置 只过滤 springmvc请求 -->
<servlet-name>springmvc</servlet-name>
</filter-mapping>
关于SpringMVC跳转
?SpringMVC中,默认是使用内部转发.
?如果需要使用重定向:**redirect:**地址
package com.sxt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* springmvc 默认是使用内部转发
* @return
* @return: String
*/
@RequestMapping("list.do")
public String list() {
return "/list.jsp";
}
/**
* 若想使用 重定向 :
* redirect: 地址
* @return
* @return: String
*/
@RequestMapping("list2.do")
public String list2() {
return "redirect:/list.jsp";
}
@RequestMapping("list3.do")
public ModelAndView list3() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/list.jsp");
return modelAndView;
}
@RequestMapping("list4.do")
public ModelAndView list4() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:/list.jsp");
return modelAndView;
}
}
配置视图解析器
<!-- 配置视图解析器 -->
<!--
配置 SpringMVC视图解析器时
其前后缀 只对 内部转发生效
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图解析器前缀 -->
<property name="prefix" value="/WEB-INF/jsp"></property>
<!-- 配置视图解析器后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
springmvc返回json数据
package com.sxt.controller;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* @Title: list
* @author: Mr.T
* @date: 2019年11月26日 下午2:35:12
* @Description: 在springmvc中,方法返回的字符串,默认会当做路径处理.springmvc 默认会解析该路径,
* 因为springmvc 提供了注解 @ResponseBody, 表示该方法返回的是字符,阻止springmvc 当做路径处理
* 默认是用 @ResponseBody 时 中文乱码, 需要设置编码格式 数据格式
* @return
* @return: String
* @throws JSONException
*/
@RequestMapping(value ="/list.do",produces = "text/json;charset=UTF-8" )
@ResponseBody
public String list() throws JSONException {
System.out.println("==============");
String msg = "{‘name‘:‘张三‘,‘age‘:18}";
JSONObject json = new JSONObject();
json.put("name", "张三");
json.put("age", 18);
System.out.println(json.toString());
msg = json.toString();
return msg;
}
}
@RestController
??RestController 继承了Controller和ResponseBody,当controller类被RestController修饰时,其下面所有的方法,返回的结果,都会当做字符串输出浏览器. 等价于,在一个类上面定义Controller和ResponseBody.
??一般若用于接口开发,都使用RestController ,若controller不需要进行页面跳转,则可以直接使用RestController。否则(若controller需要页面跳转),只能使用@Controller。
@ResponseBody
??@ResponseBody: 可以作用于方法上和类上面,若作用于方法上,则该方法的返回值,当做字符串输出给客户端.若作用于类上面,则该类中的所有方法的返回值,当做字符串输出给客户端.
springmvc返回json对象
??在springmvc中,默认是使用jackson进行数据解析,进行返回.若返回的结果是一个json对象.可以直接返回.
但是需要导入jackson的相关jar包.
jackson-annotations-2.9.9.jar
jackson-core-2.9.9.jar
jackson-databind-2.9.9.jar
@RequestMapping("/list.do")
public Object list() throws JSONException {
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", "韩梅梅");
return map;
}
@RequestMapping("/list3.do")
public Object list3() throws JSONException {
User user = new User(1, "韩梅梅", 18);
return user;
}
文件上传和下载
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="file/upload.do" method="post" enctype="multipart/form-data">
文本:<input type="text" name="userName" /><br>
文件:<input type="file" name="fileName" /><br>
<input type="submit" value="提交" />
</form>
</body>
</html>
spring-mvc.xml
<!-- 配置解析二进制数据解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
文件上传
package com.lyang.controller;
import java.io.File;
import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("/file")
public class FileUploadController {
@RequestMapping("/upload.do")
public void upload(@RequestParam("fileName")MultipartFile file,String userName) throws IOException {
// 获取提交的 input name的属性值
System.out.println(file.getName());
// 获取文件真实名称
System.out.println(file.getOriginalFilename());
// 获取数据的格式
System.out.println(file.getContentType());
// 获取文件的输入流
System.out.println(file.getInputStream());
// 获取文件的大小(字节)
System.out.println(file.getSize());
// 文件进行保存
file.transferTo(new File("D:\\uploadTest.jpg"));
}
}
文件下载
package com.lyang.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/file")
public class FileDownloadController {
@RequestMapping("/download.do")
public void downLoad(HttpServletResponse resp) {
// 找到需要被下载的文件
File file = new File("D:\\download.jpg");
// 创建输入流 读取文件
FileInputStream fis = null;
// 输出流
OutputStream ops = null;
// 设置数据格式为二进制输数据流,让浏览器不要进行解析
resp.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
try {
// 设置响应头信息 告诉浏览器 文件的相关信息 文件的名称 汉字时 容易出现乱码不识别问题 需要 编码
String fileName = URLEncoder.encode("下载.jpg", "UTF-8");
resp.addHeader("Content-Disposition", "form-data;name="img";filename="" + fileName + """);
// 输入流绑定需要读取的文件!
fis = new FileInputStream(file);
// 获取与客户端绑定的数据流
ops = resp.getOutputStream();
byte[] data = new byte[1024];
int len = -1;
while ((len = fis.read(data)) != -1) {
// 向客户端输出
ops.write(data, 0, len);
ops.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fis.close();
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@RequestMapping("download2.do")
public ResponseEntity<byte[]> downLoad2(){
// 找到需要被下载的文件
File file = new File("D:\\download.jpg");
// 存储文件数据的容器
byte[] fileByte = null;
ResponseEntity<byte[]> entity = null;
try {
// 将文件一次性读到内存中
fileByte = FileUtils.readFileToByteArray(file);
// 创建响应头
HttpHeaders headers = new HttpHeaders();
// 设置MediaType 为二进制 避免浏览器解析
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 设置文件的名称 如果名称是中文,需要进行转码
String fileName = URLEncoder.encode("下载.jpg", "UTF-8");
headers.setContentDispositionFormData("filename", fileName);
entity = new ResponseEntity<byte[]>(fileByte, headers, HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
}
return entity;
}
}
总结
springMVC原理:
-
浏览器发送请求,DispatcherServlet(调度器)
-
DispatcherServlet(调度器)需要要找处理器,找到处理器映射器(HandlerMapping).
-
处理器映射器(HandlerMapping)找到对应的处理器: Handler
-
处理器: Handler,处理器请求 Service.
-
处理器处理完后,找到ModelAndView处理器.
-
Model解析数据
-
视图映射器,查找对应的视图,View渲染视图.
-
将视图返回给浏览器
SpringMVC三种方式:
-
实现HttpRequestHandler接口
-
Controller接口
-
使用注解 :
SpringMVC的数据绑定:
?@RequestParam : 请求参数的注解
? value /name : 参数名称
? required : 必传 : true false 可选参数
? defaultValue : 参数没有值的时候的默认值
??1. web请求的参数,要与方法中的参数名保持一致。若不一致可以使用RequestParam别名
??2. RequestParam 默认参数必传,设置属性是否必传,设置默认值
??3. 使用Map 和 List 接收数据
??4. SpringMVC 默认是:HttpServletRequest HttpServletResponse HttpSession Model 可以注入的
??5. Spring 提供的工具类 获取到当前 HttpServletRequest 对象 默认的Spring的web容器,是与ServlectContext 绑定的关系,可以根据 Spring 的容器找到 ServlectContext 。
在springMVC中,可以自动注入web对象:
HttpServletRequest
HttpServletResponse
HttpSession
Model
编码过滤器:
??SpringMVC 提供内置的编码过滤器 只需要配置编码即可
跳转:
??SpringMVC 默认是内部转发, 若想使用重定向: redirect:前缀
在SpringMVC中,/表示项目根目录.
配置前缀和后缀:
??配置视图解析器:InternalResourceViewResolver
????prefix 前缀
????suffix 后缀
注意点: 视图解析器的前后缀 对 重定向不生效
参数传递问题:
? springmvc 推荐使用 Model 优先级高于Request
注意:
? 在springmvc中,默认配置是支持所有的映射器和适配器,一旦指定了适配器和映射器,其他的就不生效了。
以上是关于SpringMVC总结的主要内容,如果未能解决你的问题,请参考以下文章