第11讲:数据验证、分页显示与上传下载_第1页
第11讲:数据验证、分页显示与上传下载_第2页
第11讲:数据验证、分页显示与上传下载_第3页
第11讲:数据验证、分页显示与上传下载_第4页
第11讲:数据验证、分页显示与上传下载_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

数据验证与分页显示11数据验证:构建安全防线在前后端双重校验输入数据,过滤非法值与恶意请求,从源头保障数据的准确性与系统稳定性。分页显示:优化交互体验通过合理的分页逻辑拆分海量数据,减少网络传输压力,让用户浏览信息更流畅、加载更迅速。本讲目标服务端数据验证熟练运用JSR-380标准注解(如@NotNull、@Size、@Email)对接口请求数据进行合法性校验,在服务层拦截无效输入,保障系统数据的完整性与安全性,从源头规避脏数据产生。JPA分页查询实现掌握Pageable分页参数与Page结果对象的核心用法,实现基于SpringDataJPA的高效数据分页查询。同时学会处理总页数、当前页、总记录数等关键元数据,为前端展示提供完整支撑。前端分页导航交互在Thymeleaf模板引擎中,通过解析后端传递的分页元数据,动态渲染页码、上一页、下一页、跳转按钮等组件,打造流畅、直观且功能完善的用户分页交互体验。通过本讲的学习,将打通“后端数据校验→数据分页查询→前端分页展示”的全链路开发流程,构建规范、高效且用户友好的数据交互系统。数据验证概述客户端验证作用:主要用于防止用户的误操作,提供即时反馈,减少无效请求,显著提升前端交互的用户体验。实现:通常在浏览器端通过JavaScript脚本,在表单提交前对输入格式、长度等进行实时校验。局限:仅作为体验优化手段,安全性极低,验证逻辑可被篡改或直接通过工具绕过,无法保障数据安全。服务器端验证作用:作为数据进入系统的最后一道防线,严格校验所有输入数据的合法性、完整性与有效性。实现:在后端业务代码中独立完成验证逻辑,数据需通过校验后才能进行持久化存储或业务处理。核心:这是保障系统数据质量、防范恶意攻击(如SQL注入、非法参数)的核心与必不可少的手段。结论:构建完整的安全验证体系=客户端即时反馈验证+服务器端核心防线验证客户端验证实现原生JavaScript表单验证通过监听表单的submit事件,在事件处理函数中获取表单元素值,编写自定义逻辑判断,实现基础的前端校验,无需额外依赖。form.addEventListener('submit',(e)=>{

e.preventDefault();

constusername=document.getElementById('user').value;

if(username.length<3)alert('用户名不能少于3位');

});使用成熟开源库(如validate.js)利用封装好的开源库简化开发流程,内置丰富的验证规则(邮箱、长度、格式等),并提供更友好的错误提示与用户交互体验。<inputname="email"data-validate="email">

<inputname="pwd"data-validate="minLength:6">

<scriptsrc="validate.js"></script>

<script>newValidate('#myForm');</script>服务器端验证——BeanValidation注解在Java开发中,我们遵循JSR-380(BeanValidation)标准进行服务端数据校验。通过在实体类字段上添加简洁的注解,即可轻松定义复杂的验证规则,保障数据的合法性与完整性。@NotNull基础空值校验,严格验证字段的值不能为null,但允许为空字符串("")或空白字符。适用于非引用类型或不关注内容的引用类型。@NotBlank专为字符串设计,要求字段不仅不能为null,且调用trim()去除首尾空格后,字符长度必须大于0。常用于校验用户名、密码等关键文本。@Size(min,max)用于校验字符串的长度、集合的大小或数组的元素个数,使其必须在min(包含)和max(包含)指定的范围内,是限制数据容量的常用注解。@Email&@Min/@Max@Email校验邮箱格式的合法性;@Min/@Max用于校验数字(整数/浮点数)的取值范围。配合@Pattern还可实现自定义正则表达式的复杂校验。User.java(ValidationExample)publicclassUser{@NotBlank(message="必填")privateStringusername;@Email(message="格式错误")privateStringemail;@Size(min=6,max=20)privateStringpassword;}💡注:配合全局异常处理器可统一返回校验结果。@Valid与全局异常处理在Controller中触发参数验证在接收请求体的参数前添加`@Valid`注解,Spring框架会自动根据实体类上定义的JSR-380校验注解(如@NotBlank、@Size等)进行参数合法性校验。@PostMapping("/users")

publicResponseEntity<?>createUser(@Valid@RequestBodyUseruser){

userService.save(user);

returnResponseEntity.ok().build();

}全局捕获并统一处理验证异常当参数校验失败时,Spring会抛出`MethodArgumentNotValidException`。通过`@RestControllerAdvice`定义全局异常处理器,统一捕获该异常,格式化错误信息后返回标准的API响应。@ExceptionHandler(MethodArgumentNotValidException.class)

publicResponseEntity<ApiResponse>handleValidationExceptions(MethodArgumentNotValidExceptionex){

Map<String,String>errors=newHashMap<>();

//解析错误信息并封装

returnResponseEntity.badRequest().body(ApiResponse.error(errors));

}核心优势:这种模式将参数校验逻辑与业务逻辑解耦,实现了异常处理的统一管理,提升了代码的可维护性和系统的健壮性。分页技术概述01.核心原理:数据库层面的实现在数据库查询中,通过LIMIT和OFFSET子句实现数据的分段获取。LIMIT限定每页显示的记录条数,OFFSET指定查询结果的起始偏移位置,从而精准定位到目标数据页。--MySQL示例:查询第2页,每页10条记录SELECTFROMusersLIMIT10OFFSET10;--含义:跳过前10条,取接下来的10条数据基础输入参数pageNum/pageSize由前端请求传入,通常页码从1开始,每页记录数可设默认值(如10、20)。计算起始索引offset=(pageNum-1)×pageSize将“第几页”转换为数据库能理解的“从第几条开始查”,是分页查询的关键计算步骤。获取总记录数totalElements=COUNT(*)需额外执行一次聚合查询获取全量数据总数,这是计算总页数和生成分页导航的基础。计算总页数totalPages=(total+size-1)//size通过向上取整公式计算总页数,避免因余数导致最后一页数据无法展示,完善分页逻辑闭环。SpringDataJPA分页SpringDataJPA提供了开箱即用的分页支持,通过封装分页参数与结果元数据,大幅简化了数据分页查询的开发流程。01.Pageable分页参数核心接口,用于封装分页页码、每页记录数和排序规则。通常使用PageRequest.of()静态方法快速构建对象实例。//创建分页对象:第0页,每页10条,按id降序

Pageablepageable=PageRequest.of(

0,10,Sort.by("id").desc()

);02.Page<T>结果载体分页查询的返回结果类型,不仅包含当前页的数据列表,还封装了完整的分页元数据,便于前端进行分页渲染。getContent()

获取当前页数据列表getTotalPages()

获取查询结果总页数getTotalElements()

获取符合条件总记录数isFirst()/isLast()

判断是否为首页/尾页03.Repository自动分页无需编写SQL,只需在Repository方法中传入Pageable参数,并将返回类型声明为Page<T>,框架将自动完成物理分页查询。//基础分页查询

Page<User>findAll(Pageablep);

//条件分页查询示例

Page<User>findByUsernameContaining(

Stringkeyword,Pageablep);Service层分页实现@ServicepublicclassUserService{@AutowiredprivateUserRepositoryuserRepository;publicPage<User>getUsersByPage(intpageNum,intpageSize,Stringkeyword){//页码转换:前端从1开始,JPA从0开始Pageablepageable=PageRequest.of(pageNum-1,pageSize);returnStringUtils.hasText(keyword)?userRepository.findByUsernameContaining(keyword,pageable):userRepository.findAll(pageable);}}核心职责:作为业务逻辑层,Service负责接收并校验前端传递的分页参数,将其转换为数据访问层(Repository)所需的Pageable对象,封装复杂的条件查询逻辑,并向Controller返回标准化的分页结果对象。01.接收参数从Controller层接收`pageNum`(页码)和`pageSize`(每页条数),以及可选的查询关键字。02.页码转换前端分页通常从1开始计数,而JPA的分页查询从0开始,因此需要执行`pageNum-1`的转换。03.构建Pageable使用`PageRequest.of(page,size)`创建分页请求对象,该对象封装了分页的核心元数据。04.调用Repository根据是否存在查询关键字,动态选择调用带条件的`findBy...`方法或无条件的`findAll`方法。05.返回Page对象:将包含数据列表、总页数、总记录数等信息的`Page`对象返回给Controller,为前端渲染分页组件提供完整的元数据支持。Thymeleaf前端分页导航核心实现代码:Thymeleaf模板片段<!--分页链接与状态控制--><ath:href="@{/users(page=1)}"th:disabled="${page.isFirst()}">首页</a><!--遍历生成页码序列,高亮当前页--><spanth:each="i:${#numbers.sequence(1,page.totalPages)}"><ath:href="@{/users(page=${i})}"th:classappend="${i==page.number+1}?'active':''"th:text="${i}"/></span><!--显示分页统计信息-->第[[${page.number+1}]]页/共[[${page.totalPages}]]页,共[[${page.totalElements}]]条通过结合SpringData的Page对象与Thymeleaf的内置工具类,可高效渲染出功能完整、交互友好的分页导航组件,无需手动处理复杂的页码逻辑。th:each遍历利用该属性循环遍历页码序列,动态生成页面上的每一个分页链接,实现自动化渲染。生成页码序列使用#numbers.sequence工具类,基于总页数动态生成连续的页码数字列表,简化逻辑代码。状态动态禁用通过th:disabled结合isFirst()/isLast(),智能禁用首页和末页的跳转按钮,提升用户体验。高亮当前页利用th:classappend为当前活动的页码添加样式类,实现视觉上的突出显示,让用户明确所处位置。案例——学生列表分页+条件查询后端逻辑:Controller层接收参数@GetMapping("/students")publicStringlistStudents(@RequestParam(defaultValue="1")intpage,@RequestParam(defaultValue="10")intsize,@RequestParam(required=false)Stringname,Modelmodel){Page<Student>studentPage=studentService.getStudentsByPage(page,size,name);model.addAttribute("page",studentPage);model.addAttribute("name",name);return"student/list";}前端交互:表单查询与数据展示<!--搜索表单:回显查询条件name--><formth:action="@{/students}"method="get"><inputtype="text"name="name"th:value="${name}"placeholder="请输入姓名"/><button>搜索</button></form><!--分页导航:携带查询条件,防止翻页丢失--><ath:href="@{/students(page=1,name=${name})}">首页</a>...<ath:href="@{/students(page=${page.totalPages},name=${name})}">尾页</a>核心关键点:查询条件的“接力”传递在生成分页导航链接(如首页、上一页、下一页)时,必须将当前的查询参数(如姓名name)一并作为请求参数拼接在URL中。否则,翻页后后端无法获取到之前的查询条件,导致分页结果回到未筛选的全量数据,用户体验下降。课后作业核心任务:实现用户列表的分页展示,并结合姓名关键词进行模糊查询,打通前后端数据交互流程。01/后端逻辑实现在UserService中封装支持姓名模糊匹配的分页查询方法;通过UserController接收前端传入的page、size、name参数,调用业务层方法后,将Page<User>分页对象与查询关键词name统一存入Model,完成数据准备。02/前端页面呈现创建用户列表页user/list.html,添加姓名搜索表单;在页面中遍历page.content渲染用户数据列表;构建分页导航栏,实现页码跳转功能,并确保翻页时查询参数name能够被正确携带和传递。关键提示:注意前端页码参数与后端分页逻辑的转换(如是否从0开始);在分页链接中需通过请求参数显式传递查询条件,避免翻页后丢失搜索状态。12文件上传下载与拦截器/过滤器掌握文件操作与请求拦截技术——深入解析SpringBoot中Multipart文件处理机制,以及拦截器(Interceptor)与过滤器(Filter)在请求生命周期中的核心应用场景与实现细节。本讲目标掌握文件上传与下载实现学会配置文件上传参数,实现单文件和多文件的上传逻辑,并熟练掌握文件下载功能的具体实现方法与路径配置。理解过滤器与拦截器的区别深入剖析过滤器(Filter)和拦截器(Interceptor)在规范归属、请求执行时机以及核心功能应用场景上的关键差异与联系。能够实现登录拦截器学会利用拦截器机制编写登录校验逻辑,对需要鉴权的页面和接口进行访问控制,有效保护系统的安全访问边界。文件上传配置application.yml核心配置片段spring:

servlet:

multipart:

enabled:true#启用文件上传,默认开启

max-file-size:10MB#单个文件最大限制

max-request-size:100MB#单次请求总大小限制

location:/tmp/uploads#临时文件存储目录通过在配置文件中合理设置这些参数,可以有效控制服务器资源占用,防止因超大文件上传导致的性能问题或存储溢出。max-file-size(单文件限制)用于限制单个上传文件的最大体积,避免客户端上传过大的文件导致服务器存储压力激增,保障系统稳定性。max-request-size(总请求限制)针对多文件批量上传场景,限制单次HTTP请求中所有文件的总大小,防止恶意构造的海量小文件请求耗尽带宽资源。location(临时存储目录)指定文件上传过程中临时文件的存放路径。当文件大小超过阈值时,SpringBoot会将文件内容写入磁盘该目录,避免占用过多内存。文件上传实现Controller核心代码实现@PostMapping("/upload")publicStringhandleFileUpload(@RequestParam("file")MultipartFilefile){if(file.isEmpty())return"上传失败,请选择文件";try{StringfileName=file.getOriginalFilename();StringnewFileName=UUID.randomUUID()+fileName.substring(fileName.lastIndexOf("."));Files.write(Paths.get("uploads/"+newFileName),file.getBytes());return"上传成功";}catch(IOExceptione){e.printStackTrace();return"上传失败!";}}01.接收文件使用@RequestParam注解结合MultipartFile类型,可高效绑定前端上传的文件数据流。02.校验有效性调用file.isEmpty()方法,过滤空文件请求,提前拦截无效操作,避免后续逻辑异常。03.唯一化命名利用UUID或时间戳生成新文件名,有效避免用户上传同名文件时,发生服务器文件覆盖冲突。04.写入磁盘通过Files.write()方法将文件字节流持久化到服务器指定目录,完成整个文件上传的核心流程。核心要点:通过标准注解绑定参数,严谨的空值校验,配合唯一化命名策略,确保文件上传安全、稳定、无冲突。文件下载实现JavaController核心代码实现@GetMapping("/download/{fileName}")publicvoiddownloadFile(@PathVariableStringfileName,HttpServletResponseres){//1.设置响应头,指定二进制流与附件名res.setContentType("application/octet-stream");res.setHeader("Content-Disposition","attachment;filename=\""+fileName+"\"");//2.读取文件并写入响应输出流try(InputStreamis=newFileInputStream(newFile("uploads/"+fileName));OutputStreamos=res.getOutputStream()){IOUtils.copy(is,os);//高效流拷贝}catch(IOExceptione){e.printStackTrace();}}核心逻辑:通过手动配置HTTP响应头告知浏览器以附件形式处理数据,再通过字节流将文件内容传输至客户端。01.设定响应媒体类型使用application/octet-stream声明响应为任意二进制数据流,让浏览器根据后续头信息决定处理方式。02.配置附件下载头设置Content-Disposition:attachment,明确告诉浏览器这是一个需要下载的附件,并指定保存时的默认文件名。03.字节流读写传输通过InputStream读取服务器文件,利用缓冲区将数据写入ResponseOutputStream,完成文件内容的流式推送。过滤器Filter概述核心定义与特性规范归属:属于Servlet规范,依赖Tomcat等Servlet容器运行。执行时机:在请求进入Servlet之前拦截处理,处于请求链的上游。拦截范围:覆盖所有请求,包含HTML、CSS、JS等静态资源文件。开发与注册流程1.实现接口:创建Java类,实现javax.servlet.Filter接口,重写doFilter核心方法。2.注册配置:方式一:使用@WebFilter注解并开启@ServletComponentScan;方式二:通过FilterRegistrationBean进行Bean式注册。常见业务应用编码与跨域:统一设置请求响应的字符编码(如UTF-8),添加CORS响应头解决跨域问题。日志与监控:拦截请求URL、访问时间、客户端信息等,记录系统访问日志,实现请求监控。核心方法:doFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)——通过FilterChain控制请求是否继续向后传递。过滤器实现示例01.核心实现:实现Filter接口@WebFilter(urlPatterns="/*")publicclassMyFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainchain){req.setCharacterEncoding("UTF-8");//预处理操作chain.doFilter(req,resp);//放行请求,传递给下一环System.out.println("请求处理后执行");//后置处理}}02.启动配置:开启组件扫描@SpringBootApplication@ServletComponentScan//关键注解,扫描Web组件publicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(...);}}关键说明:添加@ServletComponentScan注解后,SpringBoot才能自动扫描并注册使用@WebFilter、@WebServlet等注解标记的Web组件,无需额外的XML配置。核心流程:定义过滤器类并实现接口→重写doFilter处理请求→配置启动类扫描注解→实现全局请求拦截与处理。拦截器Interceptor概述核心定义与特性规范归属:属于SpringMVC框架,依赖Spring容器管理,是Spring生态的核心组件。执行与范围:在请求进入Controller前后执行,仅拦截进入Controller的请求,不处理静态资源。核心方法:包含preHandle、postHandle、afterCompletion三大关键回调方法。开发与配置流程01.定义拦截器类:创建自定义类,实现org.springframework.web.servlet.HandlerInterceptor接口,按需重写其核心方法。02.注册拦截器:配置类实现WebMvcConfigurer接口,在addInterceptors方法中通过registry.addInterceptor()完成注册并指定拦截路径。核心业务应用场景校验与控制:统一做登录状态检查,防止未登录访问;校验用户角色权限,拦截非法资源请求。监控与加工:记录请求的处理时长、URL等日志信息;在视图渲染前,通过postHandle统一修改ModelAndView中的公共数据。核心价值:拦截器是AOP思想在Web层的具体体现,能解耦通用功能与业务逻辑,让开发者聚焦核心业务,提升系统的模块化与可维护性。拦截器实现示例01.实现HandlerInterceptor接口核心方法:preHandle()

在请求处理前执行,返回true表示放行请求,返回false则直接拦截,后续处理器不再执行。常用于登录校验、权限检查等场景。辅助生命周期方法:

postHandle():请求处理完成、视图渲染前执行,可对模型数据或视图进行修改。

afterCompletion():视图渲染完成后执行,主要用于资源清理工作,如关闭流、释放线程等。02.配置类注册与路径规则配置类定义

创建配置类并标注@Configuration,实现WebMvcConfigurer接口,重写addInterceptors()方法来注册自定义拦截器实例。灵活的路径匹配策略:

addPathPatterns("/**"):指定拦截所有请求路径,作为基础匹配规则。

excludePathPatterns(...):排除特定路径,如登录页、静态资源文件等,避免不必要的拦截,提升系统性能。核心要点:拦截器是SpringMVC的核心组件,通过拦截请求流程,实现统一的日志记录、权限控制与资源管理。过滤器与拦截器对比过滤器(Filter)·Servlet规范执行与范围:在请求进入Servlet之前执行,拦截范围覆盖所有请求(含静态资源如JS/CSS)。容器与能力:基于Servlet容器,生命周期由容器管理,无法直接使用Spring的依赖注入(DI)功能。典型场景:全局编码设置、C

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论