-
package com.xuecheng.media;import com.j256.simplemagic.ContentInfo;import com.j256.simplemagic.ContentInfoUtil;import io.minio.*;import io.minio.errors.*;import org.apache.commons.codec.digest.DigestUtils;import org.apache.commons.io.IOUtils;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.http.MediaType;import java.io.*;import java.util.HashMap;import java.util.Map;/** * 测试minio的sdk * * @author ManolinCoder * @date 2024-10-21 */@SpringBootTestpublic class MinioTest { // MinIO服务器地址 String url = "http://localhost:9000"; // MinIO访问密钥 String accessKey = "accessKey"; // MinIO秘密密钥 String secretKey = "secretKey"; // 待上传的文件路径 String filePath = "/Users/lcm/Movies/测试视频/1.mp4"; // MinIO存储桶名称 String bucketName = "testbucket"; // 存储桶中的对象名称 String objectName = "1.mp4"; MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); /** * 上传文件 * * @param * @return void * @author ManolinCoder * @date 2024-10-21 */ @Test public void testUpload() throws Exception { ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4"); String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE; // 通用 mimeType 字节流 if (extensionMatch != null) { mimeType = extensionMatch.getMimeType(); } try { // Make 'asiatrip' bucket if not exist. boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("testbucket").build()); if (!found) { // Make a new bucket called 'asiatrip'. minioClient.makeBucket(MakeBucketArgs.builder().bucket("testbucket").build()); } else { System.out.println("文件桶已存在!!!"); } // 上传文件 uploadFile(minioClient, filePath, bucketName, objectName, mimeType); //上传文件完整性校验 boolean flag = checkFileIntegrity(minioClient, filePath, bucketName, objectName); System.out.println(flag ? "上传文件成功了!!!" : "上传文件失败了!!!"); } catch (MinioException e) { System.out.println("Error occurred: " + e); System.out.println("HTTP trace: " + e.httpTrace()); } } /** * 删除文件 * * @param * @return void * @author ManolinCoder * @date 2024-10-21 */ @Test public void testDelete() throws Exception { RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket("testbucket").object("1.MP4").build(); minioClient.removeObject(removeObjectArgs); } /** * 查询文件,下载到本地 * * @param * @return void * @author ManolinCoder * @date 2024-10-21 */ @Test public void testGetObject() throws Exception { GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("1.MP4").build(); FilterInputStream inputStream = minioClient.getObject(getObjectArgs); String localFileName = "/Users/lcm/Downloads/1.mp4"; // 指定输出流 FileOutputStream outputStream = new FileOutputStream(new File(localFileName)); IOUtils.copy(inputStream, outputStream); // md5完整性校验 boolean flag = checkFileIntegrity(minioClient, localFileName, bucketName, objectName); if (flag) { System.out.println("下载成功了!!!"); } else { System.out.println("下载失败了!!!"); } } /** * 上传文件 * * @param minioClient * @param filePath * @param bucketName * @param objectName * @param contentType * @return void * @author CoderManolin * @date 2024-10-25 */ public void uploadFile(MinioClient minioClient, String filePath, String bucketName, String objectName, String contentType) throws Exception { // 计算上传前本地文件MD5 String uploadLocalFileMD5 = calculateMD5(filePath); System.out.println("上传前本地文件MD5: uploadLocalFileMD5=" + uploadLocalFileMD5); Map<String, String> md5Map = new HashMap<>(); md5Map.put("md5", uploadLocalFileMD5); //上传文件到 MinIO File file = new File(filePath); minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(new FileInputStream(file), file.length(), -1) .userMetadata(md5Map) .contentType(contentType) .build() ); System.out.println("File uploaded successfully: " + objectName); } /** * 计算md5 * * @param filePath * @return File * @author ManolinCoder * @date 2024-10-23 */ public String calculateMD5(String filePath) throws Exception { FileInputStream fileInputStream = new FileInputStream(filePath); return DigestUtils.md5Hex(fileInputStream); } /** * 对比本地文件和minio文件的MD5值是否一致,校验文件完整性 * * @param minioClient * @param filePath * @param bucketName * @param objectName * @return boolean * @author CoderManolin * @date 2024-10-25 */ public boolean checkFileIntegrity(MinioClient minioClient, String filePath, String bucketName, String objectName) throws Exception { // 计算本地文件的MD5 String localFileMD5 = calculateMD5(filePath); System.out.println("Local file MD5: " + localFileMD5); // 获取MinIO中对象的MD5 StatObjectResponse stat = minioClient.statObject( StatObjectArgs.builder() .bucket(bucketName) .object(objectName) .build()); String minioFileMD5 = stat.userMetadata().get("md5"); System.out.println("MinIO file MD5: " + minioFileMD5); // 比较MD5值 return localFileMD5.equals(minioFileMD5); }}
-
使用EasyExcel进行大数据量导出时容易导致内存溢出,特别是在导出百万级别的数据时。你有遇到过这种情况吗,以下是V 哥整理的解决该问题的一些常见方法,分享给大家,欢迎一起讨论:EasyExcel大数据量导出常见方法1. 分批写入EasyExcel支持分批写入数据,可以将数据分批加载到内存中,分批写入Excel文件,避免一次性将大量数据加载到内存中。示例代码: String fileName = "large_data.xlsx"; ExcelWriter excelWriter = EasyExcel.write(fileName).build(); WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); // 假设每次写入10000条数据 int batchSize = 10000; List<Data> dataList; int pageIndex = 0; do { // 分页获取数据 dataList = getDataByPage(pageIndex++, batchSize); excelWriter.write(dataList, writeSheet); } while (dataList.size() == batchSize); // 关闭资源 excelWriter.finish();2. 设置合适的JVM内存针对大数据导出场景,可以尝试增大JVM的内存分配,例如: java -Xms512M -Xmx4G -jar yourApp.jar解释:-Xms512M:设置初始堆大小为512MB。-Xmx4G:设置最大堆大小为4GB。3. 减少数据对象的复杂性导出数据时,尽量简化数据对象,避免不必要的嵌套和多余字段的加载,以减少对象占用的内存空间。4. 关闭自动列宽设置EasyExcel的自动列宽功能会占用大量内存,特别是在数据量较大的情况下。关闭自动列宽可以节省内存。示例代码: EasyExcel.write(fileName) .registerWriteHandler(new SimpleWriteHandler()) // 不使用自动列宽 .sheet("Sheet1") .doWrite(dataList);5. 使用Stream导出(适合大数据)利用OutputStream分批写入数据,减少内存消耗。通过BufferedOutputStream可以进一步提高性能。示例代码: try (OutputStream out = new BufferedOutputStream(new FileOutputStream(fileName))) { ExcelWriter excelWriter = EasyExcel.write(out).build(); WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); int pageIndex = 0; List<Data> dataList; do { dataList = getDataByPage(pageIndex++, batchSize); excelWriter.write(dataList, writeSheet); } while (dataList.size() == batchSize); excelWriter.finish(); } catch (IOException e) { e.printStackTrace(); }6. 选择合适的数据导出工具如果数据量非常大,可以考虑切换到支持更高性能的导出工具(如Apache POI的SXSSFWorkbook),适合导出百万级别数据量,但配置和使用会更复杂。亮点来了,那要如何使用 POI 的 SXSSFWorkbook来导出百万级别的数据量呢?Apache POI的SXSSFWorkbook 实现百万级别数据量的导出案例使用Apache POI的SXSSFWorkbook可以处理大数据量的Excel导出,因为SXSSFWorkbook基于流式写入,不会将所有数据加载到内存中,而是使用临时文件进行缓存,这样可以显著减少内存消耗,适合百万级别数据的导出。下面我们来看一个完整的实现示例。代码如下import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class LargeDataExportExample { public static void main(String[] args) { // 文件输出路径 String filePath = "vg_large_data_export.xlsx"; // 导出百万级数据 exportLargeData(filePath); } private static void exportLargeData(String filePath) { // 每次写入的批次大小 final int batchSize = 10000; // 数据总条数 final int totalRows = 1_000_000; // 创建SXSSFWorkbook对象,内存中只保留100行,超过的部分会写入临时文件 SXSSFWorkbook workbook = new SXSSFWorkbook(100); workbook.setCompressTempFiles(true); // 启用临时文件压缩 // 创建工作表 Sheet sheet = workbook.createSheet("Large Data"); // 创建标题行 Row headerRow = sheet.createRow(0); String[] headers = {"ID", "Name", "Age"}; for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); } int rowNum = 1; // 数据开始的行号 try { // 按批次写入数据 for (int i = 0; i < totalRows / batchSize; i++) { // 模拟获取每批数据 List<Data> dataList = getDataBatch(rowNum, batchSize); // 将数据写入到Excel中 for (Data data : dataList) { Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(data.getId()); row.createCell(1).setCellValue(data.getName()); row.createCell(2).setCellValue(data.getAge()); } // 处理完成一批数据后,可以选择清除缓存数据,防止内存溢出 ((SXSSFSheet) sheet).flushRows(batchSize); // 清除已写的行缓存 } // 将数据写入文件 try (FileOutputStream fos = new FileOutputStream(filePath)) { workbook.write(fos); } System.out.println("数据导出完成:" + filePath); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭workbook并删除临时文件 workbook.dispose(); } } /** * 模拟分页获取数据 */ private static List<Data> getDataBatch(int startId, int batchSize) { List<Data> dataList = new ArrayList<>(batchSize); for (int i = 0; i < batchSize; i++) { dataList.add(new Data(startId + i, "Name" + (startId + i), 20 + (startId + i) % 50)); } return dataList; } // 数据类 static class Data { private final int id; private final String name; private final int age; public Data(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } } }来解释一下代码SXSSFWorkbook:SXSSFWorkbook(100)表示内存中最多保留100行数据,超过的部分会写入临时文件,节省内存。批次处理:通过batchSize控制每批次写入的数据量,以减少内存消耗。totalRows设置为1,000,000表示导出100万条数据。模拟数据生成:getDataBatch方法模拟分页获取数据,每次返回一批数据。清除缓存行:每次写入一批数据后,通过flushRows(batchSize)将缓存的行从内存中清除,以控制内存占用。压缩临时文件:workbook.setCompressTempFiles(true)启用临时文件压缩,进一步减少磁盘空间占用。需要注意的事项临时文件:SXSSFWorkbook会在系统临时文件夹中生成临时文件,需要确保磁盘空间足够。资源释放:完成数据写入后需要调用workbook.dispose()以清理临时文件。性能优化:可根据机器内存调整batchSize和SXSSFWorkbook缓存行数,避免频繁刷新和内存溢出。转载自https://www.cnblogs.com/wgjava/p/18510650
-
MVC架构 mvc是一种架构模型,本身并没有新功能,只是对项目的一种规范,方便后期进行维护;mvc架构将模型(M),视图(V)和控制(C)割离开,这么做可以提高代码书写的效率和后期维护; MVC分层次介绍 模型(MODEL) 模型负责封装应用的状态,并实现应用的功能; 封装的是数据源和所有对这些数据的操作; 在组件中,模型表示组件的状态和操作状态的方法。 模型通常分为数据模型和业务逻辑模型: 数据模型 数据模型主要存放业务数据,如订单,用户信息等。 业务逻辑模型 业务逻辑模型往往是对数据的处理,如订单和用户信息的修改。 mvc的三个部件中模型拥有处理的处理能力,安装上文所说,M可以连接和处理数据库。(EJBs和ColdFusion Components构建对象处理数据库)被模型返回的数据是中立的(模型于数据格式无关),这么一来一个模型可以被多个视图调用。可以减少代码的重复性。 视图(VIEW) ** 视图是将模型的内容呈现出来,用户可以通过对视图的操作进而操作模型,封装的是对数据源Model的显示;** 一个模型可以被多个视图复用,一个视图理论上也可以和多个模型进行关联; 视图从模型中获取展示的数据,然后用自己的方法展示给用户。如用户点击H5页面的登录,视图会给模型提交用户的数据,视图接收模型的数据,然后按照自己的方式展示给用户。 在实际WEB项目中,视图通常是HTML,XHTML,XML/XSL,WML代码组成的界面。 在MVC模式中,视图只是起到展示的作用,真正处理数据其实并没有发生。 控制器(CONTROLLER) ** 控制器时用来出来视图和模型关系的组件。封装的是外界对模型的操作。** 这些操作一般为转发给模型,模型处理数据,并调用模型中相应的一个或多个方法; 一般控制器是在模型和视图之间作为沟通的组件存在的。 用户填写完账号密码由控制器接收处理并转发给模型。可以让视图和控制器之间的耦合关系更加密切;严格的分工可以提高工作的效率。 当控制器接收到用户的请求之后,会将用户的数据和模型的更新相映射,也就是调用模型来实现用户请求的功能;控制器会选择响应应用的视图,把模型更新后的数据发送给视图,视图按照自己的方式展示给用户; 当点击WEB的超链接和发送HTML表单时,控制器本身并不传输任何数据,也不做任何处理。只是接收请求并决定调用哪个模型进行构建去处理请求,然后决定用哪个视图来显示模型返回的数据。 MVC的组件关系 根据上文的描述,Model和View是严格分开的,甚至他们之间互相不知道彼此。只有Controller作为中介连接他们两个。 视图里不会有逻辑的东西。控制器里没有展示的东西。一个模型会有很多的展示方法,每一个展示方法页不止一种模型。 比如:windows下打开文件夹; 文件夹的大图标小图标就是不同的视图但内容数据是一样的(模型数据一样); 点击进入其他的文件夹内,视图一样但是数据不同。 即–模型和视图之间并非一一对应的。 而Controller作为模型和视图之间的桥梁,可以保证模型和视图之间相互制约;点击视图的操作控制器立即给出相应; MVC交互关系: 登入程序后,展示视图用户在视图上进行操作,填写业务数据 用户点击提交来提交发出的请求 视图发出的请求传到控制器,其中包含想要完成什么样的业务功能及相关数据 控制器处理用户请求并封装,选择合适的模型,请求模型来处理用户请求的数据,接收模型的更新,并选择接下来用哪一个视图进行展示这些数据 模型会处理用户请求的业务功能,同时进行模型状态的维护和更新 当模型进行更新后模型会通知相应的视图进行更新 当视图接收到模型的通知后,会向模型进行状态查询,获取需要展示的数据,然后按照视图的规则进行展示 等待用户的下一次操作,重复上面的操作 JAVA EE的MVC架构 MVC是一种横向分层的模型。采用MVC模式的用户不可以直接访问JSP视图,即使不需要调用业务逻辑功能,也应该让用户的所有操作都经过控制器,由控制器转到视图。 JAVA EE中视图层一般JSP实现一个交互性高的异步通信Web应用。 模型层:一般以JAvaBean为主体,实现Java的业务主体 控制器:用Servlet实现, JavaEE中通常把Servlet+JSP+Javabean的模型称为Model2模型,基本划分如下: Javabean作为模型,既可以作为数据模型来封装业务数据,也可以作为业务逻辑模型来实现业务的操作;其中数据模型用来存储和传递业务数据。业务逻辑模型接收控制器传来的模型请求更新后,执行特定的业务逻辑 处理,返回相应的执行结果; JSP作为视图,负责提供页面给用户展示数据。提供相应的表单(Form)来相应用户的请求,并在适当的时候(比如用户点击提交按钮)向控制器发送用户请求来要求模型进行更新; Servlet作为控制器,用来接收用户提交的请求,并获取请求中的数据,将其转化为业务模型中需要的数据模型,然后调用业务模型中相应的方法,请求业务模型进行更新,同时根据业务执行的结果来选择需要返回的视图。发送数据给相应的视图JSP; ———————————————— 原文链接:https://blog.csdn.net/Guo_Yuhua/article/details/119977966
-
MVC架构模式,即模型-视图-控制器(Model-View-Controller)模式,是一种软件工程中的软件架构模式。它将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller),以实现代码的分层组织和关注点的分离。 模型(Model) : 模型代表应用程序的数据和业务逻辑。它负责处理数据的获取、存储和更新等操作,并且可以包含一些逻辑处理,当数据发生变化时,通知视图进行更新。模型是相对稳定的部分,重用率高,通常不直接与用户界面交互。 视图(View) : 视图负责展示数据并呈现给用户。它从模型中提取数据并将其显示在用户界面上,但不处理任何业务逻辑或数据访问操作。视图的变化不会影响模型的内容,因为模型独立于视图进行数据管理。 控制器(Controller) : 控制器作为模型和视图之间的桥梁,接收用户的输入并调用相应的模型和视图来响应这些输入。它处理所有的用户交互,如点击按钮、填写表单等,并根据需要更新模型和视图。控制器本身不输出任何结果或进行处理,仅作为中介角色。 通过这种分层设计,MVC架构模式提高了应用程序的可维护性、可扩展性和可测试性。各组件之间的职责明确,使得团队成员可以独立开发和维护不同的部分而不互相干扰。此外,由于模型和视图的分离,可以在不影响其他部分的情况下改进界面和用户交互。 总之,MVC架构模式是一种经典且灵活的设计范例,广泛应用于各种应用程序的开发中,包括Web应用、桌面应用和其他类型的应用程序。 MVC架构模式的历史发展和演变是什么? MVC(Model-View-Controller)架构模式的历史发展和演变可以追溯到20世纪70年代末期。最初,这种架构模式是由Trygve Reenskaug在Xerox PARC的Smalltalk-80项目中提出的。Smalltalk-80是当时用于开发图形用户界面应用程序的一个重要平台,而MVC模式正是为了组织这些应用程序而设计的。 在Smalltalk-80环境中,MVC架构通过将应用程序分为三个主要部分来实现:模型(Model)、视图(View)和控制器(Controller)。模型负责数据处理和业务逻辑,视图负责展示数据并允许用户交互,控制器则作为模型和视图之间的中介,处理用户的输入和请求。 随着时间的推移,MVC架构逐渐被广泛应用于不同的技术平台和编程语言中。例如,Sun公司的Java平台也采用了类似的架构模式,并且后来发展出了许多变体架构,如MVVM(Model-View-ViewModel)等。这些变体架构进一步扩展了MVC的基本概念,以适应更复杂的应用场景和需求。 此外,MVC架构也在Web应用领域得到了广泛应用。经典的MVC框架如Ruby on Rails,极大地推动了MVC模式的普及和发展。其他著名的MVC框架还包括ASP.NET MVC等,它们证明了MVC架构在提高代码可维护性和可测试性方面的优势。 尽管MVC架构在软件开发中取得了巨大成功,但其应用过程中也存在一些问题。例如,由于不同变体之间的混淆,MVC常常被误用。因此,在实际应用中需要对MVC的不同变体有清晰的理解和区分。 总结来说,MVC架构自其诞生以来已经经历了显著的发展和演变。 如何在实际项目中实现MVC架构模式以提高软件开发的效率和质量? 在实际项目中实现MVC架构模式以提高软件开发的效率和质量,需要遵循以下步骤和原则: 明确角色分工: 模型(Model) :负责数据处理和业务逻辑。它与视图(View)完全独立,确保数据逻辑不被界面展示所干扰。 视图(View) :负责数据显示和用户交互。它从模型获取数据并展示给用户,但不直接操作数据。 控制器(Controller) :作为模型和视图之间的桥梁,接收用户的输入并调用相应的模型或视图进行响应。 分离代码结构: 将应用程序分为三个主要部分:模型、视图和控制器。这种分离有助于降低代码耦合度,提高可维护性和可扩展性。 模型层处理业务逻辑和数据访问,视图层负责界面展示,控制器层处理用户输入和逻辑控制。 并行开发: 由于MVC将不同部分分离,前端开发人员可以专注于视图的实现,而后端开发人员可以独立开发模型逻辑。这样可以实现并行开发,显著提高开发效率。 测试和部署: 各个部分独立开发后,可以分别进行单元测试和集成测试,确保每个部分的功能正确无误。这不仅提高了代码质量,还减少了整体系统的调试时间。 团队协作: MVC架构促进了前后端开发人员的协作。前端开发者不需要了解后端逻辑,只需通过控制器与后端通信;后端开发者也不需要关注前端界面的具体实现。 选择合适的技术栈: 根据项目需求选择合适的技术栈。例如,在Web开发中,可以选择JSP、Servlet和POJO等技术来实现MVC设计模式。 持续优化和迭代: 在项目实施过程中,不断收集反馈并优化各部分的设计和实现。通过持续迭代,逐步完善系统功能和性能。 MVC架构模式与其他软件架构模式(如MVP、MVVM)的比较有哪些优缺点? MVC(Model-View-Controller)架构模式是一种经典的软件架构模式,它将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller)。这种模式在许多方面具有其独特的优缺点,与其他架构模式如MVP(Model-呈现阶段)和MVVM(Model-View-ViewModel)相比,各有不同的适用场景。 MVC的优点: 清晰的分层:MVC通过将业务逻辑、用户界面和控制逻辑分离到不同的组件中,有助于简化应用程序的测试和维护。 模块化程度高:当业务逻辑变更时,不需要修改View和Model,只需更换Controller即可,这使得系统的可扩展性和可维护性较高。 观察者模式支持多视图更新:MVC可以利用观察者模式实现多个视图的同时更新,从而提高系统的响应速度和用户体验。 MVC的缺点: 耦合性较高:在MVC中,View可以直接访问Model,导致View与Model之间存在高度耦合,这会降低系统的可读性、健壮性和可拓展性。 控制器职责过重:由于Controller需要处理所有与用户交互相关的逻辑,因此其职责较为复杂且容易变得过于庞大,影响开发效率和代码质量。 系统复杂度增加:实现MVC架构模式需要更多的代码和更复杂的设计,前期投入大,增加了项目的时间和成本。 MVP与MVC的比较: 耦合性:MVP通过引入Presenter来降低视图和模型之间的耦合,使得View不能直接访问Model,而是通过Presenter发出请求。这使得MVP在耦合性上优于MVC。 可维护性和测试性:由于呈现阶段的存在,MVP更容易进行单元测试和维护,因为呈现阶段隔离了视图和模型之间的交互。然而,呈现阶段可能会变得复杂,增加开发工作量。 MVVM与MVC的比较: 数据绑定:MVVM引入了数据绑定的概念,这使得View和ViewModel之间的关系更加紧密,减少了手动同步数据的需求。然而,数据绑定也可能导致性能问题,在执行复杂任务时可能会影响性能。 入口点:在MVVM中,View是应用程序的入口点,而在MVC中,Controller是入口点。这种设计上的差异决定了不同架构模式在实际应用中的适用性。 单元测试:MVVM由于其事件驱动的特性,更容易进行单元测试,而MVC的Controller与View的关系密切,可能会影响单元测试的独立性。 选择哪种架构模式取决于项目的具体需求、UI复杂度以及对测试和灵活性的要求。 在使用MVC架构模式时,如何处理数据更新和视图重定向的问题? 在使用MVC架构模式时,处理数据更新和视图重定向的问题可以参考以下方法: 数据更新: 在MVC架构中,数据更新通常涉及以下几个步骤: 控制器(Controller) :接收用户的输入并调用模型(Model)中的方法来更新数据。例如,如果用户点击了一个按钮来更新数据库中的记录,控制器会调用相应的模型方法来执行这个操作。 模型(Model) :负责实际的数据更新逻辑。这可能包括与数据库交互的代码,如存储过程或直接的SQL查询。例如,可以编写一个实体方法来直接与数据库进行更新动作。 视图重定向: 视图重定向是将用户从当前处理请求定向到另一个视图或处理请求。Spring MVC提供了两种主要的重定向方式:转发和重定向。 重定向:使用RedirectView可以实现重定向。创建一个RedirectView实例后,它会调用HttpServletResponse.sendRedirect ()方法,从而将用户重定向到指定的URL。这种方式会使之前的请求(request)失效,并进入一个新的request作用域。 转发:使用ModelAndView可以实现转发。当需要将用户从当前视图转发到另一个视图时,可以使用ModelAndView对象,并将其视为重定向的一种形式。默认情况下,ModelAndView使用的是转发方式。 ———————————————— 原文链接:https://blog.csdn.net/m0_61505785/article/details/140901532
-
MVC架构职责分析 MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。其中,View 的定义比较清晰,就是用户界面。 在 Web 项目的开发中,能够及时、正确地响应用户的请求是非常重要的。用户在网页上单击一个 URL 路径,这对 Web 服务器来说,相当于用户发送了一个请求。而获取请求后如何解析用户的输入,并执行相关处理逻辑,最终跳转至正确的页面显示反馈结果,这些工作往往是控制层(Controller)来完成的。 在请求的过程中,用户的信息被封装在 User 实体类中,该实体类在 Web 项目中属于数据模型层(Model)。 在请求显示阶段,跳转的结果网页就属于视图层(View)。 像这样,控制层负责前台与后台的交互,数据模型层封装用户的输入/输出数据,视图层选择恰当的视图来显示最终的执行结果,这样的层次分明的软件开发和处理流程被称为 MVC 模式。 总结如下: 视图层(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。 控制层(Controller):负责接收并转发请求,对请求进行处理后,指定视图并将响应结果发送给客户端。 数据模型层(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(即在数据库中存取数据)。 业务流程见下图: Servlet+JSP+JavaBean Servlet+JSP+JavaBean 中 Servlet 用于处理用户请求,JSP 用于数据显示,JavaBean 用于数据封装,适合复杂的 Web 程序。 VO:视图层对象 例子:比如User类中有id,name,age,password等20个字段。而前端登录时所需数据只要name和password,这时可封装一个UserVo对象只包含name和password两个属性。 参考: https://baike.baidu.com/item/MVC%E6%A1%86%E6%9E%B6/9241230?fromtitle=mvc&fromid=85990&fr=aladdin http://c.biancheng.net/spring_mvc/mvc.html https://www.bilibili.com/video/BV1aE41167Tu?p=2 ———————————————— 原文链接:https://blog.csdn.net/qq_38256519/article/details/121895614
-
一、SpringMVC 简介 1. 什么是 MVC MVC 是一种软件架构的思想,将软件按照模型、视图、控制器来划分 M:Model,模型层,指工程中的 JavaBean,作用是处理数据。JavaBean 分为两类: 一类称为实体类 Bean:专门存储业务数据的,如 Student、User 等 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。 V:View,视图层,指工程中的 html 或 jsp 等页面,作用是与用户进行交互,展示数据 C:Controller,控制层,指工程中的 servlet,作用是接收请求和响应浏览器 MVC 的工作流程:用户通过视图层发送请求到服务器,在服务器中请求被 Controller 接收,Controller 调用相应的 Model 层处理请求,处理完毕将结果返回到 Controller,Controller 再根据请求处理的结果找到相应的 View 视图,渲染数据后最终响应给浏览器 2. 什么是 SpringMVC SpringMVC 是 Spring 的一个后续产品,是 Spring 的一个子项目 SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。 注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台 servlet 3. SpringMVC 的特点 Spring 家族原生产品,与 IOC 容器等基础设施无缝对接 基于原生的 Servlet,通过了功能强大的前端控制器 DispatcherServlet,对请求和响应进行统一处理 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案 代码清新简洁,大幅度提升开发效率 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可 性能卓著,尤其适合现代大型、超大型互联网项目要求 二、SpringMVC 入门案例 1. 创建 Maven 项目 创建 Maven web 项目 打包方式是 war 完善目录结构 目录结构如下: 2. 添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xszx</groupId> <artifactId>springmvc_20240620</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!-- SpringMVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.1</version> </dependency> <!-- 日志 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- ServletAPI --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> </plugin> </plugins> </build> </project> 注:由于 Maven 的传递性,我们不必将所有需要的包全部配置依赖,而是配置最顶端的依赖,其他靠传递性导入。 3. 配置 web.xml 注册 SpringMVC 的前端控制器 DispatcherServlet。 <?xml version="1.0" encoding="UTF-8"?> <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_4_0.xsd" version="4.0"> <!-- 配置SpringMVC的前端控制器,对浏览器发起的请求进行统一处理 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 通过初始化参数指定SpringMVC配置文件的路径和名称 --> <init-param> <!-- 参数名contextConfigLocation是固定值 --> <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> <!-- / 所匹配的请求可以是/login或.html或.js或.css方式的请求路径 但是/不能匹配.jsp请求路径的请求 --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 注: <url-pattern> 标签中使用 / 和 /* 的区别: / 所匹配的请求可以是 /login 或 .html 或 .js 或 .css 方式的请求路径,但是 / 不能匹配 .jsp 请求路径的请求 因此就可以避免在访问 jsp 页面时,该请求被 DispatcherServlet 处理,从而找不到相应的页面 /* 则能够匹配所有请求,例如在使用过滤器时,若需要对所有请求进行过滤,就需要使用 \* 的写法 4. 编写 SpringMVC 的配置文件 <?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 配置扫描 --> <context:component-scan base-package="com.xszx.controller"></context:component-scan> <!-- 配置注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> </beans> 5. 编写 controller 层代码 package com.xszx.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller // 将该类交给SpringMVC容器管理 @RequestMapping("/hello") // 请求映射路径 public class HelloController { @RequestMapping("/say") // 请求映射路径 public String say(){ System.out.println("say..."); return "/abc.jsp"; // 转发到根目录底下的abc.jsp页面 } } 6. 编写 abc.jsp 页面 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>我是abc.jsp页面中的内容!</h1> </body> </html> 原文链接:https://blog.csdn.net/bear_309/article/details/141996730
-
Spring是IOC和AOP的容器框架,SpringMVC是基于Spring功能之上添加的Web框架,想用SpringMVC必须先依赖Spring。简单点的话可以将SpringMVC类比于Struts。Spring是IOC和AOP的容器框架,SpringMVC是基于Spring功能之上添加的Web框架,想用SpringMVC必须先依赖Spring。Spring可以说是一个管理bean的容器,也可以说是包括很多开源项目的总称,spring mvc是其中一个开源项目,所以简单走个流程的话,http请求一到,由容器(如:tomact)解析http搞成一个request,通过映射关系(路径,方法,参数啊)被spring mvc一个分发器去找到可以处理这个请求的bean,那tomcat里面就由spring管理bean的一个池子(bean容器)里面找到,处理完了就把响应返回回去。SpringMVC是一个MVC模式的WEB开发框架;Spring是一个通用解决方案, 最大的用处就是通过Ioc/AOP解耦, 降低软件复杂性, 所以Spring可以结合SpringMVC等很多其他解决方案一起使用, 不仅仅只适用于WEB开发SSH:SSH 为 struts+spring+hibernate 的一个集成框架,是目前较流行的一种JAVA Web应用程序开源框架。 Struts Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。由于Struts能充分满足应用开发的需求,简单易用,敏捷迅速,在过去的一年中颇受关注。Struts把Servlet、JSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,所以说Struts是一个非常不错的应用框架。 Spring Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。然而,这仅仅是完整图景中的一部分:Spring在使用IOC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。 Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA或者JDBC事务提供一个一致的编程模型。Spring提供了一个用标准Java语言编写的AOP框架,它给POJOs提供了声明式的事务管理和其他企业事务–如果你需要–还能实现你自己的aspects。这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。 Hibernate Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。原文链接:https://devpress.csdn.net/cloudnative/66d30095a1ed2f4c8540020b.html
-
SpringMVC作为MVC框架,与Struts 2 有着异曲同工之处,首先对比一下SpringMVC与Struts2的不同之处: 1. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。 2. 性能:spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而 struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。 3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。 4. 设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。 5. intercepter的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。 6. 另外,spring3 mvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便,只需一个注解@ResponseBody ———————————————— 原文链接:https://blog.csdn.net/SpringFileld/article/details/38414929
-
MVC MVC:MVC是一种设计模式 MVC的原理图: 分析: M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity) V-View 视图(做界面的展示 jsp,html……) C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面) 2、SpringMVC SpringMVC是一个MVC的开源框架 SpringMVC=Struts2+Spring , SpringMVC就相当于是Struts2加上Sring的整合 SpringMVC是Spring的一个后续产品,其实就是Spring在原有基础上,又提供了web应用的MVC模块,可以简单的把SpringMVC理解为是Spring的一个模块 (类似AOP,IOC这样的模块),网络上经常会说SpringMVC和Spring无缝集成,其实SpringMVC就是Spring的一个子模块,所以根本不需要同Spring进行整合。 SpringMVC的原理图: 看到这个图大家可能会有很多的疑惑,现在我们来看一下这个图的步骤:(可以对比MVC的原理图进行理解) 第一步: 用户发起请求到前端控制器(DispatcherServlet) 第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找 第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain) 第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler) 第五步:处理器适配器去执行Handler 第六步:Handler执行完给处理器适配器返回ModelAndView 第七步:处理器适配器向前端控制器返回ModelAndView 第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析 第九步:视图解析器像前端控制器返回View 第十步:前端控制器对视图进行渲染 第十一步:前端控制器向用户响应结果 看到这些步骤我相信大家很感觉非常的乱,这是正常的,但是这里主要是要大家理解springMVC中的几个组件: 前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。 处理器映射器(HandlerMapping):根据URL去查找处理器 处理器(Handler):(需要程序员去写代码处理逻辑的) 处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用) 视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面 原文链接:https://blog.csdn.net/rzrenyu/article/details/78513595
-
SpringMVC 什么是MVC模型 MVC全称Model View Controller,是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分: Model(模型):指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中,JavaBean对象,业务模型等都属于Model。 View(视图):用于展示模型中的数据的,一般为jsp或html文件。 Controller(控制器):是应用程序中处理用户交互的部分。接受视图提出的请求,将数据交给模型处理,并将处理后的结果交给视图显示。 SpringMVC SpringMVC是一个基于MVC模式的轻量级Web框架,是Spring框架的一个模块,和Spring可以直接整合使用,我们使用的版本是Spring6,所以JDK需要17以上。SpringMVC代替了Servlet技术,它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。 案例 使用maven创建web项目,补齐包结构。 引入相关依赖 <dependencies> <!-- Spring核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.11</version> </dependency> <!-- SpringMVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>6.0.11</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.0.11</version> </dependency> <!-- Servlet --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <!-- JSP --> <dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency> </dependencies> 在web.xml中配置前端控制器DispatcherServlet。 <web-app> <display-name>Archetype Created Web Application</display-name> <!--SpringMVC前端控制器,本质是一个Servlet,接收所有请求,在容器启动时就会加载--> <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> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 4.编写SpringMVC核心配置文件springmvc.xml,该文件和Spring配置文件写法一样。 <?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"> <!-- 扫描包 --> <context:component-scan base-package="com.jjy"/> <!-- 开启SpringMVC注解的支持 --> <mvc:annotation-driven/> </beans> 5.编写控制器 @Controller public class MyController1 { // 该方法的访问路径是/c1/hello1 @RequestMapping("/c1/hello1") public void helloMVC(){ System.out.println("hello SpringMVC!"); } } 配置tomcat10启动项目,访问 http://localhost:8080/c1/hello1 SpringMVC执行流程 SpringMVC的组件 DispatcherServlet:前端控制器,接受所有请求,调用其他组件。 HandlerMapping:处理器映射器,根据配置找到方法的执行链。 HandlerAdapter:处理器适配器,根据方法类型找到对应的处理器。 ViewResolver:视图解析器,找到指定视图。 组件的工作流程 客户端将请求发送给前端控制器。 前端控制器将请求发送给处理器映射器,处理器映射器根据路径找到方法的执行链,返回给前端控制器。 前端控制器将方法的执行链发送给处理器适配器,处理器适配器根据方法类型找到对应的处理器。 处理器执行方法,将结果返回给前端控制器。 前端控制器将结果发送给视图解析器,视图解析器找到视图文件位置。 视图渲染数据并将结果显示到客户端。 SpringMVC封装参数 简单数据类型 在Servlet中我们通过request.getParameter(name)获取请求参数。该方式存在两个问题: 请求参数较多时会出现代码冗余。 与容器紧耦合。 而SpringMVC支持参数注入的方式用于获取请求数据,即将请求参数直接封装到方法的参数当中。用法如下: 编写控制器方法 // 封装为简单数据类型类型参数 @RequestMapping("/c1/param1") public void simpleParam(String username,int age){ System.out.println(username); System.out.println(age); 访问该方法时,请求参数名和方法参数名相同,即可完成自动封装。 http://localhost:8080/c1/param1?username=bz&age=10 简单对象 SpringMVC支持将参数直接封装为对象,写法如下: 编写实体类 public class Student { private int id; private String name; private String sex; // 省略getter/setter/tostring } 编写控制器方法 // 封装为简单对象类型参数 @RequestMapping("/c1/param2") public void objParam(Student student){ System.out.println(student); } 访问该方法时,请求参数名和对象参数的属性名相同,即可完成自动封装。 http://localhost:8080/c1/param2?id=1&name=bz&sex=female 关联对象 SpringMVC还可以将请求参数封装为关联对象,即对象的属性也是一个对象。写法如下: 编写实体类 public class Student { private int id; private String name; private String sex; private Address address; // 地址对象 // 省略getter/setter/tostring } public class Address { private String info; //地址信息 private String postcode; //邮编 // 省略getter/setter/tostring } 编写控制器方法 // 获取关联对象类型参数 @RequestMapping("/c1/param3") public void objParam2(Student student){ System.out.println(student); } 访问该方法时,请求参数名和方法参数的属性名相同,即可完成自动封装。 http://localhost:8080/c1/param3?id=1&name=bz&sex=female&address.info=beijing&address.postcode=030000 我们也可以使用表单发送带有参数的请求: <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>表单提交</title> </head> <body> <form action="/c1/param3" method="post"> id:<input name="id"> 姓名:<input name="name"> 性别:<input name="sex"> 住址:<input name="address.info"> 邮编:<input name="address.postcode"> <input type="submit"> </form> </body> </html> 原文链接:https://blog.csdn.net/m0_74436895/article/details/142927915
-
一、SpringMVC简介 1、什么是MVC MVC是一种软件架构模式(是一种软件架构设计思想,不止Java开发中用到,其它语言也需要用到),它将应用分为三块: M:Model(模型),负责业务处理及数据的收集 V:View(视图),负责数据的展示 C:Controller(控制器),负责调度。它是一个调度中心,它来决定什么时候调用Model来处理业务,什么时候调用View视图来展示数据 MVC架构模式的描述:前端浏览器发送请求给web服务器,web服务器中的Controller接收到用户的请求,Controller负责将前端提交的数据进行封装,然后Controller调用Model来处理业务,当Model处理完业务后会返回处理之后的数据给Controller,Controller再调用View来完成数据的展示,最终将结果响应给浏览器,浏览器进行渲染展示页面。 2、MVC架构模式与三层模型的区别 什么是三层模型 三层模型就是由Controller控制器和View视图组成的表现层,将Model数据模型拆封为业务层和与数据库交互的持久层 MVC架构模式与三层模型的区别? MVC和三层模型都采用了分层结构来设计应用程序,都是降低耦合度,提高扩展力,提高组件复用性 区别在于他们的关注点不同 三层模型更加关注业务逻辑组件的划分 MVC架构模式关注的是整个应用程序的层次关系和分离思想 现代的开发方式大部分都是MVC架构模式结合三层模型一起用 3、什么是SpringMVC SpringMVC是一个实现了MVC架构模式的Web框架,底层基于Servlet实现 SpringMVC已经将MVC架构模式实现了,因此只要我们是基于SpringMVC框架写代码 Spring框架中有一个子项目叫做Spring Web,Spring Web子项目当中包含很多模块 Spring MVC Spring WebFlux Spring Web Services Spring Web Flow Spring WebSocket Spring Web Services Client Spring架构图如下,其中Web中的servlet指的就是Spring MVC 二、HelloWorld程序 1、pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xc</groupId> <artifactId>springmvc-xml</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!--springmvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.1</version> </dependency> <!--servletAPI--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--spring5和thymeleaf整合--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.0.11.RELEASE</version> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project> 2、springmvc.xml 组件扫描。spring扫描这个包中的类,将这个包中的类实例化并纳入IoC容器的管理 视图解析器。视图解析器(View Resolver)的作用主要是将Controller方法返回的逻辑视图名称解析成实际的视图对象。视图解析器将解析出的视图对象返回给DispatcherServlet,并最终由DispatcherServlet将该视图对象转化为响应结果,呈现给用户 <?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--组件扫描--> <context:component-scan base-package="com.xc.controller"/> <!--视图解析器--> <bean id="thymeleafViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <!--作用于视图渲染的过程中,可以设置视图渲染后输出时采用的编码字符集--> <property name="characterEncoding" value="UTF-8"/> <!--如果配置多个视图解析器,它来决定优先使用哪个视图解析器,它的值越小优先级越高--> <property name="order" value="1"/> <!--当 ThymeleafViewResolver 渲染模板时,会使用该模板引擎来解析、编译和渲染模板--> <property name="templateEngine"> <bean class="org.thymeleaf.spring5.SpringTemplateEngine"> <!--用于指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器负责根据模板位置、模板资源名称、文件编码等信息,加载模板并对其进行解析--> <property name="templateResolver"> <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <!--设置模板文件的位置(前缀)--> <property name="prefix" value="/WEB-INF/templates/"/> <!--设置模板文件后缀(后缀),Thymeleaf文件扩展名不一定是html,也可以是其他,例如txt,大部分都是html--> <property name="suffix" value=".html"/> <!--设置模板类型,例如:HTML,TEXT,JAVASCRIPT,CSS等--> <property name="templateMode" value="HTML"/> <!--用于模板文件在读取和解析过程中采用的编码字符集--> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean> </beans> 3、配置web.xml文件 Spring MVC是一个web框架,在javaweb中谁来负责接收请求,处理请求,以及响应呢?当然是Servlet 在SpringMVC框架中已经为我们写好了一个Servlet,它的名字叫做:DispatcherServlet,我们称其为前端控制器 既然是Servlet,那么它就需要在web.xml文件中进行配置: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <!--配置前端控制器--> <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:springmvc.xml</param-value> </init-param> <!--为了提高用户的第一次访问效率,建议在web服务器启动时初始化前端控制器--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- /* 表示任何一个请求都交给DispatcherServlet来处理 --> <!-- / 表示当请求不是xx.jsp的时候,DispatcherServlet来负责处理本次请求--> <!-- jsp本质就是Servlet,因此如果请求是jsp的话,应该走它自己的Servlet,而不应该走DispatcherServlet --> <!-- 因此我们的 url-pattern 使用 / --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> DispatcherServlet是SpringMVC框架为我们提供的最核心的类,它是整个SpringMVC框架的前端控制器,负责接收HTTP请求、将请求路由到处理程序、处理响应信息,最终将响应返回给客户端。 接收客户端的HTTP请求:DispatcherServlet监听来自Web浏览器的HTTP请求,Tomcat已经将请求数据解析为Request对象 处理请求的URL:DispatcherServlet将请求的URL与处理程序进行匹配,确定要调用哪个控制器(Controller)来处理此请求 调用相应的控制器:DispatcherServlet将请求发送给找到的控制器处理,控制器将执行业务逻辑,然后返回一个模型对象(Model) 渲染视图:DispatcherServlet将调用视图引擎,将模型对象呈现为用户可以查看的HTML页面 返回响应给客户端:DispatcherServlet将为用户生成的响应发送回浏览器,响应可以包括表单、JSON、XML、HTML以及其它类型的数据 4、html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> hello world </body> </html> 原文链接:https://xuchang.blog.csdn.net/article/details/139730755
-
一.spring是什么? Spring是一个轻量级的IoC/DI和AOP容器的开源框架 二.spring的优点 1.Spring 能帮我们低侵入/低耦合地根据配置文件创建及组装对象之间的依赖关系 //解耦 2.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制等 //提高代码重用性 3.Spring 能非常简单的且强大的声明式事务管理 //使用xml或注解的方法,底层用到动态代理 4.Spring 提供了与第三方数据访问框架(如JPA)无缝集成,且自己也提供了一套JDBC模板来方便数据库访问 5.Spring 提供与第三方Web框架无缝集成,且自己也提供了一套 SpringMVC 框架,来方便 Web 层搭建 三.Spring Ioc/DI Ioc: 1.控制反转,是一种设计思想,就是原本在程序中需要手动创建对象的权利,交给spring框架管理 2.Ioc容器是实现Ioc的载体,Ioc容器实际上就是个Map(key,value),map中存放各种对象 3.Ioc容器就像一个工厂一样,当我们需要创建一个对象时,只需要配置好配置文件或贴注解即可, 完全不用考虑对象时如何被创建出来的 4.将对象相互依赖的关系交给ioc容器管理,这样可以很大程度简化应用开发 5.使用Ioc的话,我们只需要配置好,在需要的地方引用就好,这大大的增加了项目的可维护性且降低了开发难度 DI: 1.指 Spring 创建对象的过程中,将对象依赖属性通过配置设值给该对象 2.就是给对象的属性设置属性值 //Ioc创建对象,Di给属性设置值 四.Spring AOP Aop:面向切面编程 1.能够将那些与业务无关,却为业务模块所共同调用的逻辑和责任封装起来, 便于减少重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性 2.Spring Aop就是基于动态代理的,当要代理的对象实现了某个接口,就会使用Jdk动态代理 3.如果没有某个接口,就是使用cglib生成一个被代理对象的子类作为代理 //使用aop之后我们可以把一些通用的功能抽象出来,在需要的时候自己使用即可,这样大大的简化了代码量 //常用的aop的有 事务处理 日志管理 权限控制 五.Spring 中的 bean 的作用域 //作用域:在 Spring 容器中是指其创建的 bean 对象相对于其他 bean 对象的请求可见范围 singleton : 唯一bean 实例,Spring 中的 bean 默认都是单例的。 prototype : 多例,每次请求都会创建一个新的 bean 实例,多例只会初始化和销毁,不会存到容器中进行管理 request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。 session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。 /*使用总结:在开发中主要使用 scope="singleton"。对于 Struts1 的 Action 使用 request, Struts2 中的 Action 使 用 prototype 类型,其他使用 singleton,即不配置 六. SpringMVC工作原理 1、客户端发出http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet. 2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器Controller(Handler)。 3、DispatclierServlet 根据 HandlerMapping 找到对应的Handler,处理权交给Handler ( Handler将具体的处理进行封装),再由具体的处理适配器 HandlerAdapter对Handler进行具体的调用。 5、Handler对数据处理完成以后将返回一个ModeAndView对象给DispatcherServlet. 6、Handler返回的ModelAndView只是一个逻辑视图并不是一个正式的视图,dspatcherSevlet通过ViewResolver将邀辑视图转化为真正的视图view(这句话简单的就是返回一个要返回的页面的相对路径,通过试图解析器转换成具体那个页面)。 7、DispatcherServlet通过model解析出ModeAndView中的参数进行解析最终展现出完整的view并返回给客户端 //简化 1. 客户端(浏览器)发送请求到dispatcherServlet前端控制器 2. DispatcherServlet 根据请求信息调用 HandlerMapping ,解析请求对应的 Handler 3. 解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理 4. HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑 5. 处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View 6. ViewResolver 会根据逻辑 View 查找实际的 View 7. DispaterServlet 把返回的 Model 传给 View (视图渲染) 8. 把 View 返回给请求者(浏览器) 七.Spring 管理事务的方式 1. 编程式事务,在代码中硬编码。(不推荐使用) 2. 声明式事务,在配置文件中配置(推荐使用) //声明式事务又分为两种: 1. 基于XML的声明式事务 2. 基于注解的声明式事务 八.Spring 框架中用到的设计模式 1.工厂设计模式 : Spring使用工厂模式通过 BeanFactory 、ApplicationContext 创建 bean 对象 2.代理设计模式 : Spring AOP 功能的实现 3.单例设计模式 : Spring 中的 Bean 默认都是单例的 4.模板方法模式 : Spring 中 jdbcTemplate 、hibernateTemplate 等以Template 结尾的对数据库操作类, 它们就使用到了模板模式 5.包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库, 这种模式让我们可以根据客户的需求能够动态切换不同的数据源。 6.观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。 7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,spring MVC中也是用到了适配器模式适配 Controller 九.小结 1.spring的核心思想Ioc/DI和aop 2.使用spring不用处理对象之间的依赖关系,能够大大的降低我们代码的耦合度,增加项目的可维护性 3.使用spring我们不用关心对象是怎么创建的,只需要配置好配置文件或贴注解即可,很大程度简化应用开发 4.使用spring能够将与业务无关的代码,,却为业务模块所共同调用的逻辑使用aop将其抽象出来,提高代码可重用性 5.spring提供与第三方web框架无缝集成,并且自己也提供一套SpringMVC框架 使用spring需要配置大量的xml文件,其实也是有点头疼的,但是springboot可以帮我们完美的解决这些问题 原文连接:https://devpress.csdn.net/cloudnative/66d41b140bfad230b8b2e176.html
-
spring是什么? pring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 Spring项目出发点: 目的:提供一种贯穿始终的解决方面,将各种专用框架整合成一个连贯的整体框架,简化企业级应用的开发(有点像粘合剂) 鼓励最佳实践: 例如spring将“针对接口编程”的成本降到了最小 非侵入性: 应用对象尽量避免依赖框架,IoC和AOP是避免依赖的关键技术 统一配置: 好的框架应该让应用配置灵活且统一 易于测试: 使单元测试尽可能简单 可扩展: 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 1.核心容器(Spring Core) 是Spring的核心容器,提供了Spring框架的基本功能; 此模块包含 的BeanFactory类是Spring的核心类,负责产生和管理Bean,是工程模式的实现; 采用Factory(工厂模式)实现了IOC(控制反转)将应用的配置和依赖性规范与实际的应用程序代码分开; Spring以bean的方式组织和管理Java应用中发各个组件及其关系。 2.应用上下文(Spring Context) 是一个配置文件,向Spring框架提供上下文信息; SpringContext模块继承BeanFactory类,添加了事件处理、国际化、资源装载、透明装载、以及数据校验等功能; 还提供了框架式的Bean的访问方式和企业级的功能,如JNDI访问,支持EJB、远程调用、继承模板框架、Email和定时任务调度等; 3.面向切面编程(Spring AOP) Spring AOP直接将面向方面的编程功能集成到了Spring框架中,所以很容易的使Spring框架管理的任何对象支持AOP(Spring集成了所有AOP功能。通过事务管理可以使任意Spring管理的对象AOP化); Spring AOP为基于Spring的应用程序中的对象提供了事务管理服务; 通过使用Spring AOP,不用依赖EJB组件,就可以将声明性事务管集成到应用程序中。 4.JDBC和DAO模块(Spring DAO) DAO(DataAccessObject)模式思想是将业务逻辑代码与数据库交互代码分离,降低两者耦合; 通过DAO模式可以使结构变得更为清晰,代码更为简; DAO模块中的JDBC的抽象层,提供了有意义的异常层次结构,用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息; 异常层次结构简化了数据库厂商的异常错误(不再从SQLException继承大批代码),极大的降低了需要编写的代码数量,并且提供了对声明式事务和编程式事务的支持; 5.对象实体映射(Spring ORM) SpringORM模块提供了对现有ORM框架的支持; 提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有的这些都遵从Spring的通用事务和DAO异常层次结构; 注意这里Spring是提供各类的接口(support),目前比较流行的下层数据库封闭映射框架,如mybatis,Hibernate等; 6.Web模块(Spring Web) 此模块建立在SpringContext基础之上,提供了Servlet监听器的Context和Web应用的上下文; 对现有的Web框架,如JSF、Tapestry、Structs等提供了集成; SpringWeb模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 7.MVC模块(Spring Web MVC) SpringWebMVC模块建立在Spring核心功能之上,拥有Spring框架的所有特性,能够适应多种多视图、模板技术、国际化和验证服务,实现控制逻辑和业务逻辑的清晰分离; 通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI; IOC 控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。 IoC还有一个另外的名字:“依赖注入 (DI=Dependency Injection)” ,即由容器动态的将某种依赖关系注入到组件之中。 示例 创建工程---创建maven的web项目 pom文件 <properties> <spring.version>5.3.6</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies> spring配置文件 创建beans.xml(名称可以任意)配置文件,文件内容如下 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> </beans> 示例代码 1.代码 /** * 第一个Spring,输出"Hello,Spring!"。 */ public class HelloSpring { // 定义who属性,该属性的值将通过Spring框架进行设置 private String who = null; public HelloSpring(){ } public HelloSpring(String who){ this.who = who; } /** * 定义打印方法,输出一句完整的问候。 */ public void print() { System.out.println("Hello," + who + "!"); } public String getWho() { return who; } public void setWho(String who) { this.who = who; } } 2.beans.xml配置文件中配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id要唯一,class:指定类,不能是接口或者抽象类;默认情况,spring调用class指定类中不带参的构造方法 --> <bean id="helloSpring" class="com.zking.springdemo.HelloSpring"> <!-- 调用class类中的set+name方法,传value指定的值 --> <property name="who" value="spring"/> </bean> </beans> 配置文件说明: id:在容器中查找Bean的id(唯一、且不能以/开头) class:bean的完整类名 scope:(singleton|prototype)默认是singleton singleton: 单例模式, 在每个Spring IoC容器中一个bean定义对应一个对象实例;spring在容器启动时,创建实例 ; prototype: 原型模式/多例模式, 一个bean定义对应多个对象实例;在用户使用bean对象时才创建 3.通过Spring的ApplicationContex 获取Bean public class HelloSpringTest { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); HelloSpring h1 = (HelloSpring)ctx.getBean("helloSpring"); h1.print(); } } 注入方式 设值注入--通过调用对应的set方法注入 <bean id="helloSpring" class="com.zking.springdemo.HelloSpring"> <property name="who" value="spring"/> </bean> 构造注入 <bean id="helloSpring2" class="com.zking.springdemo.HelloSpring"> <constructor-arg value="spring"></constructor-arg> </bean> p注入--在beans.xml文件中额外引入p命名空间 xmlns:p="http://www.springframework.org/schema/p" p注入--beans.xml中bean的配置 <bean id="helloSpring3" class="com.zking.springdemo.HelloSpring" p:who="spring"> </bean> 复杂属性的配置 依赖bean对象(重点) <bean id="userDao" class="com.zking.springdemo.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.zking.springdemo.service.impl.UserServiceImpl"> <!--ref="userDao"依赖spring容器中的id为userDao的bean对象--> <property name="userDao" ref="userDao"></property> </bean> <bean id="userService2" class="com.zking.springdemo.service.impl.UserServiceImpl" p:userDao-ref="userDao"/> List或数组 声明属性 private String[] array; private List list; 配置文件 <property name="array"> <array> <value>足球</value> <value>蓝球</value> </array> </property> <property name="list"> <list> <value>jack</value> <value>rose</value> </list> </property> Map private Map map; 配置文件 <property name="map"> <map> <entry key="en" value="english"></entry> <entry key="ch" value="chinese"></entry> </map> </property> Properties private Properties prop; 配置文件 <property name="props"> <props> <prop key="en">english</prop> <prop key="ch">chinese</prop> </props> </property> 多配置文件 系统一般会被分成多个模块,可以为每个模块配置一个配置文件,便于管理,在版本控制软件中也可以减少冲突 beans.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="spring_ioc.xml"/> </beans> spring_ioc.xml配置文件 <?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id要唯一,class:指定类,不能是接口或者抽象类;默认情况,spring调用class指定类中不带参的构造方法 --> <bean id="helloSpring" class="com.zking.springdemo.HelloSpring"> <!-- 调用class类中的set+name方法,传value指定的值 --> <property name="who" value="spring"/> </bean> <bean id="helloSpring2" class="com.zking.springdemo.HelloSpring"> <constructor-arg value="spring"></constructor-arg> </bean> <bean id="helloSpring3" class="com.zking.springdemo.HelloSpring" p:who="spring"></bean> <bean id="userDao" class="com.zking.springdemo.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.zking.springdemo.service.impl.UserServiceImpl"> <!--ref="userDao"依赖spring容器中的id为userDao的bean对象--> <property name="dao" ref="userDao"></property> </bean> <bean id="userService2" class="com.zking.springdemo.service.impl.UserServiceImpl" p:dao-ref="userDao"/> <!--复杂属性的配置--> <bean id="testBean" class="com.zking.springdemo.TestBean"> <property name="list"> <list> <value>jack</value> <value>rose</value> </list> </property> <property name="array"> <array> <value>足球</value> <value>蓝球</value> </array> </property> <property name="map"> <map> <entry key="en" value="english"></entry> <entry key="ch" value="chinese"></entry> </map> </property> <property name="props"> <props> <prop key="en">english</prop> <prop key="ch">chinese</prop> </props> </property> </bean> </beans> ———————————————— 原文链接:https://blog.csdn.net/weixin_59196705/article/details/123842794
-
1. Spring 的介绍 1.1 Spring是什么? Spring: Spring Framework(Spring 框架)Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的 应⽤程序开发起来更简单。用一句简单的话来说,Spring就是一个拥有众多工具的ioc容器。 1.2 什么是容器,什么是IOC 容器? 容器: ⽤来容纳某种物品的(基本)装置 在我们学习Java基础的时候,就接触过一些关于数据结构的容器,他们都是根据一定的组织结构来组织众多的数据,例如:Map,List,Stack,Queue... 它们是组织数据的容器。 Spring也是一个容器。是一个IOC容器。 IOC(Inversion of control) 翻译为控制反转,IOC不是一种技术而是一种设计思想,其实这里的控制反转指的是,我们在创建对象的时候,对象的创建控制权交给了外部,在使用对象时,在程序中不要自己使用new创建对象,转换成为由外部主动提供对象。 ioc容器用于充当ioc思想中的外部 IOC容器负责对象的创建,初始化等一系列的工作,被创建或者被管理的对象在IOC容器中统称为Bean 在传统程序设计,我们直接在对象内部通过new进行创建对象。如果我们在A类中需要一个B类中的对象,那按照以前我们在A类中就可以直接new出一个B类型的对象,那么此时我们不妨想一下,如果这个在A类中需要B类对象的时候,直接new 出B类型对象的思想,放到复杂的项目中,那么就有可能程序的调用链就会很长。例如:在A类中new一个B类型的对象,在B类中new一个C类型的对象,在C类中new一个D类型的对象… 那么如果此时的程序需求一旦有了变化,那么就会牵一发而动全身,这些类中的代码都需要改动。传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象 那么既然Spring是一个拥有众多工具的ioc容器,那么Spring这个容器就有控制反转的思想,那么是谁控制谁,又控制了什么,为什么在Spring中需要控制反转。 是谁控制谁?控制了什么? 其实Spring的ioc容器,控制了在类中创建和管理对象的权限。也就是ioc容器控制了在该类中new出其他类型的对象。在传统的程序设计中,如果要想在A类中得到B类型的对象,那么就会直接new出B类型的对象,但是在这样的操作在后期维护代码的时候是非常费劲的。只要在A类中依赖的B对象的成员属性如果需要改动,那么整个代码就要进行大规模的更改。 但是如果使用的ioc容器,创建和管理对象的权限就交给了ioc容器。把B对象传给ioc容器,当我们在A类中需要B对象的时候,只要引用Spring ioc 容器中的B对象即可。 为什么Spring需要控制反转,在Spring中又控制反转了什么? 因为在传统的程序设计中,如果要想在A类中得到B类型的对象,那么就会直接new出B类型的对象,但是在这样的操作在后期维护代码的时候是非常费劲的。只要在A类中依赖的B对象的成员属性如果需要改动,那么整个代码就要进行大规模的更改。,在ioc容器中创建和管理对象,在容器中创建对象A,并且有该容器管理A对象。当在类A中需要对象B的时候,那么此时就不需要在类A中创建出一个对象B,此时对象A中的引用就可以被动的接受ioc容器中传来的对象B. spring ioc 优点: 成功实现了解耦, 耦合是指:两个或两个以上对象存在依赖,当一方修改之后会影响另一方,那么就说这些对象间存在耦合。我们知道较好的代码应该是 "高内聚,低耦合 "的。这里把创建和管理对象的权限交给了ioc容器。 1.3 Spring IOC 的核心理念 我们目前知道了Spring是一个拥有众多工具的IOC容器,那么怎样理解这就话呢? 所谓的容器:最大的用处就是把某物添加到容器中,再从容器中把某物取出来,这里的spring ioc容器也是一样的。IOC的核心:就是把bean添加到ioc容器中,然后在从ioc容器中把bean对象取出来。 其实Spring ioc 是一种具体的思想。它不是一种具体的行为措施。 将对象存放到容器中的好处:将对象存储在 IoC 容器相当于 将以后可能⽤的所有⼯具制作好都放到仓库中,需要的时候直接取就⾏了,⽤完再把它放回到仓库。 ⽽ new 对象的⽅式相当于,每次需要⼯具 了,才现做,⽤完就扔掉了也不会保存,下次再⽤的时候还得重新做,这就是 IoC 容器和普通程序开 发的区别。 1.4 什么是DI? DI (Dependency Injection) “依赖注⼊” 那么什么又是“依赖注入”? 在ioc容器中创建bean 和 bean之间依赖关系的整个过程 ,使用对象的时候不仅可以直接从ioc容器获取,并且获取到的bean已经绑定了所有的依赖关系。 所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。所以, 赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容 器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。 1.5 经典面试题:说一说 IOC 和 DI 的区别 依赖注入不是一种设计实现,而是一种具体的技术,它是在 IoC 容器运行期间,动态地将某个依赖对象注入到当前对象的技术就叫做DI(依赖注入)。 IoC 和 DI 都是 Spring 框架中的重要概念,它们都是用来实现对象解耦的,其中 IoC(控制反转)是一种设计思想,而 DI(依赖注入)是一种具体的实现手段。 2. 手把手创建一个Spring项目 第一步:先创建一个maven 项目 第二步:在spring_test项目中配置pom.xml文件,因为我们要基于maven创建一个Spring项目,所以要引入一个spring-context(Spring上下文)依赖,还有要把bean对象添加到spring中,就需要引入spring_beans依赖我们也可以在maven的官网去找。 这里就是spring-context和spring-beans依赖,可以直接添加到pom.xml文件中,加入之后在idea的右边栏maven栏中点击重新加载按钮。 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <ersion>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.3.RELEASE</version> </dependency> </dependencies> 到此我们的第一个spring项目基本就创建完成了,但是我们还要往spring ioc容器中添加对象。 往spring ioc 容器中添加依赖对象: 在 src --> main --> resource中添加配置,在resource下创建一个文件,这个文件名可以随便起,但是在这里还是简明知意的好,在这里我们创建一个spring-config.xml文件,并且在这个.xml文件中写入如下内容。 <?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:content="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> </beans> 此时还没有引入bean对象到ioc 容器中。那么就要在这个spring-config.xml中写入一下信息,即就把bean对象添加到了spring ioc容器中了。 如果要想再spring ioc 容器中添加对象,com.model包下先创建一个User类,在这个类中创建一个sayHi()方法 package com.model; public class User { public void sayHi(){ System.out.println("say hi"); } } 那么就在<bean> 标签中添加对象即可,其中在<bean>标签中的属性有 id 其中 这个 id表示的是在从spring ioc 容器中得到相应对象的时候的beanName,就是通过这个beanName就可以找到spring ioc 容器中找到这个对象 还有一个属性 class 表示的是这个spring ioc 容器中的user对象所在的类,就是一个具体的类的路径 <beans> <bean id = "user" class="com.model.User"></bean> </beans> 从spring ioc 容器中得到对象 创建一个App类,在该类中得到存入spring ioc 容器中的user对象,那么此时就不得不介绍一下spring的上下文对象了 spring上下文即是Spring容器抽象的一种实现;而我们常见的ApplicationContext本质上说就是一个维护Bean定义以及对象之间协作关系的高级接口 一种是不常用的BeanFactory,这是最简单的容器,只能提供基本的DI功能;还有一种就是继承了BeanFactory后派生而来的应用上下文,其抽象接口也就是我们上面提到的的ApplicationContext,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是应用上下文实例对象最常见的应用场景。有了上下文对象,我们就能向容器注册需要Spring管理的对象了。 ApplicationContext 和 BeanFactory 的区别: 相同点: 都可以实现从容器中获取Bean,都提供了getBean()方法。 不同点: ApplicationContext属于BeanFactory的子类,而ApplicationContext除了拥有BeanFactory 的所有功能之外,所提供了更多的方法实现,比如对国际化的支持,资源访问的支持,以及事件和传播等方面的支持 从性能方面来说,二者是不同的,BeanFactory是按需加载Bean,ApplicationContext是饿汉模式,在创建时会将所有的Bean都加载起来,以备以后使用。 如果使用BeanFactory作为spring的上下文对象,在加载spring-config配置文件的时候,是按需加载的,也就是说我现在在这个类中需要使用到spring ioc 容器所管理的某个对象,那么此时只把我要的Bean对象进行加载,这种就属于懒汉模式,你要的时候,我才给你拿。但是每次加载spring-config.xml文件中的某个对象到spring ioc容器会消耗一部分时间,相比,AppliactionContext作为spring的上下文对象,在spring ioc 容器加载时,就会把spring-config.xml文件中的全部Bean对象加载进来。如果在以后从spring ioc 容器中获取对象的时候,直接获取即可,无需加载,这样只是第一次加载spring-config.xml文件的时候,时间会消耗长一点。所以说在计算机中,懒汉模式不一定比饿汉模式好 在model包下,在创建出一个User2类,并且把这个user2对象,添加到 spring ioc 容器中。 package com.model; public class User2 { //在spring ioc 容器加载user2 对象到 spring ioc 容器的时候就会调用User2类中的构造方法 public User2(){ System.out.println("加载User2类"); } public void sayHi(){ System.out.println("hello world"); } } //把user2对象添加到spring ioc 容器中 <bean id="user2" class="com.model.User2"></bean> 在User类中,添加一个无参的构造方法 package com.model; public class User { public User(){ System.out.println("加载User类"); } public void sayHi(){ System.out.println("say hi"); } } 在AppliactionContext作为spring上下文对象的时候,会一次性加载spring-config.xml中的所有Bean 在BeanFactory作为spring上下文对象的时候,会按需加载spring-config.xml中的Bean对象。 言回正传,从spring ioc 容器中获取对象。 public class App { public static void main(String[] args) { // 使用ApplicationContext作为spring的上下文对象,把spring-config.xml文件作为参数传给这个对象。就能通过getBean()方法,得到spring ioc 容器中所管理的对象。 ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); //因为getBean()方法的返回值是一个Object的类型,所以要在这里进行强制类型转换 User user = (User) context.getBean("user"); //得到spring ioc 中的对象,调用对象所在类的方法 user.sayHi(); } } 在上述到代码中,一定要注意的是在getBean()方法中,所传入的参数一定要和spring-config.xml文件中Bean对象的id是一样的。 getBean()方法的更多用法: 第一种: UserController user = context.getBean(UserController.class); 根据类的类型,在spring ioc 容器中获得Bean对象 第二种: UserController user = context.getBean("user", UserController.class); 根据类的类型,和在spring-config.xml文件中的Bean的id在spring ioc 容器中获得Bean对象 第三种: UserController user = context.getBean("user") 根据spring-config.xml文件中的Bean的id在spring ioc 容器中获得Bean对象 但是第一种方法获得Bean对象,有一个诟病,那就是如果在spring-config.xml配置文件中出现了两个相同的类型网spring ioc容器中添加Bean对象,那么在按照对象的类型在spring ioc 容器中获得对象的时候,就不知道你此时要获取那个对象(此时spring ioc 容器中有多个类型相同的对象) ———————————————— 原文链接:https://blog.csdn.net/qq_54883034/article/details/126458733
-
先来看看大数据的概念。根据维基百科,大数据是庞大或复杂的数据集的广义术语,因此传统的数据处理程序不足以支持如此庞大的体量。 在许多情况下,使用SQL数据库存储/检索数据都是很好的选择。而现如今的很多情况下,它都不再能满足我们的目的,这一切都取决于用例的变化。 现在来讨论一些不同的非SQL存储/处理数据工具,例如,NoSQL数据库,全文搜索引擎,实时流式处理,图形数据库等。 1、MongoDB——最受欢迎的,跨平台的,面向文档的数据库。 MongoDB是一个基于分布式文件存储的数据库,使用C++语言编写。旨在为Web应用提供可扩展的高性能数据存储解决方案。应用性能高低依赖于数据库性能,MongoDB则是非关系数据库中功能最丰富,最像关系数据库的,随着MongDB 3.4版本发布,其应用场景适用能力得到了进一步拓展。 MongoDB的核心优势就是灵活的文档模型、高可用复制集、可扩展分片集群。你可以试着从几大方面了解MongoDB,如实时监控MongoDB工具、内存使用量和页面错误、连接数、数据库操作、复制集等。 2、Elasticsearch ——为云构建的分布式RESTful搜索引擎。 ElasticSearch是基于Lucene的搜索服务器。它提供了分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是比较流行的企业级搜索引擎。 ElasticSearch不仅是一个全文本搜索引擎,还是一个分布式实时文档存储,其中每个field均是被索引的数据且可被搜索;也是一个带实时分析功能的分布式搜索引擎,并且能够扩展至数以百计的服务器存储及处理PB级的数据。ElasticSearch在底层利用Lucene完成其索引功能,因此其许多基本概念源于Lucene。 3、Cassandra——开源分布式数据库管理系统。 最初是由Facebook开发的,旨在处理许多商品服务器上的大量数据,提供高可用性,没有单点故障。 Apache Cassandra是一套开源分布式NoSQL数据库系统。集Google BigTable的数据模型与Amazon Dynamo的完全分布式架构于一身。于2008开源,此后,由于Cassandra良好的可扩展性,被Digg、Twitter等Web 2.0网站所采纳,成为了一种流行的分布式结构化数据存储方案。 因Cassandra是用Java编写的,所以理论上在具有JDK6及以上版本的机器中都可以运行,官方测试的JDK还有OpenJDK 及Sun的JDK。 Cassandra的操作命令,类似于我们平时操作的关系数据库,对于熟悉MySQL的朋友来说,操作会很容易上手。 4、Redis ——开源(BSD许可)内存数据结构存储,用作数据库,缓存和消息代理。 Redis是一个开源的使用ANSI C语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis 有三个主要使其有别于其它很多竞争对手的特点:Redis是完全在内存中保存数据的数据库,使用磁盘只是为了持久性目的; Redis相比许多键值数据存储系统有相对丰富的数据类型; Redis可以将数据复制到任意数 5、Hazelcast ——基于Java的开源内存数据网格。 Hazelcst 是一种内存数据网格 in-memory data grid,提供Java程序员关键任务交易和万亿级内存应用。虽然Hazelcast没有所谓的“Master”,但是仍然有一个Leader节点(the oldest member),这个概念与ZooKeeper中的Leader类似,但是实现原理却完全不同。同时,Hazelcast中的数据是分布式的,每一个member持有部分数据和相应的backup数据,这点也与ZooKeeper不同。 Hazelcast的应用便捷性深受开发者喜欢,但如果要投入使用,还需要慎重考虑。 6、Ehcache——广泛使用的开源Java分布式缓存。 主要面向通用缓存、Java EE和轻量级容器。 EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是hibernate中默认的CacheProvider。主要特性有:快速简单,具有多种缓存策略;缓存数据有两级,内存和磁盘,因此无需担心容量问题;缓存数据会在虚拟机重启的过程中写入磁盘;可以通过RMI、可插入API等方式进行分布式缓存;具有缓存和缓存管理器的侦听接口;支持多缓存管理器实例,以及一个实例的多个缓存区域;提供Hibernate的缓存实现。 7、Hadoop ——用Java编写的开源软件框架。 用于分布式存储,并对非常大的数据用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群进行高速运算和存储。Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。 8、Solr ——开源企业搜索平台,用Java编写,来自Apache Lucene项目。 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。 与ElasticSearch一样,同样是基于Lucene,但它对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化。 9、Spark ——Apache Software Foundation中最活跃的项目,是一个开源集群计算框架。 Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。 Spark 是在 Scala 语言中实现的,它将 Scala 用作其应用程序框架。与 Hadoop 不同,Spark 和 Scala 能够紧密集成,其中的 Scala 可以像操作本地集合对象一样轻松地 10、Memcached ——通用分布式内存缓存系统。 Memcached是一套分布式快取系统,当初是Danga Interactive为了LiveJournal所发展的,但被许多软件(如MediaWiki)所使用。Memcached作为高速运行的分布式缓存服务器,具有以下的特点:协议简单,基于libevent的事件处理,内置内存存储方式。 ———————————————— 原文链接:https://blog.csdn.net/qq_43556680/article/details/142631934
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签