MVC:模型(dao,service) 视图(jsp) 控制(servlet)
职责分析
1. Controller:控制器- 取得表单数据- 调用业务逻辑- 转向指定页面
2. Model:模型- 业务逻辑- 保存数据的状态
3. View:视图- 显示页面
我们可以将springMVC中使用的所有bean注册到spring中
Spring的web框架围绕DispatcherServlet设计,DispatcherServlet它的作用是将请求分发到不同的处理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YzlFUPG8-1670147240885)(D:\Java\Markdown\java学习笔记\05第五阶段:SSM框架.assets\image-20221124150719846.png)]
1.导入依赖
org.springframework spring-webmvc 5.3.23
javax.servlet jstl 1.2
web.xml
springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml 1 springmvc /
3.编写spring的配置文件
springmvc-servlet.xml
4.编写Controller
package com.daban.controller;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();//业务代码mv.addObject("msg","这是响应的数据");//设置视图跳转mv.setViewName("hello");return mv;}
}
5.编写显示页面(jsp)
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
${msg}
6.启动tomcat测试
如果报404,检查一下编译输出目录out有没有lib包导出
1.新建一个maven项目,导入web框架
2.编写web.xml
springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml 1 springmvc /
3.编写springmvc-servlet.xml
4.创建Controller
package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HelloController {@RequestMapping("/hello")//请求路径public String hello(Model model){//封装数据model.addAttribute("msg","我是注解开发");return "hello";//返回的视图名字(跳转的视图)}
}
5.视图
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
${msg}
注解扩展:
@Controller
@RequestMapping("/all")//如果给类加上该注解,则url变成http://localhost:8080/all/hello
@RestController//标识该类不会被视图解析器解析,返回的是一个字符串
public class HelloController {@RequestMapping("/hello")//请求路径public String hello(Model model){//封装数据model.addAttribute("msg","我是注解开发");return "hello";//返回的视图名字(跳转的视图)}
}
概念:RestFul是一个资源定位及资源操作的风格,不是标准,也不是协议,是一种风格
使用不同的地址,带不同的参数来实现
原始方式:http://localhost:8080/r?a=1&b=2
@Controller
public class RestFulTest {//http://localhost:8080/r?a=1&b=2@RequestMapping("/r")public String test(int a, int b , Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}
通过不同的请求方式实现,使用相同的地址实现不同的请求
更改后url:http://localhost:8080/r/1/2
@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@RequestMapping("/r/{a}/{b}")public String test(@PathVariable int a, @PathVariable int b , Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}
限定请求方式一
@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@RequestMapping(value = "/r/{a}/{b}",method = RequestMethod.POST)public String test(@PathVariable int a, @PathVariable String b , Model model){String res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}
限定请求方式二
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@GetMapping("/r/{a}/{b}")public String test(@PathVariable int a, @PathVariable String b , Model model){String res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}
这样通过限定不同的请求方式,来使同一个地址,执行不同的方法
return "forward:/login.jsp"; //转发到 根目录/login.jsp
return "forward:/login"; //转发到 根目录/login
return "redirect:/login.jsp";//重定向到 根目录/login.jsp
return "redirect:/login"; //重定向到 根目录/login
return "login.jsp"; //转发到,根目录/WEB-INF/jsp/login.jsp.jsp,错误用法
return "login"; //转发到 根目录/WEB-INF/jsp/login
@Controller
public class DispatcherTest {@RequestMapping("/d/t1")public String test3(Model model){model.addAttribute("msg","t3");//默认是转发,加上redirect:就是重定向return "redirect:/index.jsp";}
}
WEB-INF下的文件无法重定向:
WEB-INF是安全目录,客户端无法访问,而重定向就相当于用户直接从客户端访问了的路径,自然就不可以啦,只有程序内部转发的时候才能转发到WEB-INF下的JSP
提交域名称和处理方法的参数名一致
//http://localhost:8080/hello?name=123
public String test3(String name,Model model){return "test1";
}
提交域名称和处理方法的参数名不一致
//http://localhost:8080/hello?name=123
public String test3(@RequestParam("name") String username, Model model){return "test1";
}
提交的是一个对象
创建一个实体类,实体类的属性就是提交的参数
//http://localhost:8080/hello?name=ss&age=12
public String test3(User user, Model model){return "test1";
}
如果使用对象的话,前端传递的参数名必须和实体类的属性名一致,否则会为null
使用ModelAndView
可以在存储数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转
public ModelAndView test3(ModelAndView mv){mv.addObject("msg","ModelAndView");mv.setViewName("test1");return mv;
}
使用Model
只有寥寥的几个方法,只适用于存储数据,简化操作
public String test3(Model model){model.addAttribute("msg","信息");return "test1";
}
使用ModelMap
继承了LinkedMap,除了实现自身的一些方法,同样继承了LinkedMap的方法,操作更丰富
public String test3(ModelMap map){map.addAttribute("msg","map");return "test1";
}
加上过滤器,这里一定要注意"/“和”/*"的区别
/ :匹配所有请求,不会去匹配jsp页面
/* :匹配所有请求,包括jsp页面
encoding org.springframework.web.filter.CharacterEncodingFilter encoding utf-8
encoding /*
json是js对象的字符串表示形式,它使用文本表示一个js对象信息,本质是一个字符串
var obj = {name:"zhangsan",age:12};//这是对象
var json ='{{name:"zhangsan",age:12}}'//这是json字符串
json和js对象互相转化
var obj1 = JSON.parse(json);//json字符串转js对象
var json1 = JSON.stringify(obj);//js对象转json字符串
@RestController //标识该类不会被视图解析器解析,返回的是一个字符串
@ResponseBody //标识该方法不会被视图解析器解析,返回的是一个字符串
对象使用toString输出样式
User{name='张三', age=12, sex='男'}
对象使用jackson转换成json字符串输出样式
{"name":"张三","age":12,"sex":"男"}
@Controller
public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {User user = new User("张三",12,"男");ObjectMapper mapper = new ObjectMapper();String s = mapper.writeValueAsString(user);return s;}
}
后端响应给前端的字符串乱码解决
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
或这个spingmvc-servlet.xml文件中配置
列表返回
@Controller
public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ArrayList list = new ArrayList<>();ObjectMapper mapper = new ObjectMapper();User user = new User("张三",12,"男");User user1 = new User("张三1",12,"男");User user2 = new User("张三2",12,"男");list.add(user);list.add(user1);list.add(user2);return mapper.writeValueAsString(list);}
}返回值:[{"name":"张三","age":12,"sex":"男"},{"name":"张三1","age":12,"sex":"男"},{"name":"张三2","age":12,"sex":"男"}]
时间返回
@Controller
public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();Date date = new Date();return mapper.writeValueAsString(date);}
}返回值:1669365101815
@Controller
public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//设置一个我们喜欢的时间格式SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//关闭ObjectMapper的自动转换时间格式功能mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);//设置使用自己的时间格式mapper.setDateFormat(dateFormat);Date date = new Date();return mapper.writeValueAsString(date);}
}返回值:"2022-11-25 04:41:45"
依赖
com.alibaba fastjson 2.0.19
//java对象转json字符串
String s = JSON.toJSONString(list);
System.out.println("java对象转json字符串(列表):"+s);
String us = JSON.toJSONString(user);
System.out.println("java对象转json字符串(对象):"+us);
//json字符串转Java对象
JSONObject javaObj = JSON.parseObject(us);
System.out.println("json字符串转Java对象:"+javaObj);
//java对象转json对象
JSONObject jsonObject = (JSONObject) JSON.toJSON(user1);
System.out.println("java对象转json对象:"+jsonObject);
//json对象转java对象
User user3 = JSON.toJavaObject(jsonObject, User.class);
System.out.println("json对象转java对象:"+user3);
创建一个数据库
CREATE DATABASE `ssmbuild`;USE `ssmbuild`;
DROP TABLE IF EXISTS `books`;CREATE TABLE `books`(`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',`bookName` VARCHAR(100) NOT NULL COMMENT '书名',`bookCounts` VARCHAR(11) NOT NULL COMMENT '数量',`detail` VARCHAR(200) NOT NULL COMMENT '描述',KEY `bookID` (`bookID`)
)ENGINE INNODB DEFAULT CHARSET=utf8;INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)
VALUES
(1,'三国演义',10,'三国'),
(2,'西游记',8,'孙悟空'),
(3,'红楼梦',32,'贾府,林黛玉'),
(4,'水浒传',6,'梁山好汉三结义'),
(5,'三体',43,'科技之光'),
(6,'射雕英雄传',98,'金庸大作');
创建一个Maven项目
导入依赖
junit junit 4.12
mysql mysql-connector-java 5.1.47
com.mchange c3p0 0.9.5.2
javax.servlet servlet-api 2.5
javax.servlet.jsp jsp-api 2.2
javax.servlet jstl 1.2
org.mybatis mybatis 3.5.11
org.mybatis mybatis-spring 2.0.7
org.springframework spring-webmvc 6.0.0
org.springframework spring-jdbc 6.0.0
创建配置文件mybatis-config.xml
创建数据源database.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
创建spring空配置文件ApplicationContext.xml
创建books实体类
package com.daban.pojo;public class Books {private int bookID;private String bookName;private String bookCounts;private String detail;public Books(int bookID, String bookName, String bookCounts, String detail) {this.bookID = bookID;this.bookName = bookName;this.bookCounts = bookCounts;this.detail = detail;}public int getBookID() {return bookID;}public void setBookID(int bookID) {this.bookID = bookID;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getBookCounts() {return bookCounts;}public void setBookCounts(String bookCounts) {this.bookCounts = bookCounts;}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}@Overridepublic String toString() {return "Books{" +"bookID=" + bookID +", bookName='" + bookName + '\'' +", bookCounts='" + bookCounts + '\'' +", detail='" + detail + '\'' +'}';}
}
创建接口BookMapper.java
package com.daban.dao;import com.daban.pojo.Books;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface BookMapper {//增加一本书int addBook(Books books);//删除一本书int deleteBookById(@Param("bookId") int id);//修改一本书int updateBook(Books books);//查询一本书Books queryBookById(@Param("bookId") int id);//查询全部书List queryAllBook();List queryBookByName(String bookName);
}
创建接口映射文件BookMapper.xml
insert into ssmbuild.books(bookName, bookCounts, detail)values (#{bookName},#{bookCounts},#{detail}); delete from ssmbuild.books where bookID = #{bookId}; update ssmbuild.booksset bookName = #{bookName},bookCounts=#{bookCounts},detail=#{detail}where bookID = #{bookID};
在mybatis配置文件中注册mapper
创建接口BookService.java
package com.daban.service;import com.daban.pojo.Books;
import java.util.List;public interface BookService {//增加一本书int addBook(Books books);//删除一本书int deleteBookById(int id);//修改一本书int updateBook(Books books);//查询一本书Books queryBookById(int id);//查询全部书List queryAllBook();List queryBookByName(String bookName);
}
创建接口的实现类BookServiceImp.java
package com.daban.service;import com.daban.dao.BookMapper;
import com.daban.pojo.Books;import java.util.List;public class BookServiceImp implements BookService{//业务层调dao层private BookMapper bookMapper;public void setBookMapper(BookMapper bookMapper) {this.bookMapper = bookMapper;}@Overridepublic int addBook(Books books) {return bookMapper.addBook(books);}@Overridepublic int deleteBookById(int id) {return bookMapper.deleteBookById(id);}@Overridepublic int updateBook(Books books) {return bookMapper.updateBook(books);}@Overridepublic Books queryBookById(int id) {return bookMapper.queryBookById(id);}@Overridepublic List queryAllBook() {return bookMapper.queryAllBook();}@Overridepublic List queryBookByName(String bookName) {return bookMapper.queryBookByName(bookName);}}
创建spring-dao.xml
创建spring-service.xml
增加web支持
配置web.xml
这里有一个兼容文件,在配置DispatcherServlet时报错,把spring-webmvc依赖版本改成5.3.23
springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:ApplicationContext.xml 1 springmvc / encoding org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 encoding /* 15
创建配置spring-mvc.xml
将spring配置文件统一到ApplicationContext中
创建一个控制类BookController.java
package com.daban.controller;import com.daban.pojo.Books;
import com.daban.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;@Controller
@RequestMapping("/book")
public class BookController {@Autowired@Qualifier("BookServiceImp")private BookService bookService;//查询所有书籍@RequestMapping("/allBook")public String allBook(Model model){List books = bookService.queryAllBook();model.addAttribute("boos",books);return "allBook";}//跳转到新增书籍页面@RequestMapping("/addBookPage")public String toAddBookPage(){return "addBookPage";}//执行添加书籍@RequestMapping("/addBook")public String addBook(Books books){//System.out.println(books);bookService.addBook(books);return "redirect:/book/allBook";//return "allBook";}//跳转到书籍修改页@RequestMapping("/updateBookPage")public String toUpdateBookPage(int id,Model model){Books book = bookService.queryBookById(id);model.addAttribute("book",book);return "updateBookPage";}//执行修改书籍@RequestMapping("/updateBook")public String updateBook(Books books){System.out.println(books);bookService.updateBook(books);return "redirect:/book/allBook";}//删除数据@RequestMapping("/deleteBook")public String deleteBook(int id){bookService.deleteBookById(id);return "redirect:/book/allBook";}//查询书籍@RequestMapping("/queryBookByName")public String queryBook(String queryBookName,Model model){List books = bookService.queryBookByName("%"+queryBookName+"%");//System.out.println(books);if(books.size()==0){model.addAttribute("error","没有查到内容");}else{model.addAttribute("boos",books);}return "allBook";}
}
页面其实和Controller层同步写的
编写首页index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
首页 全部书籍
编写allbook.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
查询全部书籍
编写addBookPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
添加书籍
添加书籍
编写updateBookPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
修改书籍
修改书籍
他是一个在无需刷新网页的情况下,能够更新部分网页数据的技术
Ajax的核心是XMLHttpRequest对象(XHR)
jQuery提供了多个与ajax相关的方法
jQuery静态资源找不到问题
spring配置文件没有加这个语句,过滤静态资源使不经过servletfunction a(){$.ajax({//请求地址url:"${pageContext.request.contextPath}/a2",//请求数据data:{"name":$("#username").val()},//成功回调函数,带返回数据data,这个参数是键值对success:function (data) {alert(data);console.log("执行的成功的回调函数");},//失败回调函数error:function () {console.log("执行的失败的回调函数");}})
}
实体类
package com.daban.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private int age;private String sex;
}
控制层
@RequestMapping("/a3")
public List a3(){ArrayList userList = new ArrayList<>();userList.add(new User("张三",32,"男"));userList.add(new User("李四",12,"女"));userList.add(new User("王五",52,"男"));userList.add(new User("王留",22,"男"));return userList;
}
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
姓名 年龄 性别
控制层
@RequestMapping(value = "/a4",produces = "text/html;charset=utf-8")
public String a4(String name){if(name.equals("ss")){return "OK";}elsereturn "用户名不存在";
}
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
用户名:
密码:
SpringMVC的拦截器类似于servlet中的过滤器Filter
拦截器是AOP思想的具体应用,意思拦截器就是横切进去的
拦截器只会拦截访问控制器的方法,静态页面放行,自带静态资源过滤
自定义拦截器(实现HandlerInterceptor接口):
package com.daban.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("===========拦截前===========");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("===========拦截后===========");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("===========清理===========");}
}
在springmvc中配置拦截器,才能使用
控制器:
@RequestMapping("/login")
public String login(HttpSession session, String name, String pwd, Model model){//如果name或pwd为空,则说明是使用session越权登录,正常跳转//否则是正常登陆,需要验证用户名密码if(name==null || pwd==null){return "main";}else {if(name.equals("zj") && pwd.equals("123")){session.setAttribute("username",name);return "main";}else{model.addAttribute("msg","账号或密码错误");return "forward:/login.jsp";}}}
@RequestMapping("/logout")
public String logout(HttpSession session){session.removeAttribute("username");return "redirect:/login.jsp";
}
拦截器:
package com.daban.config;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();Object username = session.getAttribute("username");String name = request.getParameter("name");String pwd = request.getParameter("pwd");//如果name和pwd都不为空,则是正常登录,需要放行if (name!=null && pwd!=null){return true;}//如果name和pwd字段为空,则表示越权登陆,就需要判断是否有session//如果有session则放行,没session则重定向if(username!=null){return true;}else {response.sendRedirect("/login.jsp");}return false;}
}
要使用spring的上传功能,需要上下文中配置MultipartResolver
前端表单必须是post,enctype设置为multipart/form-data
表单属性enctype说明
步骤:
导入文件上传的jar包
commons-fileupload commons-fileupload 1.4
javax.servlet javax.servlet-api 4.0.1
写提交页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
spring配置文件中配置
写controller
方法一
package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;@Controller
public class FileController {//将表单中name属性为file的控件得到的文件封装成CommonsMultipartFile对象//批量上传,CommonsMultipartFile为数组即可//注意重点,CommonsMultipartFile必须加@RequestParam("file"),否则报空指针@RequestMapping("/upload")public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {//获取文件名String filename = file.getOriginalFilename();//如果文件为空,则直接回到首页System.out.println("文件名:"+filename);if("".equals(filename)){return "redirect:/index.jsp";}//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");//如果路径不存在,创建一个File realPath = new File(path);if(!realPath.exists()){realPath.mkdir();}System.out.println("上传路径:"+realPath);InputStream is = file.getInputStream();FileOutputStream fos = new FileOutputStream(new File(realPath, filename));int len=0;byte[] buffer = new byte[1024];while ((len=is.read(buffer))!=-1){fos.write(buffer,0,len);fos.flush();}is.close();fos.close();return "redirect:/index.jsp";}
}
方法二
package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;@Controller
public class FileController {//将表单中name属性为file的控件得到的文件封装成CommonsMultipartFile对象//批量上传,CommonsMultipartFile为数组即可//注意重点,CommonsMultipartFile必须加@RequestParam("file"),否则报空指针@RequestMapping("/upload")public String upload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {//获取文件名String filename = file.getOriginalFilename();//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");//如果路径不存在,创建一个File realPath = new File(path);if(!realPath.exists()){realPath.mkdir();}//通过CommonsMultipartFile的方法直接写文件file.transferTo(new File(realPath+"/"+filename));return "redirect:/index.jsp";}
}
写controller
package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;@Controller
public class FileController {@RequestMapping("/download")public String download(HttpServletRequest request, HttpServletResponse response) throws Exception {//要下载文件的地址String path = request.getServletContext().getRealPath("/upload");String fileName = "123.md";//设置响应头response.reset();//设置响应页面不缓存,清空bufferresponse.setCharacterEncoding("utf-8");//字符编码response.setContentType("multipart/form-data");//二进制流传输response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));File file = new File(path, fileName);FileInputStream fis = new FileInputStream(file);OutputStream os = response.getOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len=fis.read(buffer))!=-1){os.write(buffer,0,len);os.flush();}os.close();fis.close();return null;}
}