前言:
该系统总代码行数约2100行,采用技术栈为Swing框架与MySQL,编码环境为Eclipse。实现的功能有:用户注册、登陆;货物入仓、货物出仓,货物信息更新与货物信息查询(对货物信息的增删改查)。
对于Java大作业或课程结课作业而言,须侧重分析基本语法,面向对象设计三要素(封装、继承、多态),基本泛型集合的简单使用,数据库接口的操作与工程设计规范;对于面向对象分析与设计而言,须侧重分析用例图与用例建模,类图与对象图之间的分析与设计,状态图;对于毕业设计而言,可在该系统基础上增加用户权限与角色管理,货物信息分析与打印导出,更改系统偏好设置来达到论文设计要求。
该系统主要分为controller
层与service
层(笔者由于开发工具原因没有单独对View
分层,但不影响系统工程性),controller
层绘制UI,接收数据并调用service
层实例对象的具体业务方法,service
层中的接口方法编写业务语句,调用dao
层使其直接与数据库底层操作,并按此逆顺序将数据返回至UI。
一:需求分析
1:系统需实现的功能
- 系统需提供注册功能与登陆功能以进入主管理界面
- 系统需提供货物信息入仓功能
- 系统需根据精准条件将货物信息出仓
- 系统需根据精准条件更新货物信息
- 系统需根据精准条件查询货物信息
2:系统模块结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202194604827.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
3:功能需求
- 提供注册账户功能
- 提供根据输入账户验证登陆功能
- 提供根据输入的全部信息将货物入仓功能
- 提供根据id将货物出仓功能
- 提供根据货物名称将货物出仓功能
- 提供根据销售者将货物出仓功能
- 提供根据购买日期将货物出仓功能
- 提供根据id更新货物名称功能
- 提供根据id更新货物销售者功能
- 提供根据id更新货物购买单价功能
- 提供根据id更新货物购买数量功能
- 提供根据id更新货物使用数量功能
- 提供根据id更新货物销售单价功能
- 提供根据日期查询货物信息功能
- 提供根据销售者查询货物信息功能
- 提供根据货物名称查询货物信息功能
- 提供根据id查询货物信息功能
4:软件/硬件需求
- 操作系统平台不限(OS X/ Linux/ Windows)
- Java JDK 1.7及以上
- MySQL 8.0及以上
二:系统设计思路
1:数据库设计
系统主要服务两个实体对象,一个为“登陆者”,另一个即为“货物”,那么可设计两个数据表:
user_login
stock_detail
user_login
内应存在关于账户与密码的字段,即如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202200035936.jpg#pic_center)
stock_detail
内信息较为丰富,包括并不限于如下图所示信息:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202200224774.jpg#pic_center)
2:.dao设计
该层主要与数据库直接操作以得到connection
来进行statement
。局部代码如下:
public ResultSet getResult(String sqlContent){
try{
resultSet = statement.executeQuery(sqlContent);
return resultSet;
} catch(Exception e){
e.printStackTrace();
return null;
}
}
说明:该方法返回一个ResultSet
对象,接收参数为要执行的SQL语句。
3:.service设计
该层主要定义接口,提供抽象方法,供.service.impl实现。局部实例代码如下:
LoginService.java:
public interface LoginService {
public int login(String account, String password);
public int register(String account, String password);
}
说明:第一个抽象方法接收两个参数用户验证登陆,返回类型为int
类型。
4:.service.impl设计
该层主要用来实现(implements
).service
层提供的接口并重写其抽象方法。局部实例代码如下:
LoginService.java:
public class LoginServiceImpl implements LoginService{
@Override
public int login(String account, String password) {
DBUtil db = new DBUtil();
String sql = "select * from user_login where account = '" + account + "' and password = '" + password + "';";
ResultSet resultSet = db.getResult(sql);
try {
if(resultSet.next()){
return 1;
} else{
return 0;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.close();
}
return 0;
}
@Override
public int register(String account, String password) {
DBUtil db = new DBUtil();
String sql = "INSERT INTO `stock_manager`.`user_login` (`account`, `password`) VALUES ('" + account + "', '" + password + "');";
try{
db.updateData(sql);
return 1;
} catch(Exception e){
e.printStackTrace();
} finally {
db.close();
}
return 0;
}
}
说明:第一个重写方法先拿到DBUtil()
实例对象,后拼接一SQL语句从user_login
表中检索是否存在该用户,如果结果集(ResuleSet
)不为空,即存在该用户,就返回1,否则0。
5:.controller设计
该层用于绘制UI及控制逻辑。局部示例代码如下:
LoginFrame.java:
public class LoginFrame {
private JFrame frmLogin;
private JTextField accountTextField;
private JPasswordField passwordField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
LoginFrame window = new LoginFrame();
window.frmLogin.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public class Login implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
LoginServiceImpl loginServiceImpl = new LoginServiceImpl();
int status = loginServiceImpl.login(accountTextField.getText().toString(), passwordField.getText().toString());
if(status == 1){
MainFrame mainFrame = new MainFrame(accountTextField.getText().toString());
mainFrame.frmStockManager.setVisible(true);
frmLogin.dispose();
} else{
JOptionPane.showMessageDialog(null, "Login Failed!");
}
}
}
public class Register implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
LoginServiceImpl loginServiceImpl = new LoginServiceImpl();
int status = loginServiceImpl.register(accountTextField.getText().toString(), passwordField.getText().toString());
if(status == 1){
JOptionPane.showMessageDialog(null, "Register Succeed!");
} else{
JOptionPane.showMessageDialog(null, "Register Failed!");
}
}
}
public LoginFrame() {
initialize();
}
private void initialize() {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
}
frmLogin = new JFrame();
frmLogin.setTitle("Login");
frmLogin.setBounds(100, 100, 514, 264);
int windowWidth = frmLogin.getWidth();
int windowHeight = frmLogin.getHeight();
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
frmLogin.setLocation(screenWidth/2-windowWidth/2, screenHeight/2-windowHeight/2);
frmLogin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmLogin.getContentPane().setLayout(null);
JLabel accountLabel = new JLabel("Account");
accountLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
accountLabel.setBounds(192, 44, 54, 15);
frmLogin.getContentPane().add(accountLabel);
JLabel passowrdLabel = new JLabel("Password");
passowrdLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
passowrdLabel.setBounds(192, 108, 65, 15);
frmLogin.getContentPane().add(passowrdLabel);
accountTextField = new JTextField();
accountTextField.setFont(new Font("宋体", Font.PLAIN, 12));
accountTextField.setBounds(292, 41, 165, 24);
frmLogin.getContentPane().add(accountTextField);
accountTextField.setColumns(10);
JButton loginButton = new JButton("Login");
loginButton.addActionListener(new Login());
loginButton.setFont(new Font("微软雅黑", Font.PLAIN, 12));
loginButton.setBounds(192, 163, 93, 23);
frmLogin.getContentPane().add(loginButton);
JButton registerButton = new JButton("Register");
registerButton.addActionListener(new Register());
registerButton.setFont(new Font("微软雅黑", Font.PLAIN, 12));
registerButton.setBounds(364, 163, 93, 23);
frmLogin.getContentPane().add(registerButton);
JLabel lblNewLabel_2 = new JLabel("Stock");
lblNewLabel_2.setFont(new Font("微软雅黑 Light", Font.BOLD | Font.ITALIC, 28));
lblNewLabel_2.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel_2.setForeground(Color.BLUE);
lblNewLabel_2.setBounds(38, 44, 86, 55);
frmLogin.getContentPane().add(lblNewLabel_2);
JLabel lblManager = new JLabel("Manager");
lblManager.setFont(new Font("微软雅黑 Light", Font.PLAIN, 29));
lblManager.setHorizontalAlignment(SwingConstants.CENTER);
lblManager.setForeground(new Color(0, 191, 255));
lblManager.setBounds(10, 94, 145, 55);
frmLogin.getContentPane().add(lblManager);
passwordField = new JPasswordField();
passwordField.setFont(new Font("宋体", Font.PLAIN, 12));
passwordField.setBounds(292, 105, 165, 24);
frmLogin.getContentPane().add(passwordField);
}
}
说明:Login
类实现的逻辑为:根据返回数据是1或0来判断是否登陆成功,如果成功就启动主窗口,否则就显示JOptionPane
提示用户登陆失败。
6:.util设计
该层用以提供工具类。其中一个业务逻辑为:自动生成不重复自增的货物id
。示例文件如下:
GenerateStockId.java:
public class GenerateStockId {
public static long getStockId(){
long id = 0;
DBUtil db = new DBUtil();
String sql = "select * from stock_detail order by stock_id desc limit 1;";
ResultSet resultSet = db.getResult(sql);
try {
while(resultSet.next()){
long getId = resultSet.getInt("stock_id");
getId++;
id = getId;
}
return id;
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.close();
}
return id;
}
}
注意:这里提供的是静态方法,直接调用即可。
三:类图
这里只展示局部文件的类图
MainFrame.java类图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202210409948.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
SearhFrame.java类图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202210558570.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
四:工程结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202210721278.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
五:业务层分析
这里以查询功能为例分析。
1:定义接口
SearchService.java:
public interface SearchService {
public List<List<String>> queryById(String id);
public List<List<String>> queryByName(String name);
public List<List<String>> queryBySeller(String seller);
public List<List<String>> queryByDate(String date);
}
说明:这里定义四个抽象方法,其作用通过名称也很容易得出。以第一个抽象方法为例,其接收参数为id
,返回类型为泛型集合
2:接口实现类
SearchServiceImpl.java:
public class SearchServiceImpl implements SearchService{
@Override
public List<List<String>> queryById(String id) {
List<List<String>> list = new ArrayList<List<String>>();
DBUtil db = new DBUtil();
String sql = "select * from stock_detail where stock_id = '" + id + "';";
ResultSet resultSet = db.getResult(sql);
try {
while(resultSet.next()){
List<String> sList = new ArrayList<String>();
sList.add(String.valueOf(resultSet.getInt("stock_id")));
sList.add(resultSet.getString("stock_name"));
sList.add(resultSet.getString("stock_seller"));
sList.add(resultSet.getString("stock_purchase_amount"));
sList.add(resultSet.getString("stock_current_amount"));
sList.add(resultSet.getString("stock_purchase_price"));
sList.add(resultSet.getString("stock_sell_price"));
sList.add(resultSet.getString("stock_purchase_date"));
sList.add(resultSet.getString("stock_used_amount"));
list.add(sList);
sList = null;
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.close();
}
return null;
}
...
}
说明:这里先定义一个泛型集合,其作用是存入从结果集里迭代取出的货物数据信息。在结果集里面,先定义一参数为String类型的泛型集合,其作用是存入货物数据信息,每次迭代完成设置其为空以便下次迭代继续。
3:如何使用
实例化SearchServiceImpl
并调用其重写方法并将返回类型赋予泛型集合即可。
六:运行效果
1:登陆
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212402703.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
2:登陆成功后进入主界面
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212412320.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
3:登陆失败
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212420266.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
4:将货物信息入仓
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212429619.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212443611.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
5:根据id将货物信息更改
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212834314.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
6:根据日期查询货物信息
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020120221261620.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
7:根据id将货物出仓
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201202212927346.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tpY2luaW8=,size_16,color_FFFFFF,t_70#pic_center)
七:总结
- 良好的工程结构是软件工程必须掌握的目标,其作用就是减少代码间耦合、增加内聚、提高利用率
- 完备的软件需求分析、软件设计、数据库设计与分析是系统构建的必要条件。残缺、不充分的需求分析与设计只会带来灾难
- 提高人机交互的效率是软件设计的一个目标。良好的人际交互界面会使软件使用臃肿度降低
- 充分利用面向对象的三个基本要素,使其达到在软件设计、软件开发、软件测试、软件修改流程中的得力助手。
有需要的读者可以留言获取。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)