文章目录
- 43.Dao层设计规范
- 44.POJO层设计规范
- 45.Service层设计规范
- 46.自定义DruidUtils
- 47.QueryRunner
- 48.用户状态信息保存设计
- 49.查询规范
- 50.如何在项目中提高八股应用效率,减少犯错
- 51.Cookie 和 Session 区别
- 52.什么样的数据存到Cookie中?
- 53.什么样的数据存到Session中?
- 54.为什么登陆业务昨天一切正常,今天就找不到数据源了?红温下播
43.Dao层设计规范
reference
接口规范:com.xx.dao
一张表的SQL操作对应一个接口
接口名: 对应表的实体类名+Dao.如UserDao
一个SQL对应一个方法(只与sql映射,不映射功能)
实现类书写规范:com.xxx.dao.impl
一个实现类实现一个接口
实现类名: 接口名+impl,如UserDaolmpl
方法实现:使用数据库连接技术实现SQL需求
通常不会声明独有方法(使用接口引用,无法使用实现类独有方法)
方法定义规范::Xxx为对应类名
査询多行数据: public List<对象>selectXxxs[By属性名](),如selectUsers()|selectUsersByAge(int age)
查询单行数据:public 对象 selectXxxBy属性名().如selectUserByUserld(数据类型 属性名)
增: public int insertXxx(存储了添加信息的对象),当字段值较少时,也可以直接传入对应字段的属性声明
删: public int deleteXxxBy属性名(筛选条件对应的属性声明),如deleteUserByUserld(int Userld)
改: public int updateXxxBy属性名(存储了所有修改相关信息的对象),当涉及字段较少时,也可以直接传入相关属性声明
44.POJO层设计规范
-
基本属性
私有化字段:所有字段都应声明为private,以封装内部数据,防止外部直接访问。
默认构造函数:提供一个无参的默认构造函数,方便框架或工具类实例化对象。
全参数构造函数:根据需要提供一个包含所有必要字段的构造函数,便于创建对象时一次性初始化。 -
Getter和Setter方法
遵循命名规则:对于每个私有字段,提供相应的getter和setter方法,方法名应符合JavaBean规范,如getField()和setField(Field field)。
逻辑控制:可以在setter方法中添加业务逻辑验证,确保数据的有效性。 -
等值判断与哈希码
重写equals()和hashCode():如果POJO对象需要用于集合操作(如放入HashSet或作为HashMap的键),则应该重写这两个方法,基于对象的实际业务意义来实现等值比较和哈希值计算。
-
字段类型选择
使用合适的类型:选择最能准确表达业务含义的数据类型。例如,使用LocalDate而不是String来表示日期。
避免使用原始类型数组:尽可能使用泛型集合代替原始类型的数组,如使用List代替String[]。 -
注解使用
适当使用注解:利用ORM框架提供的注解(如JPA中的@Entity, @Table, @Column等)来映射数据库表和字段,增强代码的可读性和简洁性。
校验注解:使用Hibernate Validator等提供的校验注解(如@NotNull, @Size等)来标注字段约束条件。 -
文档与注释
详细文档说明:为每个POJO类及其成员变量编写详细的文档注释,解释其用途和使用方式。
保持注释更新:随着代码的变化,及时更新相关注释,确保它们与实际代码一致。 -
不要在POJO中加入业务逻辑
POJO应当保持纯粹,不应包含任何业务逻辑处理,所有的业务逻辑应该放在服务层实现。
用来和数据库中的表对应,解决的是数据格式在Java和数据库间的转换可以理解为:如何设计一个Java实体类,使其可以作为接收数据库中数据的载体
编码规范:Java中将所有数据库的数据,使用Java对象进行表示
一张表对应一个实体类
类名与表名相关,如 t_user 的实体类名 User
一个字段对应一个属性
属性名必须由字段决定,字段名由1部分组成,则属性名与字段名保持一致,如 字段名 age的属性名也为 age;字段名由多个部分组成,属性名变成小驼峰命名,如字段名 user_id 的属性名为 userId
属性的数据类型必须与字段的类型保持一致(属性仍然是Java的数据类型)对应关系如下:对应关系 整数 小数 字符 日期Java byte/short/int/long double String DateMySQL 整数类型(int...) 小数类型(float,double,decimal) char/varchar/enum/text 日期类型(datetime...)
属性的数据类型必须为引用类型(目的是为了处理数据库中的null值)
必须提供封装和无参构造方法,可以根据需要提供有参构造
必须实现序列化接口
45.Service层设计规范
将面向用户操作的功能代码封装,Service业务层封装了用户的操作功能,一个用户操作,对应Service的一个方法。
执行流程:
视图层->调用业务层->调用DAO
书写顺序:
先写DAO->书写业务层->再写视图层
书写顺序原因:
因为视图层需要业务层的数据支持,而业务层需要DAO的sql支持
Service设计规范
接口:com.xxx.service
一张表的相关的功能对应一个service层接口,如登录|注册功能-UserService,转账-Accountservice
命名:实体类名+Service
一个功能对应一个方法
实体类:com.xxx.service.impl
一个实现类对应一个service接口
命名: service接口名+impl
方法实现:调用DAOSQL支持+逻辑代码
方法:
返回值:查询功能的返回值为List集合或单个对象增删改查及其他功能,通常返回boolean类型
参数:需要用户提供的数据都应该为功能的参数,参数模式为单个声明还是对象容器存储由参数的数量决定
命名:功能逻辑复杂:以功能命名,如登陆 login,注册 register ,转账 transfer功能逻辑简单(功能结构只与SQL执行结构相关):在DAO模式命名的基础上更改方法前端的关键字查询:query... ,如查询所有用户信息-queryUsers增加:add...,如新增用户信息-addUser删除:remove...,如根据用户ID删除用户信息-removeUserByUserId更改:change...,如根据用户名修改密码-changeUserByUserName |changePasswordByUserName
46.自定义DruidUtils
封装DruidUtils:
public class DruidUtils {//定义成员变量 数据源private static DataSource dataSource;//使用静态代码块 读取配置文件信息static {try {//创建Properties 对象Properties p = new Properties();//基于反射技术 获取类加载器InputStream inputStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");//使用Properties对象的 load方法 从字节流中读取配置信息p.load(inputStream);//通过工厂类获取连接池对象 dataSource = DruidDataSourceFactory.createDataSource(p);} catch (Exception e) {e.printStackTrace();}}public static DataSource getDataSource() {return dataSource;}//获取连接的方法 public static Connection getConnection(){ try {return dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); return null; } }public void close(Connection connection, Statement statement){if (connection != null && statement != null){try {statement.close();connection.close();} catch (SQLException e) {e.printStackTrace();}}}public void close(Connection connection, Statement statement, ResultSet resultSet){if (connection != null && statement != null && resultSet != null){try {resultSet.close();statement.close();connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
DruidUtils使用:
1.实例化QueryRunner()
//手动方式 创建QueryRunner对象
QueryRunner qr = new QueryRunner();//自动创建 传入数据库连接池对象 提供数据源(连接池),DBUtils底层自动维护连接connection
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
2.qr.update()方法,执行增删改的sql命令
update(Connection conn, String sql, Object… params) ,用来完成表数据的增加、删除、更新
3.qr,qruey()方法,得到结果集
query(Connection conn,String sql ,ResultSetHandler rsh ,Object。。。parametres)
47.QueryRunner
QueryRunner 是 Apache Commons DbUtils 库中的一个类,它简化了 JDBC 操作,提供了便捷的方法来执行 SQL 查询和更新。然而,随着技术的发展,特别是关系型数据库访问模式的演进,出现了多种替代方案和技术来简化数据访问层的工作,这些新技术往往提供了更多的功能和更好的性能。
以下是几种常见的替代方案:
ORM(对象关系映射)框架:Hibernate: 一个广泛使用的ORM框架,它可以将Java对象映射到数据库表,并提供强大的查询功能。JPA (Java Persistence API): 这是一个标准的Java规范,Hibernate是其最流行的实现之一。JPA允许开发者以面向对象的方式操作数据库,而不需要直接编写SQL语句。Spring Framework 的 JdbcTemplate 和 NamedParameterJdbcTemplate:Spring 提供了 JdbcTemplate 和 NamedParameterJdbcTemplate 类,它们进一步简化了JDBC操作,提供了更高级别的抽象,并且更好地与Spring的依赖注入特性集成。MyBatis:MyBatis 是另一个持久化框架,它介于传统的JDBC和完全的ORM之间。MyBatis允许你通过XML或注解来配置原始SQL语句、存储过程以及高级映射规则。纯Java的NoSQL客户端库:如果你的应用使用的是NoSQL数据库,比如MongoDB、Cassandra等,则会有相应的Java客户端库,如MongoDB的官方Java驱动程序,这些库通常提供了比传统JDBC更自然的数据访问方式。Reactive 数据访问:随着响应式编程模型的兴起,像 R2DBC (Reactive Relational Database Connectivity) 和 Spring Data R2DBC 这样的技术为Java应用程序提供了非阻塞式的数据库交互能力。
尽管有这些替代方案,QueryRunner 仍然适用于那些需要轻量级解决方案且不希望引入复杂框架的应用场景。选择哪种技术取决于具体的需求、项目规模和个人偏好。如果你正在寻找一个更现代、功能更丰富的解决方案,上述提到的任何一种都可能是合适的替代品。
48.用户状态信息保存设计
49.查询规范
50.如何在项目中提高八股应用效率,减少犯错
51.Cookie 和 Session 区别
首先,他们两个都是用来跟踪浏览器用户身份的会话方式。
工作原理:
- Cookie:浏览器第一次发请求👉服务端创建Cookie包含用户信息👉返回给浏览器端👉浏览器再次访问(不是请求)服务端时候会携带服务端创建的Cookie(这个过程中Cookie对象传输应该是通过一个字节流+Socket实现)👉服务端通过Cookie中携带的数据区分用户
- Session:浏览器第一次发请求👉服务端创建session,同时创建一个特殊Cookie默认值name=JSESSIONID固定值 value=session对象ID,然后将Cookie发送给浏览器 ,会话域是服务端自己保存的一个用户域,所以对于用户来说,我就给他开了一个单独的空间。👉浏览器再次发请求就会携带这个默认值Cookie,服务端接收到这个特殊Cookie后,就会根据value去查对应的Session,下列两种情况会重新创建:
- name为JSESSIONID的Cookie不存在(关闭或者更换浏览器),返回中重新去创建Session和特殊Cookie
- name为JSESSIONID的Cookie存在,但是对应Session不存在(存活30min),返回中重新去创建
区别:
- Cookie数据保存在客户端,Session保存在服务端。
应用场景:
- Session:当你登陆一个网站时候,如果web服务端使用的是session,那么所有数据都保存在服务器上,客户端每次请求服务器的时候会发送当前会话SESSIONID,服务器根据当前id判断相应的用户数据标志,确定用户是否登录或者具有某种权限。由于数据是存储在服务器上面,所以你不能伪造。
- Cookie:SESSIONID是服务器和客户端连接时候随机分配的,如果浏览器使用的是cookie,那么所有数据数据都保存在浏览器端,比如你登陆以后,服务器设置了cookie的用户名,那么当你再次服务器的时候,浏览器会将用户名一块发送给服务器,这些变量有一定的特殊标记。服务器会解释为Cookie变量,所以只要不关闭浏览器,那么cookie变量一直是有效的,所以能够保证长时间不掉线。
- 如果你能够截获某个用户的cookie变量,然后伪造一个数据包发过去,那么服务器还是认为你是合法的。所以,使用cookie被攻击的可能性比较大。
- 如果cookie设置了有效值那么cookie会保存到客户端的硬盘上,下次再访问网站的时候,浏览器先检查是否有cookie,有的话就读取并发给服务器。
- 所以你在机器上保存了某个论坛cookie,有效期是一年,如果有人入侵你的机器,将你的cookie拷走,放在他机器下面,那么他登陆该网站的时候就是用的你的身份登陆的。当然伪造的时候需要注意,直接复制相关文件浏览器是不认的,他还有一个index.dat文件,存储了相关信息,所以你必须先要有该网站的cookie文件,并且要保证时间上骗过浏览器。
四、区别对比:
(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
(5)所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中
52.什么样的数据存到Cookie中?
- 身份认证:在localStorage出现之前,cookie一直背开发者所滥用,导致很多的无关紧要的数
据被请求携带到服务器。cookie也存在一些限制,每一个域下的cookie最多是4KB,
每一个域下的cookie最多存在20条。
53.什么样的数据存到Session中?
用户认证信息:当用户登录成功后,用户的ID或用户名等信息可以存储在Session中,以便在整个网站的不同页面间保持登录状态。购物车信息:电子商务网站可能会使用Session来临时存储用户的购物车内容,直到订单完成或会话结束。个性化设置:例如用户界面的偏好设置、语言选择等,这些数据可以在用户访问不同页面时提供一致的体验。临时数据:一些只需要在用户当前会话期间使用的数据,比如表单填写过程中的一些中间步骤数据。
需要注意的是,虽然Session可以方便地用于存储上述类型的数据,但为了保证应用的安全性和性能,应避免在Session中存放过多或者过大的数据,并且应该对存入Session的数据进行适当的保护,防止敏感信息泄露。
54.为什么登陆业务昨天一切正常,今天就找不到数据源了?红温下播
步骤1:查看数据库是否存活
步骤2:查看依赖和资源配置文件无果
步骤3:查看数据库访问权限是否变更:不对啊,如果IDEA能够连接数据库为什么找不到数据源,还是配置文件的问题,但是就是不知道什么问题,都没动过。
步骤4:确认是resources 文件路径问题,扫描不到了