前言
汇总Java基础知识和部分MySQL知识,希望通过本篇博客的知识梳理,希望能帮助阅读的你
过滤器和拦截器的区别
过滤器和拦截器都可以实现对请求的预处理和后处理,但二者有以下主要区别:
过滤器(Filter)
- 依赖于 Servlet 规范,是 Servlet 体系结构的一部分
- 配置在 web.xml 中
- 作用于 Servlet 前后,用于处理 Servlet 请求和响应
- 主要用于处理与Servlet 无关的功能,如:日志,认证,数据压缩等
- 一个过滤器实例只能在容器的生命周期一次初始化,处理所有请求
拦截器(Interceptor) - 依赖于 Spring MVC 框架,是 Spring MVC 体系结构的一部分
- 通过实现 HandlerInterceptor 接口编写,并在 Spring 配置文件中配置拦截器
- 只作用于 Spring MVC 的请求,在 Spring MVC 的 DispatcherServlet 把请求转发到 Controller 前后执行拦截操作
- 主要应用于对业务处理的预处理和后续处理,如:日志,性能监控,权限控制等
- 拦截器实例会在每次请求时创建,只作用于当前请求
总的来说,过滤器的应用范围更广,拦截器更专注于 MVC 请求的拦截,拦截器的灵活性更高,可以访问请求和响应。所以在适当的情况下,二者是可以结合使用的。GET和POST的区别
GET 和 POST 都是 HTTP 协议里最常用的两种请求方法,但二者有以下主要区别:
GET 请求: - GET 请求通过 URL 传递参数,URL 中携带的参数是很明显的,不安全
- GET 请求参数有长度限制,通常不能超过 2048 个字符
- GET 请求只能获取数据,不会修改服务器资源
- GET 请求可以被缓存
- GET 请求应该被幂等(重复调用同一个请求应该得到同样的结果)
POST 请求: - POST 请求通过请求体传递参数,参数不在 URL 中显示
- POST 请求参数没有长度限制
- POST 请求可以修改服务器资源
- POST 请求不会被缓存
- POST 请求不需要幂等
所以综上,二者的区别在于: - GET 适用于信息获取,POST 更适用于表单提交及信息修改
- GET 更不安全,参数明显,POST 更安全,参数不在 URL 显示
- GET 受 URL 长度限制,POST 没有限制
- GET 可被缓存,POST 不会被缓存
- GET 应该幂等,POST 不需要
在实际开发中,我们通常会遵循以下原则: - GET 用于查询,POST 用于修改(创建/更新/删除)
- GET 请求的结果可以被缓存,POST 请求的结果不会被缓存
- GET 请求应该是幂等的,POST 请求可以不幂等
HttpServletResponse response实现文件上传、下载
文件下载:
- 设置响应头:
response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
- 设置 Content-Type 为 application/octet-stream,表示响应体是二进制数据
- 设置 Content-Disposition 为 attachment; filename=xxx,表示这是需要下载的文件,文件名叫 xxx
- 读取文件并写出:
FileInputStream fis = new FileInputStream(file); ServletOutputStream sos = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { sos.write(buffer, 0, len); } sos.close(); fis.close();
- FLUSH 输出并结束响应:
sos.flush(); sos.close();
文件上传:
- 获取 MultipartResolver 解析multipart/form-data请求:
在 SpringMVC 中,可以在 DispatcherServlet 中配置 MultipartResolver,如:<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760000"/> </bean>
- 在处理方法上添加 @RequestParam("file") MultipartFile 文件参数:
@PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) throws IOException { // ... }
- 获取文件输入流 MultipartFile#getInputStream(),并保存文件:
String fileName = file.getOriginalFilename(); File dest = new File(uploadPath + fileName); file.transferTo(dest);
- 返回结果:
return "redirect:/success";
MySql基础知识总结
MySQL 是最流行的关系型数据库管理系统之一,以下是 MySQL 的一些基础知识总结:
- 数据库和数据表
- 设置响应头:
- 数据库是一组存储的相关数据的容器,一个 MySQL 服务器可以包含多个数据库
- 数据表是数据库内部存储数据的结构,每个表包含多行记录和固定数量的列
- 创建数据库语法:CREATE DATABASE database_name;
- 创建表语法:CREATE TABLE table_name (column1 type, column2 type, ...);
- 数据类型
- MySQL 支持多种数据类型,如 INT,VARCHAR,CHAR,DATE,BOOLEAN 等
- VARCHAR 是可变长度字符串,CHAR 是定长字符串
- INT 可以指定长度,如 INT(4)
- DATE 格式为 YYYY-MM-DD
- BOOL 只有 TRUE 和 FALSE 两个值
- 约束
- 约束用于限制表中的数据,保证数据的正确性和可靠性
- 常用约束有:PRIMARY KEY,UNIQUE,NOT NULL,FOREIGN KEY,CHECK 等
- PRIMARY KEY:主键,唯一且非空;
- UNIQUE:唯一,避免重复的值;
- NOT NULL:非空;
- FOREIGN KEY:外键,用于建立两张表的关联关系;
- CHECK:检查约束, SQL 表达式结果为 TRUE;
- CRUD 操作
- INSERT INTO 向表中插入数据
- SELECT FROM 查询表中数据
- UPDATE 修改表中数据
- DELETE FROM 删除表中数据
- WHERE 子句用于过滤数据
- 其他
- SQL 注释:#或者
--
- 事务:一组SQL查询,全部成功或全部失败。开始:START TRANSACTION;提交:COMMIT;回滚:ROLLBACK
- 视图:虚拟表,从一个或多个基本表中导出的数据;CREATE VIEW view_name AS SELECT ...
- 索引:提高查询效率;CREATE INDEX 索引名 ON 表名 (列名)
SQL性能优化的21个小技巧
- 使用 EXPLAIN 分析查询语句
- 使用索引
- 选择正确的数据类型
- 避免 NULL
- 去除重复索引
- 合理使用 JOIN
- 尽量使用 CONSTANT 和 SYSTEM 表
- LIMIT 优化
- 使用 SQL_CACHE
- 避免 SELECT *
- 使用 UNION ALL 代替 UNION
- 使用锁定表LOCK TABLES
- 使用延迟关联 LAZY LOADING
- 整理数据表的结构
- 使用存储过程和函数
- 使用游标Cursor处理大数据集
- 避免频繁创建和 DROP 临时表
- 利用 QPM (Query Performance Monitoring)监控慢查询
- 选择合适的存储引擎
- 使用分区表
- 自己动手做 SQL 调优
详细说明如下: - EXPLAIN 可以分析查询语句,看看哪里性能差弱。
- 索引大大提高查询速度,但会稍微降低更新表的速度。
- 选择正确的类型可以优化查询和节省存储空间。
- 防止在列上使用 NULL 值可以提高查询性能。
- 重复或冗余的索引会降低插入和更新表的速度。
- 合理使用 JOIN 可以避免严重的性能问题。
- System表数据变化少,插入删除少,使用时查询效率高。
- 如果只需要几行记录,使用 LIMIT 可以提高效率。
- 使用 SQL_CACHE 可以缓存查询结果,提高后续同样查询的速度。
- 避免 SELECT *,只选择需要的列,可以提高查询速度和网络带宽。
- UNION ALL vs UNION
- UNION 会去除重复行,UNION ALL 不会,所以 UNION ALL 通常更快。
- LOCK TABLES 可以锁定表,避免并发操作带来的性能问题。
- LAZY LOADING 只在使用数据时才会从数据库查询,而EAGER 前面会将相关数据全部查询出来,性能差一些。
- 合理的表结构可以带来更好的查询性能,如规范的表名和字段名,字段顺序等。
- 存储过程和函数可以简化应用开发,减少编译次数并且提高性能。
- 对大数据集使用游标Cursor可以控制内存使用,避免整个数据集读入内存造成性能问题。
- 频繁创建和删除临时表会对性能产生较大影响。
- QPM 可以实时监控数据库在运行查询时的性能,找到其中比较慢的查询并进行优化。
- 选择合适的存储引擎可以获得更好的性能,如InnoDB 和 MyISAM。
- 对高并发写操作的表,使用分区表可以提高性能。
- 熟练掌握 SQL 调优的方法和经验,并不断总结和提高。比如优化索引、SQL语句、参数、架构等。
SQL代码编码原则和规范
SQL 代码编码原则和规范主要包括:
- 数据库对象命名
- 表名,列名使用小写字母和下划线,例如:user_info, order_detail
- 不使用SQL保留字,例如:order, user 而不使用 select, table
- 避免使用拼音,例如:用户表名为 user 而不是 yonghu
- SQL 关键字大写
- SQL 关键字如 SELECT, FROM, WHERE 等全部大写
- 缩进和空格
- SQL语句块需要有统一的缩进,便于阅读,例如:
SELECT * FROM user_info WHERE age > 30 AND gender = 'M' ORDER BY create_time DESC
- SQL 语句中各关键字之间使用一个空格隔开,例如 BETWEEN 应写成 BETWEEN 而不是BETWEEN, IN应写成IN 而不是IN等
- 每条 SQL语句以分号结尾
- 每条 SQL 语句后需添加分号 ; 作为结束符
- 注释
- 单行注释使用 -- 注释内容
- 多行注释使用 / 注释 /
- 避免魔法值,使用参数
- 不要直接在SQL语句中使用"魔法值",即没有具体意义的常量,这会导致维护困难
- 例如不要:
SELECT * FROM user WHERE age = 30
- 应该使用参数:
SELECT * FROM user WHERE age = ?
- 数据库对象权限控制
- 根据业务需要和研发流程,对数据库对象(表、视图、存储过程等)进行权限分配,控制研发人员对其的访问
- 统一的数据库设计规范
- 对数据库的表结构、字段命名、索引和约束等需要统一的规范,这有助于多人协作开发维护数据库。
MySQL 函数、数字函数、日期函数、运算符
MySQL 中常用的函数、数字函数、日期函数和运算符如下:
函数: - IF(expr,res1,res2):如果expr是TRUE,返回res1,否则返回res2
- CASE expr WHEN res1 THEN ... ELSE ... END:类似多重IF语句
- CONCAT(str1,str2...):连接字符串
- LENGTH(str):字符串长度
- SUBSTRING(str,start,end):截取字符串
- REPLACE(str,a,b):替换字符串
- UPPER/LOWER(str):大/小写转换
- ROUND(x):四舍五入
数字函数: - abs(x):绝对值
- ceil(x)/floor(x):向上/向下取整
- mod(x,y):取余
- rand():随机数
- power(x,y):x的y次方
- sqrt(x):开方
- pi():圆周率
日期函数: - now():当前日期+时间
- curdate():当前日期
- curtime():当前时间
- date(str):字符串转日期
- date_add/sub(date,INTERVAL x UNIT):日期增加/减少 日/周/月/年
- datediff(date1,date2):两个日期差
- date_format(date,format):格式化日期显示
运算符: -
-
-
- / %:加减乘除取余
-
-
- between ... and ...:在某个范围
- is null/is not null:是否为空
- in(set):在集合中的值
- like:模糊查询
- < <= > >= != :大小比较
- and or not:逻辑运算
示例:SELECT IF(1>0,'true','false'); // true SELECT CASE 2 WHEN 1 THEN '一' WHEN 2 THEN '二' ELSE '其他' END; // 二 SELECT CONCAT('a','b','c'); // abc SELECT DATE_ADD(now(), INTERVAL 1 DAY); // 日期增加1天
MySQL进阶实战1,数据类型与三范式
一、数据类型
- 整数:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT
- 浮点数:FLOAT, DOUBLE, DECIMAL
- 字符串:CHAR, VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT
- 日期时间:DATE, TIME, DATETIME, TIMESTAMP
- 其他:BOOL, BLOB, JSON, XML 等
选择数据类型时需要考虑:
- 所存储数据的范围(长度,值域)
- 确定性(FLOAT 和 DOUBLE 存在精度损失)
- 字符集与校对规则(对字符串比较)
- 空间消耗(定长/变长)
- 语义(TIMESTAMP 带时间信息,DATE 不带)
二、三范式
三范式是关系数据库设计的理论基础,主要包括:
第一范式(1NF):每列的值必须是原子性的,不能再分解。
第二范式(2NF):满足1NF,并且非主属性(非主键)必须完全依赖于候选键(在1NF基础上消除非主属性对主键的部分依赖)。
第三范式(3NF):满足2NF,并且非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖)。
示意例:
出版社(Name, City)
书籍 (Name, Publish_ID) # Publish_ID -> 出版社.ID (外键)
作者(ID, Name, Age)
书籍作者(Book_Name, Author_ID) # Book_Name -> 书籍.Name;Author_ID -> 作者.ID - 书籍和书籍作者违反2NF,书籍作者依赖书籍的Name和作者的ID,但书籍的Name不是主关键字。
- 解决:将书籍作者的Book_Name改为Book_ID,作为外键引用书籍的ID。
- 这样就满足了2NF,并继而满足3NF。
因此,数据类型的选择和数据库的三范式设计是进行MySQL进阶优化的两个非常重要的方面。
三范式的目的是减少数据冗余,提高数据的完整性。但过度pursuit也会影响性能,需要具体问题具体分析。
(Java基础知识和MySQL部分知识)Java学习路线(漫漫人生路,步步架构梦)Java Learning Path (Long Life Path, Step by step Structure Dream)