目录
springmvc简介:
springmvc的核心组件:
1、前端控制器DispatcherServlet
2、处理器映射器HandlerMapping
3、处理器适配器HandlerAdapter
4、处理器Handler
5、视图解析器ViewResolver
springmvc的工作原理图:
编辑
具体流程:
springmvc的表单处理:
Spring MVC - 页面重定向:
springmvc实现文件上传和下载:
MultipartFile:
文件下载:
springmvc是一种结构模式,将界面和后台代码分隔开来,使程序分层又分工合作。其中,MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
模型(Model):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或 JavaBean组件。
视图(View):负责进行模型的展示,将逻辑视图解析成物理视图并渲染。
控制器(Controller):接收用户请求,委托给模型进行处理,处理完毕后把返回的模型数据返回给视图,由视图负责展示。起调度作用。
接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
根据请求的url查找Handler,HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
按照特定规则去执行Handler通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler通过扩展适配器可以对更多类型的处理器进行执行。
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
进行视图解析,根据逻辑视图名解析成真正的视图(view)
ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
(1)首先浏览器发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
(2)DispatcherServlet——>HandlerMapping,处理器映射器将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器对象、多个HandlerInterceptor拦截器)对象;
(3)DispatcherServlet——>HandlerAdapter,处理器适配器将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
(4)HandlerAdapter——>调用处理器相应功能处理方法,并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
(5)ModelAndView对象(Model部分是业务对象返回的模型数据,View部分为逻辑视图名)——> ViewResolver, 视图解析器将把逻辑视图名解析为具体的View;
(6)View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构;
(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
首先,创建一个实体类:
package com.yinan;
@Data
@Setter
@Getter
public class Student {
private Integer age;
private String name;
private Integer id;
}
要使用注解来代替手写getter和setter方法,需要下载插件Lombok,然后倒入依赖
然后,创建一个对应的控制器
package com.yinan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.ui.ModelMap;
@Controller
public class StudentController {
@RequestMapping(value = "/student", method = RequestMethod.GET)
public ModelAndView student() {
return new ModelAndView("student", "command", new Student());
}
@RequestMapping(value = "/addStudent", method = RequestMethod.POST)
public String addStudent(@ModelAttribute("SpringWeb")Student student,
ModelMap model) {
model.addAttribute("name", student.getName());
model.addAttribute("age", student.getAge());
model.addAttribute("id", student.getId());
return "result";
}
}
在这里,第一个服务方法 student(),我们在 ModelAndView 对象中传递了一个名为"command"的空白 Student 对象。这样做是因为 spring 框架需要一个名为"command"的对象,如果我们在 JSP 文件中使用
接下来,创建jsp界面:
<%@taglib uri="http://www.springframework.org/tags/form" prefix = "form"%>
Spring MVC
Student Information
Name
Age
id
接下来,启动程序:
首先,还是先创建一个控制器:
package com.yinan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class WebController {
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
@RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
return "redirect:finalPage";
}
@RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
return "final";
}
}
创建index.jsp界面:
<%@taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%>
Spring Page Redirection
Spring Page Redirection
Click below button to redirect the result to new page
创建final.jsp界面:
<%@taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%>
Spring Page Redirection
Redirected Page
然后,启动项目:
首先,导入相关依赖:
commons-fileupload
commons-fileupload
1.4
然后,写一个文件上传和下载的配置类:
@Configuration
public class FileConfig implements WebMvcConfigurer {
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("utf-8");
resolver.setMaxUploadSize(1024 * 1024*10);//设置文件最大上传大小为10MB
resolver.setMaxUploadSizePerFile(1024*5);//设置每个文件最大的上传大小
return resolver;
}
}
编辑上传文件的jsp页面:method="post" enctype="multipart/form-data"
文件上传
为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
封装了请求数据中的文件,此时这个文件存储在内存中或临时的磁盘文件中,需要将其转存到一个合适的位置,因为请求结束后临时存储将被清空。在 MultipartFile 接口中有如下方法:
String getName(); // 获取参数的名称
String getOriginalFilename(); // 获取文件的原名称
String getContentType(); // 文件内容的类型
boolean isEmpty(); // 文件是否为空
long getSize(); // 文件大小
byte[] getBytes(); // 将文件内容以字节数组的形式返回
InputStream getInputStream(); // 将文件内容以输入流的形式返回
void transferTo(File dest); // 将文件内容传输到指定文件中
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(String wjsm, @RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
System.out.println("文件说明:" + wjsm);
if(!file.isEmpty()) {
String path = request.getServletContext().getRealPath("/resource/uploadFile");
//获取上传文件的原名
String fileName = file.getOriginalFilename();
File desfile = new File(path,fileName);
if(!desfile.getParentFile().exists()) {
desfile.getParentFile().mkdirs();
}
file.transferTo(new File(path + File.separator + fileName));
}else {
System.out.println("文件为空!");
}
return "success";
}
该链接 href 属性为要下载文件的文件,download 属性可自定义修改下载的文件名。这样就实现文件下载了
下载
@RequestMapping(value="/download")
public ResponseEntity download(HttpServletRequest request, @RequestParam("fileName") String fileName) throws Exception{
//下载文件路径
String path = request.getServletContext().getRealPath("/resource/uploadFile");
File file = new File(path + File.separator + fileName);
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名,并解决中文名称乱码问题
String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");
//通知浏览器以attachment(下载方式)打开
headers.setContentDispositionFormData("attachment", downloadFileName);
//applicatin/octet-stream: 二进制流数据(最常见的文件下载)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}
另外需要注意的一点:ajax请求无法响应下载功能,我们可构建表单进行提交。