文档工具
- Typora(本地存储)
- 语雀(云存储)
- 有道云
开发工具
- idea (java)
- vscode (大前端)
- HBuilderx (网页设计)
- WebStorm
- MySql/Navicat
- JDK8
- Maven(Gradle),NPM
开发岗位
- 方向: 全栈, java后端方向, 大前端方向(Web前端)
- 岗位分类: java开发工程师(后端), 大前端开发工程师(web前端)
- 岗位方向: 实习岗, java实训工程师, 高级工程师, 项目经理, 技术总监, 总裁, 自主创业(boss)
岗位技术栈
java技术栈
-
idea, linux(CentOS, Ubuntu), 云服务
-
Linux终端: Xshell, 宝塔, SercureCRT
-
javaSE(核心基础)
-
JDBC(数据源/连接池), Servlet, javaWeb
-
数据库:MySql, Oracle,
-
NoSql: Redis, MongoDB, Mencached, Zookeeper
-
框架:Spring, SpringMVC, SpringBoot, SpringCloud, SpringClouldAlibaba
-
持久层框架: MyBaits, MyBatisPlus, SpingData JPA
-
安全(权限)框架: SpringSecurity, Shiro, OAuth2.0
-
项目管理工具: Maven, Gradle, NPM
-
版本控制: Git, Github, Gitee
-
消息队列: Kafka, RabbitMQ, RocketMQ
-
Driud, SpringBootAdmin, SkyWalking
-
开发架构: 单体框架, 垂直架构, 分布式架构, SOA(面向服务的架构), 微服务架构
-
辅助工具: Xmind, draw.io, ProcessOn
-
运维部署: Docker, k8s
-
性能优化: SQL优化, JVM优化, Jmeter
-
服务器: Tomcat, 云服务, Nginx, Apache
前端技术栈
-
HTML/H5, css3, JavaScript, JQuery(Ajax)
-
Es6(原型, 原型链,作用域 ,闭包, 异步, this, 函数, js新特性), TS(TypeScript)
-
js框架: Vue2/Vue3, React.js, Augular, servlet
-
异步请求:Jquery(Ajax), Axios, fetch
-
跨域: 跨域问题, 同源问题, JSONP, CORS, Xss
-
H5, App, 微信小程序, UniApp
-
大前端的后端技术栈: Node.js, Express, Koa, Egg.js
-
数据库: MySql, MongoDB
-
版本控制: Git/Gitee, SVM
-
自动化构建工具: 脚手架(Vue-cli), webpack
-
UI组件: ElementUI, Bootstrap, Layui
-
服务器渲染框架: Next.js(React.js), Nuxt.js(Vue.js)
项目实训技术架构
- IDEA
- JDK8以上
- MySql8
- Tomcat9
- Maven
- Servlet/jsp, EL表达式, JSTL标签
- JDBC, DbUtils, 数据源(Druid)
- UI模板, JQuery, LayUI
- HuTool
MySql
1.概念
数据库是"按照数据结构来组织, 存储, 管理数据的仓库", 上一个可以持久化长期存储在计算机类的, 有组织的, 有共享的, 可以统一管理的数据集合
2.数据库分类
- 网状结构数据库
- 层次结构数据库
- 关系结构数据库(Oracle, MySql, DB2, SQL Server)
- 非关系型数据库: MongDB, Redis, 使用哈希表, 表中以键值(Key-Value)的方式实现特定的键和指针指向的特定数据
3. 数据库管理系统
数据库管理系统(DBMS): 管理和操作数据库的系统, 用于建立, 使用, 维护数据库, 谁数据库进行统一的管理和控制, 保证数据库的安全性和完整性
常用的数据库系统:
-
Oracle
-
DB2
-
SQL Server
-
SQLLite
-
MySql
4.SQL语句
SQL: 是结构化查询语言, 用于存储数据, 更新, 想查询和管理关系类型数据库系统的程序设计语言
通常用于对数据库的数据操作进行CRUD(增(Create), 删(Delete), 改(Update), 查(Retrieve))操作
对于数据库的操作, 在MySql的环境下进行指令操作, 都是使用";"结束
-
登录数据库
mysql -u -root -p # 回车键 Enter password: #输入密码即可Enter
-
查看MySql数据库中所有的数据库
show databases;
-
创建数据库
# create database (数据库名) create database mysql; #创建名为mysql的数据库 # 创建数据库的缩放指定数据库的字符集 create database mysql character set utf-8;
-
删除数据库
# drop database (数据库名) drop database mysql;
-
查看数据库创建信息
show create database mysql;
-
修改数据库编码信息
# 修改数据库msql的字符集为gbk alter database mysql character set gbk;
-
使用数据库
use mysql; # 当前环境下选中mysql数据库
-
查看当前使用的数据库
select database(); # 查看当前使用的数据库
-
退出DBMS
exit;
备注: DBMS不区分大小写, MySql命令以";"作为结束符
5.数据库表
任何一张表都是由行和列组成:
- 行(row): 称为一行记录/一条数据
- 列(column): 表字段
数据库表每个字段: 字段名, 数据类型, 约束等属性
- 字段名: 就是一个普通的名字, 定义要做的见名知意, 不要使用和顾问中文和关键字
- 数据类型: 字符(char), 字符串(varchar), 数字类型(int, double, float), 日期等
- 约束: 数据库约束有很多, 常用的约束有: 主键约束, 唯一约束, 非空约束
对表的操作就是对表的定义(DDL): create, drop, alter等
5.1 创建表
语法格式:
craete table 表名(
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,
约束条件
)
说明:如果数据库表由多个单词组成, 建议"_"连接, eg: cz_emp
表名禁止使用数字或者关键字或者特殊符号命名
数据库在windows系统下不区分大小写, 但在linux系统下是严格区分大小写的, 所以在数据库名, 表名, 字段名说都做到统一, 避免据节外生枝
需求:
创建一个学生表, 学号, 性别, 年龄, 电话, 出生日期, 地址
//创建数据库
create database ch_db;
//选中数据库
use ch_db;
//创建表
create table ch_student(
id int(10) primary key not null auto_increment,
username varchar(20) not null,
sex char(20),
age int (10),
phone varchar(11),
address varchar(40)
);
//查看表结构
desc ch_student;
注意:
- 在同一张表中, 字段名不能相同
- 数据类型长度和约束条件为可选参数, 字段名和字段类型是必须的
5.2 更新表
向ch_student表在添加列(字段)
语法:
# alter table table_name(表名) add column 列名(字段) 字段名
alter table ch_student add column classes varchar(20);
alter table ch_student add column birthday date;
5.3 删除列
语法:
//alter table table_name(表名) drop column 列名
//删除年龄字段
alter table ch_student drop column age;
注意:
在实际开发过程中 需求一旦确定, 表一旦设计好之后, 是很少对表的结构进行修改操作的, 因为修改的成本很高, 表的结构改了, 对应和业务逻辑的java代码也要进行大量的修改
5.4字段的约束
在创建表的时候, 可以改表的字段添加相应的约束, 添加约束的目的是为了保证表中的数据的合法性, 有效性, 完整性
- 非空约束 (not null): 约束的字段不能为空
- 唯一约束 (unique): 约束的字段值不能重复
- 主键约束 (primary key): 约束的字段既不能为空, 也不能重复 (PK)
- 外键 (foreign key) : 外键字段的约束 (FK)
6. DML操作
所谓DML操作, 就是对表记录进行读写(CRUD)的操作
6.1 添加语句
语法
insert into 表名(字段1, 字段2, 字段3, ....., 字段n) values(值1, 值2, 值3, ....., 值n);
//字段和值是一一对应, 数据类型也要相同
insert into ch_student (username, sex, age, phone, birthday, address, classes)
values ("法外狂徒张三", "男", "6", "12365478910", "2023-12-26", "翻斗花园", "翻斗幼儿园");
//添加操作时, 还可以不给表字段, 但需要给每一个字段赋值
insert into ch_student
values (0, "法外狂徒张三", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26");
insert into ch_student
values
(0, "法外狂徒张三一", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26"),
(0, "法外狂徒王五", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26"),
(0, "法外狂徒张二麻", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26"),
(0, "法外狂徒张三五", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26"),
(0, "法外狂徒张三六", "男", "6", "12365478910", "翻斗花园", "翻斗幼儿园", "2023-12-26");
6.2 修改语法
语法
update 表名 set 字段名1 = 值1, 字段名2 = 值2, 字段名3 = 值3, ..., 字段名n = 值n where id = 1;
update ch_student set classes = "翻斗小学" where id = 1;
update ch_student set username = "法外狂徒李四", classes = "翻斗小学" where id = 2;
6.3 删除语句
语法
//删除所有记录(清空)
delete from 表名;
//根据条件删除
delete from 表名 where 条件;
delete from ch_student where id = 1;
6.4 查询操作
//查询所有记录
select * from 表名;
//查询单个字段的值
select 字段名1 from 表名;
select username from ch_student;
//查多个字段的值
select 字段名1 , 字段名2 from 表名;
select username, age from ch_student;
备注:
- 任何一条sql语句都是以";"结束
- sql语句不区分大小写
在sql语句中可以使用as关键字起别名, 当然在语句中as关键字可以默认省略
select username as "姓名" from ch_student;
//或者省略as关键字
select username "姓名" from ch_student;
//或者
select username 姓名 from ch_student;
备注:
在sql语句中不使用引号也不会报错, 但按照语法来说, 还是给定义的别名使用单引号
6.5 排序查询
语法
select 列名 from 表名 order by 排序列名 [排序规则]
排序规则:
-
asc: 升序排序 (默认排序)
-
desc: 降序排序
//但进行升序排列时, 排序规则可以不显示声明, 默认为升序排序规则 select * from ch_student order by id asc; //升序 select * from ch_student order by id desc; //升序
6.6 条件查询
语法
//where条件: 在查询结果中筛选符合条件的记录
select * from 表名 where 条件
-
等值判断(=)
select * from ch_student where username = '法外狂徒李四';
-
不等值判断(>, < , >=, <=, !=, <>)
select * from ch_student where username != '法外狂徒李四'; //或者 select * from ch_student where username <> '法外狂徒李四';
-
逻辑判断(and , or, not)
//查询工资为[5000, 10000]的员工信息 select * from emp where salary>= 5000 and salary <= 10000; //查询工资为5000或者10000的员工信息 select * from emp where salary= 5000 or salary = 10000; //查询除了工资是10000的员工信息 select * from emp where salary not salary=10000;
-
区间判断(between, and)
//区间判断: 包含区间边界的两个值[5000, 10000]; select * from emp where salary between 5000 and 10000;
注意: between and 要遵循between 小值 and 大值
-
枚举查询(in (值1, 值2, 值3))
//查询工资为5000, 6000, 7000的员工 select * from emp where salary in (5000, 6000, 7000);
-
模糊查询like(_, %)
语法:
// like _ (表示单个任意字符) // like % (表示任意长度的任意字符) //查询结尾为四的字符串 尾匹配 select * from ch_student where username like '%四'; //查询以李开头的字符串 头匹配 select * from ch_student where username like '法%'; //查询包含四的字符串 select * from ch_student where username like '%四%'; //查询第二个字符为外的字符串 select * from ch_student where username like '_外';
-
分页limit
在进行数据库表查询操作中, 一般都知道使用select语句进行查询, 但是当数据量较大时, selet查询就表示很方便, 这时分页查询就派上了用场,
在MySql中使用limit关键字来进行分页. limit实现分页的方式是读取数据库表中的部分数据
语法:
//pageNum页码, pageSize每页显示记录 select * from ch_student limit 0, 3; //第一页(1-1) * 3 = 0 select * from ch_student limit 3, 3; //第二页(2-1) * 3 = 3 select * from ch_student limit 6, 3; //第三页(3-1) * 3 = 6 select * from ch_student limit 9, 3; //第三页(4-1) * 3 = 9
分页通用公式:
//pageNum: 当前页, pageSize: 每页显示的记录数 select * from 表名 limit (pageNum - 1) * pageSize, pageSize;
-
count()函数
作用: 获取数据库表的总记录
//数据库表 总记录 select count(*) from 表名; //根据字段查询总记录数 select count(username) from 表名;
Maven
Apache Maven是一个(特别是Java编程)项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象建模(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。
下载地址: Maven – Download Apache Maven
解压路径: 随意
配置环境变量:
在path中配置: 解压路径下\apache-maven\bin
测试: mvn -v
配置maven镜像
-
设置镜像资源存储路径
在setting.xml中settings标签里面配置存储地址
//设置本地仓库 <localRepository>在这里配置</localRepository>
-
配置阿里的镜像地址
//在mirror标签中配置 <mirror> <id>alimaven</id> <name>aliyun maven</name> <url> http://maven.aliyun.com/nexus/content/groups/public/ </url> <mirrorOf>all</mirrorOf> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
JDBC数据库连接操作
JDBC(java数据库连接) 是一种用于执行sql语句的javaAPI, 可以为多种关系数据库做统一的操作, 其由一组java语言编写的类分和接口组成
JDBC本质: java官方提供的一套规划(接口), 用于帮助开发人员快速实现不同关系型数据库的连接
JDBC是由多个接口和类进行功能实现
类型 | 名称 | 描述 |
---|---|---|
class | DriverManager | 管理多个数据库驱动类, 提供了获取数据库连接的方法 |
接口 | Connection | 表示数据库连接 |
接口 | Statement | 发送sql语句到数据库的工具 |
接口 | ResultSet | 保存sql查询语句的结果数据(结果集) |
class | SQLException | 处理数据库应用程序时所发生的异常 |
-
Connection对象
JDBC实现MySql连接数据库
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DbTest { private static final String URL = "jdbc:mysql://localhost:3306/ch_db"; public static void main(String[] args) throws ClassNotFoundException, SQLException { //加载驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接对象 Connection connection = DriverManager.getConnection(URL, "root", "1234"); if(connection != null){ System.out.println("数据库连接成功!"); }else { System.out.println("数据库连接失败!"); } } }
-
Statement对象
通过Connection对象获取Statement对象, 用于对数据库进行通用访问
PreparedStatement pre = connection.prepareStatement(sql); //传入sql语句
preparedstatement()方法传入sql语句可以预防sql注入
优点: 防止sql注入, 提高代码可读性, 运行效率
preparedstatement接口提供了两个方法进行数据库表的操作:
- executeQuery(): 主要用于执行查询操作, 此方法返回ResultSet对象
- executeUpdate(): 主要用于执行(添加, 修改, 删除)的操作, 执行完成之后返回int类型的结果值, 这个值是受影响的行
-
ResultSet对象
在执行查询sql后, 存放查询得到的结果集数据
ResultSet resultSet = statement.executeQuery(sql);
遍历ResultSet中的数据
ResultSet以表结构进行临时结果的存储, 需要通过JDBC API将其中的数据进行 依次获取
- 数据行指针(resultSet.next()): 初始化位置在第一行数据前, 每调用一次boolean返回值类型的next()方法, 指针向下移动一行, 结果为true表示当前行有数据
- resultSet.getXXX(“列名”): 根据列名获取数据
package com.example; import java.sql.*; public class DbTest { private static final String URL = "jdbc:mysql://localhost:3306/ch_db"; public static void main(String[] args) throws ClassNotFoundException, SQLException { //加载驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接对象 Connection connection = DriverManager.getConnection(URL, "root", "1234"); if(connection != null){ System.out.println("数据库连接成功!"); }else { System.out.println("数据库连接失败!"); } //获取Statement对象 assert connection != null; Statement statement = connection.createStatement(); //执行sql操作 String sql = "select * from ch_db.ch_student"; ResultSet resultSet = statement.executeQuery(sql); //处理结果集 while (resultSet.next()){ //判断结果集中是否有下一行 int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String sex = resultSet.getString("sex"); String phone = resultSet.getString("phone"); Date birthday = resultSet.getDate("birthday"); String classes = resultSet.getString("classes"); System.out.println(id + "\t" + username+ "\t"+ sex+ "\t"+ phone+ "\t"+ birthday+ "\t"+ classes); } //释放资源: 后进先出 resultSet.close(); statement.close(); connection.close(); } }
-
小结:
JDBC实现MySql数的步骤据库连接的步骤
- 导入数据库驱动(数据库依赖)
- 注册驱
- 获取数据库连接对象(Connection)
- 获取执行对象(PreparedStatement对象)
- 执行sql语句并返回结果
- 处理结果
- 释放资源
综合案例:
-
修改id = 8 的用户信息(修改电话, 地址信息)
public static void executeUpdateTest() throws ClassNotFoundException, SQLException { //加载驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接对象 Connection connection = DriverManager.getConnection(URL, "root", "1234"); if (connection != null) { System.out.println("数据库连接成功!"); } else { System.out.println("数据库连接失败!"); } //获取Statement对象 assert connection != null; Statement statement = connection.createStatement(); //执行sql操作 String sql = "insert into ch_db.ch_student(username, sex, phone, birthday, classes)" + "values ('马克斯', '男', '123556532', '1988-12-3', '软件1班')"; int result = statement.executeUpdate(sql); if (result > 0) { System.out.println("执行成功!"); } else { System.out.println("执行失败!"); } }
-
根据用户名来查询某条记录(李四)
-
添加一条记录
-
模糊查询(查询名字中带"三"的用户)
-
根据电话和班级查询某个用户信息
public static void executeQueryByUsername() throws ClassNotFoundException, SQLException { Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接对象 Connection connection = DriverManager.getConnection(URL, "root", "1234"); if(connection != null){ System.out.println("数据库连接成功!"); }else { System.out.println("数据库连接失败!"); } String sql = "select * from ch_db.ch_student where username = ? and classes = ?"; assert connection != null; PreparedStatement pre = connection.prepareStatement(sql); pre.setString(1, "李四"); pre.setString(2, "21软件1"); ResultSet resultSet = pre.executeQuery(); while (resultSet.next()){ //判断结果集中是否有下一行 int id = resultSet.getInt("id"); String username = resultSet.getString("username"); String sex = resultSet.getString("sex"); String phone = resultSet.getString("phone"); Date birthday = resultSet.getDate("birthday"); String classes = resultSet.getString("classes"); System.out.println(id + "\t" + username+ "\t"+ sex+ "\t"+ phone+ "\t"+ birthday+ "\t"+ classes); } }
数据库连接池
常用的数据库连接池有: DBCP, C3PO, Druid, HikariCP(SpringBoot)
Druid连接池
Druid: 阿里开源数据库连接池, 功能强大, 是java语言最好的数据库连接池之一, 同时加入了日志监控, 可以很好的监控数据库连接qing’k和sql语句的执行情况
使用步骤:
-
导入Druid依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.20</version> </dependency>
-
定义连接数据库的配置文件
在resource文件夹中, 创建druid.properties
driverClassName = com.mysql.cj.jdbc.Driver url = jdbc:mysql://localhost3306/ch_db username = root password = 1234
-
加载配置文件
-
获取连接池
-
通过连接池获取连接
单元测试
@Test
public void jdbcTest() throws Exception {
//获取配置文件流对象
InputStream inputStream = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
//创建Properties对象加载配置文件
Properties properties = new Properties();
properties.load(inputStream);
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//获取连接对象
Connection connection = dataSource.getConnection();
System.out.println(connection);
if (connection != null){
System.out.println("连接数据库成功!");
}else {
System.out.println("连接数据库失败!");
}
}
DBUtils工具类
如果只使用JDBC进行开发, 通过其学习和实验发现进行相关CRUD操作时, 存在大量冗余代码, 为了简化JDBC是实使用和开发, 可以采用Apache common组件: DBUtils工具类实现.
DBUtils对JDBC的操作进行优化和封装, 其提供了三个核心功能
- QueryRunner: 提供了对sql语句操作的API
- ResultSetHandler: 用于定义select操作后结果集的处理
- DBUtils类: 关闭资源和事物处理的方法
加载DBUtils工具类的依赖
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
1. Update
public int update(java.lang.String sql, java.lang.Object... params) throws java.sql.SQLException { /* compiled code */ }
备注:
- update()方法用于执行DML(增, 删, 改)的操作
- Object… params: 动态参数(动态数组)
测试案例:
@Test
public void queryRunnerUpdate() throws SQLException {
QueryRunner queryRunner = new QueryRunner( DruidUtils.getDataSource());
String sql = "update ch_db.ch_student set username = ?, age = ? where id = ?";
Object[] object = {"胡爷爷", 59, 11};
int result = queryRunner.update(sql, object);
if (result > 0){
System.out.println("更新成功!");
}else {
System.out.println("更新失败");
}
}
QueryRunner类基于update()的通用性操作封装的方法
public class BaseDao {
static QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
/**
*
* @param sql
* @param objects
* @return 增删改的结果集
* @throws SQLException
*/
public static int update(String sql, Object... objects) throws SQLException {
return queryRunner.update(sql, objects);
}
}
2. query()
public <T> T query(java.lang.String sql, org.apache.commons.dbutils.ResultSetHandler<T> rsh) throws java.sql.SQLException { /* compiled code */ }
通过对底层源代码的分析, query()方法的结果是, 其通过ResultSetHandler接口的实现对结果进行预处理
开发过程中常用的实现方式有:
- ArrayListHandler: 将结果集中的每一条记录封装到一个Object[]数组中, 再将这些数组再次封装到List集合中
- BeanListHandler: 加结果集中的每一条记录封装到一个指定的JavaBean中, 再将JavaBean封装到List集合
- ScalarHandler: 用于单数据, 可以用于获取中记录数
单元测试:
@Test
public void queryArrayListHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner( DruidUtils.getDataSource());
String sql = "select * from ch_db.ch_student";
//将结果集的封装到Object数组中
List<Object[]> list = queryRunner.query(sql, new ArrayListHandler());
for (Object[] objects:list){
System.out.println(Arrays.toString(objects));
}
}
@Test
public void queryBeanListHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner( DruidUtils.getDataSource());
String sql = "select * from ch_db.ch_student";
List<Student> list = queryRunner.query(sql, new BeanListHandler<Student>(Student.class));
for (Student student : list){
System.out.println(student.toString());
}
}
@Test
public void queryScalarhandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql = "select count(*) from ch_db.ch_student";
long count = queryRunner.query(sql, new ScalarHandler<>());
System.out.println("总记录数:" + count);
}
总结:
使用Druid和DBUtils简化JDBC的操作, 封装了通用性的实现类, 但在实际开发过程中, 涉及到的业务和模块非常复杂, 为了更好的进行业务开发和后期的维护和迭代, 其需要进一步统一化的操作和分层组织:
企业开发过程中的一些行为规划:
- 项目名称: 全部字母小写, 不要使用中文, 数组, 特殊符号等相关来命名
- 包名: com.项目名称(公司名称) .具体名称 eg:com.ch.bean
- 类名: 类名首字母大写, 采用大驼峰命名规则: eg: StudentDao
- 方法名: 首字母小写, 采用小驼峰命名规则: eg: findById()
- 变量名: 采用小驼峰命名规则, 不要包含中文, 数组, 特殊符号等
- 常量: 每个单词都是大写
分层架构
在软件体系架构设计中, 分层式架构是最常见, 也是最重要的一种架构, 分层架构一般分为三层, 从下至上分别为:
- 数据访问层: 为业务逻辑层和表示层提供数据
- 业务逻辑层: 主要针对具体的问题的操作, 也可以理解为对数据层的操作
- 表示层: 展示数据
在实际项目中的分层结构如下:
- com.ch.dao: Dao包(接口包) /接口实现
- com.ch.utils: 工具包
- com.ch.bean: 实体包
- com.ch.servlet: 业务包
封装通用的Dao接口
public class BaseDao {
static QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
/**
*
* @param sql
* @param objects
* @return 增删改的结果集
* @throws SQLException
*/
public static int update(String sql, Object... objects) throws SQLException {
return queryRunner.update(sql, objects);
}
/**
*
* @param type
* @param sql
* @param objects
* @return 返回单个对象
* @param <T>
* @throws SQLException
*/
public <T>T query(Class<T> type, String sql, Object... objects) throws SQLException {
return queryRunner.query(sql, new BeanHandler<T>(type), objects);
}
/***
*
* @param type
* @param sql
* @param objects
* @return 列表
* @param <T>
* @throws SQLException
*/
public <T> List<T> queryAll(Class<T> type, String sql, Object... objects) throws SQLException {
return queryRunner.query(sql, new BeanListHandler<>(type), objects);
}
/**
*
* @param sql
* @param objects
* @return 返回行数据
* @param <T>
* @throws SQLException
*/
public <T> List<T> selectCount(String sql, Object... objects) throws SQLException {
return queryRunner.query(sql, new ScalarHandler<>(), objects);
}
}
案例项目分析
案例引入
1. 商城类型:
- B2B: 商家对商家 eg: 阿里巴巴, 慧聪网
- B2C: 商家对客户 eg: 当当网, 京东
- C2C: 客户对客户 eg: 淘宝, 拼多多
- O2O: 线上线下相结合 eg: 美团, 滴滴
2. 常见模块
- 商品管理: 后台商品库存管理, 上货, 出货, 编辑商品和商品分类管理等
- 订单管理
- 支付管理
- 物流管理
- 会员模块
- 广告管理
3. 项目功能介绍
本系统主要分为前台和后台功能两个大模块
其中前台功能主要的模块有: 商品列表, 商品分类查看, 我的购物信息, 个人信息, 广告位
后台管理主要模块有: 商品信息管理, 用户信息管理, 管理员个人中心
管理员: 管理是商品, 管理用户, 个人信息, 广告位, 数据中心
用户用例图
前置条件: 用户注册成功
后置条件: 用户登录成功
重点: 查看商品信息, 把商品加入购物车, 对商品进行结算和支付
主要事件流程:
- 加入登录界面
- 登陆成功, 用例开始
- 登陆成功跳转到首页
- 分类列表查看商品信息
- 点击"商品图片"查看商品详细信息
- 点击"加入购物车"把商品记录购物车
- 点击"我的购物车"把商品查看购物车商品信息
- 点击"结算"即可结算商品
- 点击"我的订单"可以查看结算商品的信息
- 点击"支付"即可对商品进行支付
- 点击删除购物车中的商品
- 点击"个人信息"查看或者修改
4. 数据库设计
-
用户表 (tb_user)
字段 类型 主键 约束 备注 id int 是 自增 序号 username varchar(20) not null 用户昵称 password varchar(60) not null 用户密码 email varchar(60) not null gender varchar(2) 性别 flag int 默认值 状态标记: 0未激活, 1激活, 2无效 role int 角色: 0管理员, 1会员 code varchar(100) 激活码 picture varchar(50) 图像 createtime varchar(50) 注册时间 -
商品表 (tb_goods)
字段 类型 主键 约束 备注 id int 是 自增 主键 name varchar(50) not null 类型名称 pubdate varchar(20) not null 时间 picture varchar(20) not null 图片 price double(7, 2) not null 价格 star double(2, 1) 评分 info varchar(60) 商品信息 typeid int 外键 商品类型 gunm int 默认1024 商品数量[库存] gstate int 默认0 商品状态: 0上架, 1下架 createtime varchar(50) not null 入库时间 -
商品类型表 (tb_goods_type)
字段 类型 主键 约束 备注 id int 是 自增 主键 name varchar(50) not null 类型名称 nioc varchar(20) not null 图标 level int not null 类型级别 parent int not null 上一级序号: 默认0 -
购物车表 (tb_cart)
字段 类型 主键 约束 备注 id int 是 自增 主键 pid int 是 外键 商品序号 num int not null 数量 money double(8,2) 金额 -
订单表 (tb_order)
字段 类型 主键 约束 备注 id varchar(80) 是 自增 订单编号 uid int 外键 用户序号 money double(8,2) not null 订单总金额 ordertime datatime not null 订单时间 status int 订单状态 aid int 外键 收货地址序号 -
订单详情表 (tb_orderdetail)
字段 类型 主键 约束 备注 id int 是 自增 主键 oid int 外键 订单id pid int 外键 商品id num int not null 购买数量 money double(8,2) not null 金额 -
地址表 (tb_address)
字段 类型 主键 约束 备注 id int 是 自增 主键 detail varchar(80) not nulll 详细地址 name varchar(20) not null 收件人姓名 phone varchar(20) not null 手机号码 level int not null 地址顺序 1是最高 creatime varchar(20) 创建时间
Hutool工具集
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
官网API: 简介 | Hutool
验证码测试:
//URL: http://localhost:8080/chMaven_war/ServletCapthcha
@WebServlet(value = "/ServletCapthcha", name = "ServletCapthcha")
public class ServletCaptcha extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//定义图形验证码的长、宽、验证码字符数、干扰线宽度
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);
OutputStream out = resp.getOutputStream();
//写到浏览器
captcha.write(out);
//获取生成的验证码
String code = captcha.getCode();
System.out.println("====> 验证码: " + code);
//验证图形验证码的有效性, 返回boolean值
//验证码验证是否正确, 建议忽略大小写
System.out.println(captcha.verify(code));
out.close();
}
}