1. 介绍
1)三层架构:
表现层(UI):负责数据展示;
业务层(BLL):负责业务处理;
数据层(DAL):负责数据操作;
2)MVC
SpringMVC(Model-View-Controller)是Spring的一部分,基于Java的Web框架,用于开发Web应用框架。
提供一种模型(Model)-视图(View)-控制器(Controller)的架构模式,用于构建灵活,可维护性和可扩展性的Web应用。
-
-
Model(模型):数据模型,用于封装数据;
-
View(视图):页面视图,用于展示数据;
-
Controller(Handle 处理器):处理用户交互的调度器,用于根据用户需求处理程序逻辑;
-
SpringBoot只是提供了一种更快更优的Spring方式,并不是Spring的增强版。
Spring约定:简化配置。
2. 创建SpringMVC 步骤(上传文件与下载文件)
1)后端:新建MavenWeb项目
如下:
2)后端:导入Maven依赖(pom.xml)
<dependencies> <!-- Servlet 坐标 --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- servlet3.1规范的坐标 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp坐标--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <!--spring的坐标--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--spring web的坐标--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--springmvc的坐标--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> </plugins> </build>
注:导入后背景有黄色高亮的是有漏洞的,但不影响;
3)后端:创建controller层 -- > FileController类
文件上传:
1 // 文件上传 2 // @RequestMapping(value = "/upload", method = RequestMethod.POST) 等价于 @PostMapping() 3 @PostMapping(value = "upload") 4 @ResponseBody 5 public String fileUpload(MultipartFile[] uploadFile) { 6 for (MultipartFile file : uploadFile) { 7 //获取原始文件名 8 String originalFilename = file.getOriginalFilename(); 9 10 11 try { 12 // 生成UUID 13 // 修正文件名出现乱码 防止文件名重复造成覆盖 14 originalFilename = new String(originalFilename.getBytes("ISO-8859-1"), "UTF-8"); 15 } catch (UnsupportedEncodingException e) { 16 throw new RuntimeException(e); 17 } 18 System.out.println("文件名:" + originalFilename); 19 // UUID随机 20 String newFile = UUID.randomUUID().toString() + "_" + originalFilename; 21 22 // 指定文件上传路径 23 // Windows版--方式 24 String serverWin = "E:\\Chrom\\Download\\pictures\\"; 25 26 // Linux版--方式 27 // String serverLinux = "/home"; 28 29 File fileWin = new File(serverWin); 30 // 文件夹是否存在 31 if (!fileWin.exists()) { 32 fileWin.mkdir(); 33 } 34 try { 35 // 文件与文件夹 36 file.transferTo(new File(serverWin + newFile)); 37 } catch (IOException e) { 38 throw new RuntimeException(e); 39 } 40 } 41 return "success"; 42 }
文件下载:
// 文件下载 @GetMapping(value = "download") public ResponseEntity<byte[]> download(HttpServletRequest httpServletRequest, String filename) { // 指定文件下载目录 // 文件在服务器的目录 String fileDownloadWin = "E:\\Chrom\\Download\\pictures\\"; // 指定文件下载名称 File file = new File(fileDownloadWin + File.separator + filename); HttpHeaders httpHeaders = new HttpHeaders(); filename = getFilename(httpServletRequest, filename); httpHeaders.setContentDispositionFormData("attachment", filename); httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); try { return new ResponseEntity<>(FileUtils.readFileToByteArray(file), httpHeaders, HttpStatus.OK); } catch (IOException e) { throw new RuntimeException(e); } }
工具类:(解决不同浏览器版本兼容问题)
/** * 工具类 解决 不同浏览器的版本兼容 * @param request * @param filename * @return * @throws UnsupportedEncodingException */ private String getFilename(HttpServletRequest request,String filename){ //判断是不是IE内核的关键字 String[] IEBrowerKeyWords = {"MSIE","Trident","Edge"}; String keywords = request.getHeader("User-Agent"); for (String keyWord : IEBrowerKeyWords) { if(keywords.contains(keyWord)){ //判断是否为IE浏览器 try { return URLEncoder.encode(filename,"UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } } // 其他浏览器编码格式ISO-8859-1 try { return new String(filename.getBytes("UTF-8"),"ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } }
@ResponseBody 注解:将方法的返回值通过适当的转换器转换为指定的格式之后,写入到 response 对象的 body 区,通常用来返回 JSON、XML 数据。
4)后端:创建spring-mvc.xml配置文件(本质就是spring的配置件)
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> </bean> <!--注解开发--> <context:component-scan base-package="com.bei"/>
5)后端:web.xml中配置前端控制器
<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*:spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
6)后端:配置tomcat
7)前端:使用JQuery编写上传方法
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上传</title> <!-- 导入JQuery --> <script type="text/javascript" src="./jquery-1.11.3.min.js"></script> </head> <body> <!-- 请求路径 --> <form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data"> 上传文件: <input type="button" value="添加文件" onclick="add()" /> <div id="file" style="margin-top: 10px;" value="文件上传区域"> </div> <input id="submit" type="submit" value="上传" style="display: none;margin-top: 10px;" /> </form> </body> <script> function add() { var innerdiv = "<div>"; // name='uploadFile' 一定是 上传方法内的参 innerdiv += "<input type='file' name='uploadFile'>" + "<input type='button' value='删除' onclick='remove(this)'>"; innerdiv += "</div>"; $("#file").append(innerdiv); $("#submit").css("display", "block"); } function remove(obj) { $(obj).parent().remove(); if ($("#file div").length == 0) { $("#submit").css("display", "none"); } } </script>
8)前端:使用JQuery编写下载方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>下载</title> </head> <body> <!-- 请求路径 ? 文件名 --> <a href="http://localhost:8080/downloadThree?fileName=小可莉.mp4">小可莉.mp4</a> </body> </html>
3. 工作流程分析
1)服务器启动
-
-
加载web.xml中DispatcherServlet;
-
读取spring-mvc.xml中的配置,加载所有com.xx 包中所有标记为bean的类;
-
读取bean中方法上方标注@RequestMapping的内容;
-
2)处理请求
-
-
DispatcherServlet配置拦截所有请求 / ;
-
使用请求路径与所有加载的@RequestMapping的内容进行比对;
-
执行对应的方法;
-
根据方法的返回值在webapp目录中查找对应的页面并展示;
-
3)web三大组件有 处理器映射,处理器适配器, 视图解析器
-
- dispatcherServlet 前置控制器,负责接收并处理所有的web请求,根据handlerMapping(处理器映射)找到具体的Controller(处理器),由controller完成具体的处理逻辑。
- HandlerMapping(处理器映射器):负责处理web请求和具体的Controller之间的映射关系匹配。
- HandlerAdapter(处理器适配器) 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 主要处理方法参数、相关注解、数据绑 定、消息转换、返回值、调用视图解析器等等。
- Controller(处理器):DispatherServlet的次级控制器,web请求的具体处理者。DispatherServlet获得handlerMapping的返回结果后,调用controller的处理方法处理当前的业务请求,处理完成后返 回ModelAndView对象。
- ViewResolver( 视图解析器):用来处理视图名与具体的view实例之间的映射对应关系。根据ModelAndView中的视图名查找相应的View实现类,然后将查找的结果返回给DispatcherServlet, DispatcherServlet最终会将ModelAndView中的模型数据交给返回的View处理最终的视图渲染工作。
Springmvc架构原理解析:
第一步:发起请求到前端控制器(DispatcherServlet);
第二步:前端控制器请求HandlerMapping查找 Handler,可以根据xml配置、注解进行查找;
第三步:处理器映射器HandlerMapping向前端控制器返回Handler;
第四步:前端控制器调用处理器适配器去执行Handler;
第五步:处理器适配器去执行Handler;
第六步:Handler执行完成给适配器返回ModelAndView;
第七步:处理器适配器向前端控制器返回ModelAndView ModelAndView是springmvc框架的一个底层对象,包括 Model和view;
第八步:前端控制器请求视图解析器去进行视图解析 根据逻辑视图名解析成真正的视图(jsp);
第九步:视图解析器向前端控制器返回View;
第十步:前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域;
第十一步:前端控制器向用户响应结果。
4. 请求参数的绑定
1)默认类型:
直接放在参数上就可以使用的数据,HttpServletRequest;
2)简单类型:
直接将简单类型的数据放在方法里,如果前端参数和后端参数名字一样,自动匹配;
名字不一样:@RequsetParam(“前端的值”) 就可以将前传的值和后端参数映射;
3 对象 :
前端的参数要和对象的属性名称必须、一定一致,会自动封装。
4 对象嵌套:
参数和对象的属性名称一致,前端参数对象子属性必须(子对象.属性);
5 自定义数据的绑定:
① 编写转换器类,作用是将前端的数据类型转换成后端的数据类型,继承converter;
② 配置文件中,添加转化器驱动。
6 数组:
前端数组中是简单类型的数据,前端数组中的name要和后端数组名称一致;
7 集合:
后端接受的对象是含有List<对象>属性的,那么前端的name值格式要和后端list属性名称一致,而且用索引的格式 list[0].属性(list集合里对象的属性名称)。