该系统总代码行数约2100行,采用技术栈为Swing框架与MySQL,编码环境为Eclipse。实现的功能有:用户注册、登陆;货物入仓、货物出仓,货物信息更新与货物信息查询(对货物信息的增删改查)。
对于Java大作业或课程结课作业而言,须侧重分析基本语法,面向对象设计三要素(封装、继承、多态),基本泛型集合的简单使用,数据库接口的操作与工程设计规范;对于面向对象分析与设计而言,须侧重分析用例图与用例建模,类图与对象图之间的分析与设计,状态图;对于毕业设计而言,可在该系统基础上增加用户权限与角色管理,货物信息分析与打印导出,更改系统偏好设置来达到论文设计要求。
该系统主要分为controller
层与service
层(笔者由于开发工具原因没有单独对View
分层,但不影响系统工程性),controller
层绘制UI,接收数据并调用service
层实例对象的具体业务方法,service
层中的接口方法编写业务语句,调用dao
层使其直接与数据库底层操作,并按此逆顺序将数据返回至UI。
系统主要服务两个实体对象,一个为“登陆者”,另一个即为“货物”,那么可设计两个数据表:
user_login
stock_detail
user_login
内应存在关于账户与密码的字段,即如下图所示:
stock_detail
内信息较为丰富,包括并不限于如下图所示信息:
该层主要与数据库直接操作以得到connection
来进行statement
。局部代码如下:
public ResultSet getResult(String sqlContent){
try{
resultSet = statement.executeQuery(sqlContent);
return resultSet;
} catch(Exception e){
e.printStackTrace();
return null;
}
}
说明:该方法返回一个ResultSet
对象,接收参数为要执行的SQL语句。
该层主要定义接口,提供抽象方法,供.service.impl实现。局部实例代码如下:
LoginService.java:
public interface LoginService {
public int login(String account, String password);
public int register(String account, String password);
}
说明:第一个抽象方法接收两个参数用户验证登陆,返回类型为int
类型。
该层主要用来实现(implements
).service
层提供的接口并重写其抽象方法。局部实例代码如下:
LoginService.java:
public class LoginServiceImpl implements LoginService{
@Override
public int login(String account, String password) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
db.close();
}
return 0;
}
@Override
public int register(String account, String password) {
// TODO Auto-generated method stub
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。
该层用于绘制UI及控制逻辑。局部示例代码如下:
LoginFrame.java:
public class LoginFrame {
private JFrame frmLogin;
private JTextField accountTextField;
private JPasswordField passwordField;
/**
* Launch the application.
*/
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) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
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!");
}
}
}
/**
* Create the application.
*/
public LoginFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
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) {
// java.util.logging.Logger.getLogger(RevertSql.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
// java.util.logging.Logger.getLogger(RevertSql.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
// java.util.logging.Logger.getLogger(RevertSql.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
// java.util.logging.Logger.getLogger(RevertSql.class.getName()).log(java.util.logging.Level.SEVERE, null, 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
提示用户登陆失败。
该层用以提供工具类。其中一个业务逻辑为:自动生成不重复自增的货物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) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
db.close();
}
return id;
}
}
注意:这里提供的是静态方法,直接调用即可。
这里只展示局部文件的类图
MainFrame.java类图:
SearhFrame.java类图:
这里以查询功能为例分析。
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
,返回类型为泛型集合
SearchServiceImpl.java:
public class SearchServiceImpl implements SearchService{
@Override
public List<List<String>> queryById(String id) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
db.close();
}
return null;
}
...
}
说明:这里先定义一个泛型集合,其作用是存入从结果集里迭代取出的货物数据信息。在结果集里面,先定义一参数为String类型的泛型集合,其作用是存入货物数据信息,每次迭代完成设置其为空以便下次迭代继续。
实例化SearchServiceImpl
并调用其重写方法并将返回类型赋予泛型集合即可。
有需要的读者可以留言获取。