十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JAVAEE进阶---Spring

JAVAEE进阶---Spring 海量注解一、传入参数注解package org.example.springbootdemo.controller; import org.example.springbootdemo.Person; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; //控制器类 RestController RequestMapping(/hello) public class HelloController { RequestMapping(/v1) public String hello() { return Hello SpringBoot; } RequestMapping(/v2) public Integer getNum(){ return 6/2; } RequestMapping(/v3) public String aa(Integer x,String y){ return x: x, y: y; } //参数重命名 RequestMapping(/v33) public String aa2(RequestParam(value nameX,required false) Integer x,RequestParam(value nameY,required false) String y){ return x: x, y: y; } //传递类参数 RequestMapping(/v4) public String v4(Person person){ return person.toString(); } //传递数组参数 RequestMapping(/v5) public String v5(String[] arr){return Arrays.toString(arr);} //通过RequestParam绑定传递集合参数 RequestMapping(/v6) public String v6(RequestParam ListString list){ return list.toString(); } //通过RequestBody来将请求正文中的内容 //转换成你想要的Person对象 RequestMapping(/v7) public String v7(RequestBody Person person) { return person.toString(); } //获取URL里的参数 //通过使用PathVariable实现参数重命名 RequestMapping(/v8/{id}/{type}) public String v8(PathVariable(id) Integer useId, PathVariable String type) { return 获取到的url参数 useId type; } //上传文件 //通过使用RequestPart实现参数重命名 //每次不能传入相同的图片我的picture下已经有了请记住这个错误前车之鉴警示后人 RequestMapping(/v9) public String v9(RequestPart(file) MultipartFile multipartFile) throws IOException { System.out.println(multipartFile.getOriginalFilename()); File file new File(E:/my-first-web/屏幕截图/ multipartFile.getOriginalFilename()); multipartFile.transferTo(file); System.out.println(目标完整路径 file.getAbsolutePath()); return 文件上传成功; } }1、在文件操作上我踩了坑1️⃣ 方法声明部分说明RequestPart(file)告诉 Spring从请求中取名为file的文件部分MultipartFileSpring 提供的文件对象类型封装了文件的所有信息throws IOException文件读写可能出错必须抛出异常重点RequestPart(file)里的file必须和前端/form-data 里的 Key 名称一致2️⃣ 获取原始文件名System.out.println(multipartFile.getOriginalFilename());方法作用getOriginalFilename()获取用户上传文件的原始文件名含扩展名示例用户上传照片.jpg→ 返回照片.jpg3️⃣ 构造保存路径File file new File(E:/my-first-web/屏幕截图/ multipartFile.getOriginalFilename());部分说明E:/my-first-web/屏幕截图/目标文件夹路径末尾必须有/ multipartFile.getOriginalFilename()拼接文件名最终效果E:/my-first-web/屏幕截图/照片.jpg⚠️警告如果末尾没有/会变成E:/my-first-web/屏幕截图照片.jpg文件夹名和文件名粘在一起4️⃣ 保存文件核心multipartFile.transferTo(file);方法作用transferTo(File dest)将上传的文件写入到目标位置等价于把上传的文件复制到你的硬盘里这个就是真正保存文件的操作2、Controller与RestControllerController返回的是视图RestController返回数据RestController Controller ResponseBody二、Cookie与Session面试1、http协议是无状态协议服务器不记得你是谁。为了解决这个问题才引入了 Cookie 和 Session 机制来保持会话状态设置 Session 时服务器会创建一个 Session生成一个 SessionId然后把 SessionId 存到客户端浏览器的 Cookie 中。获取时浏览器自动带上 Cookie服务器根据里面的 SessionId 找到对应的 Session取出你想要的数据返回给你2、两者的区别首先从存储位置来看:Cookie 存在客户端Session 存在服务端这是它们最根本的区别它们之间通过 SessionId 关联:SessionId 就是连接 Cookie 和 Session 的桥梁但要注意的是它们不是必须配合使用的:一方面Cookie 完全可以独立使用比如存用户的主题偏好或语言设置不一定要存 SessionId另一方面SessionId 也不一定非走 Cookie 不可如果浏览器禁用了 Cookie我们也可以通过 URL 重写的方式来传递 SessionId3、获取Session的代码package org.example.springbootdemo.controller; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/session) public class RequestController { // 方式1通过 HttpServletRequest 手动获取 GetMapping(/get1) public String getSession1(HttpServletRequest request) { HttpSession session request.getSession(true); String name (String) session.getAttribute(name); return 方式1 - name: (name null ? 未设置 : name); } // 方式2通过参数注入 HttpSession GetMapping(/get2) public String getSession2(HttpSession session) { String name (String) session.getAttribute(name); return 方式2 - name: (name null ? 未设置 : name); } // 方式3通过 SessionAttribute 直接取值 GetMapping(/get3) public String getSession3(SessionAttribute(value name, required false) String name) { return 方式3 - name: (name null ? 未设置 : name); } // 设置Session测试用 GetMapping(/set) public String setSession(HttpSession session) { session.setAttribute(name, 张三); return 设置成功name 张三; } //读取请求头中浏览器信息非必须 RequestMapping(/getHeader) public String getHeader(HttpServletRequest request) { String userAgent request.getHeader(User-Agent); return 获取header成功。userAgent: userAgent; } RequestMapping(/getHeader2) public String getHeader2(RequestHeader(User-Agent) String userAgent) { return 获取header成功。userAgent: userAgent; } }三、Spring两大核心思想---IOC与AOP面试1、IOC控制反转Inversion of ControlIOC 就是 将对象的创建权和管理权交给 Spring 容器由容器来管理对象的生命周期和依赖关系而不是由程序员主动 new控制 指的是啥—— 对象的创建权限反转 指的是啥—— 把创建权从程序员手里反转到 Spring 容器手里2、五大注解注解层级作用Controller控制层/表现层接收请求返回响应Service业务逻辑层处理业务逻辑事务管理Repository数据访问层操作数据库异常转换Configuration配置层配置类替代XMLComponent组件层通用组件不属于以上三层3、核心要点五个注解底层都是Component功能上可以相互替代但实际开发中不能混用为什么不能混用代码可读性Service一眼看出是业务层Component看不出团队协作统一规范别人接手代码更容易理解问这些注解有啥区别答本质都是存对象但分门别类放清楚实用4、Bean注解五大注解和 Bean 的区分五大注解用于自己写的类直接在类上加注解Spring 自动创建并管理默认是单例Bean用于两种场景同一个类型需要创建多个对象第三方的类源码不在自己手里没法加Component两者本质都是存对象取用方式也相同Autowired只是应用场景不同5、Autowired与Resource面试Autowired 是 Spring 框架提供的注解Resource 是 JDK 自带的注解。它俩最核心的区别是Autowired 默认按类型注入Resource 默认按名称注入。另外Resource 比 Autowired 支持更多参数设置比如可以直接用 name 属性指定 Bean 名称来精确注入接着需要回答下面问题Autowired 装配流程直接画图即可Autowired 装配过程 1. 按类型byType查找 │ ├── 找到 1 个 → ✅ 直接注入 │ ├── 找到 0 个 → ❌ 抛异常NoSuchBeanDefinitionException │ └── 找到多个 → 进入第 2 步 2. 按名称byName匹配 │ ├── 匹配上 → ✅ 注入 │ └── 匹配不上 → ❌ 抛异常NoUniqueBeanDefinitionException6、AOP面向切面编程Aspect Oriented ProgrammingAOPAspect Oriented Programming面向切面编程是一种编程思想。它的作用是在不修改原有业务代码的情况下对方法进行统一增强。比如在开发中很多功能是通用的日志记录权限校验事务管理方法耗时统计这些功能如果直接写在每个业务方法中会造成代码重复和业务代码耦合。简单讲就是把这些公共逻辑抽取出来统一处理。Spring AOP中的几个重要概念1. Aspect切面切面就是封装通用功能的类。使用Aspect Component public class TimeAspect { }Component表示交给Spring管理。Aspect表示该类是一个切面类。2. PointCut切点切入点用于指定哪些方法需要被增强。例如指定所有Service层方法execution(* com.example.service.*.*(..))3. Advice通知通知表示增强代码执行的位置。常见类型Before方法执行前执行After方法执行后执行Around方法执行前后都可以处理最常用AOP常见应用场景日志记录统一记录用户请求信息、操作日志。权限校验例如判断用户是否具有管理员权限。事务管理Spring中的Transactional底层就是通过AOP实现。性能监控统计接口执行时间发现慢接口。Spring AOP的实现原理是什么你可以这样回答Spring AOP底层是通过动态代理实现的。Spring在创建Bean的时候会判断这个Bean是否需要进行AOP增强如果需要就会创建一个代理对象交给IOC容器管理。之后调用这个Bean的方法时实际上调用的是代理对象代理对象会先执行切面中的增强逻辑然后再调用目标对象的方法。Spring AOP主要有两种动态代理方式如果目标类实现了接口使用JDK动态代理如果没有实现接口则使用CGLIB动态代理。四、Spring、SpringMVC、SpringBoot 的理解超级高频这道题几乎所有 Java 面试都会问重点说清楚“三者是什么关系”我将从“是什么”和“什么关系”两个角度来回答:Spring是一个“全家桶”框架它的核心是IOC 容器和AOP。IOC 帮我们管理对象AOP 帮我们做功能增强。Spring 提供了很多功能比如事务管理、数据访问等但它的问题是配置复杂。SpringMVC是 Spring 框架中的一个模块专门用来做Web 开发。它的核心是MVC 设计模式Model 存数据、View 显示页面、Controller 接收请求同时它也是一个Servlet负责处理 HTTP 请求和响应。SpringBoot是基于 Spring 的“脚手架”它的核心目标是简化 Spring 开发。它通过“自动配置”帮我们省掉了大量繁琐的 XML 配置同时通过“起步依赖”把常用的技术栈打包好比如spring-boot-starter-web直接把 Web 开发需要的依赖全给你配好了开箱即用。简单总结Spring 是“基础框架”SpringMVC 是“做网站用的模块”SpringBoot 是“帮我省配置的脚手架”。SpringBoot 里面包含了 SpringSpringMVC 是 Spring 的一部分。五、#{}与 ${}的选择问题两个方向总结 补充#{}和${}主要有两个区别第一处理方式不同。#{}是预编译占位符MyBatis会把它替换成?参数自动加引号作为值处理${}是纯字符串拼接直接把参数内容拼到SQL里不加引号。第二安全性不同。因为#{}是预编译参数不会改变SQL结构所以能防止SQL注入${}是拼接如果参数包含恶意代码就会被执行存在注入风险。所以能用#{}的地方优先用#{}。补充${}只在迫不得已时用比如 ORDER BY、动态表名、动态列名这些场景因为数据库不允许对这些位置使用占位符。但用之前必须做白名单校验。本章完
返回列表