Welcome to Yumao′s Blog.
T-ELTS Project Day02
====================
1. MVC 架構應用
2. Swing 控件事件響應
3. MVC 登錄流程實現
4. 實現退出系統的功能
5. 裝載用戶信息到用戶集合 , 從文件中加載用戶數據到users集合
6. 利用用戶數據實現登錄業務邏輯
7. 系統配置文件的加載
8. 創建整合測試 Main.class
9. 參考實現裝載Question 的方法 loadQuestions();
1. MVC 架構應用
1) Module 業務模型: 軟件核心功能的抽象,封裝軟件核心功能.
如: 註冊, 登錄, 開始考試, 交卷等
2) View 視圖 (表現): 軟件的界面視圖, 用來呈現用戶數據狀態,
接受用戶請求. 界面中只包含界面顯示處理邏輯.
3) Controller: 控制器: 耦合界面與業務模型. 響應處理用戶請求,
將用戶數據和請求轉發給業務模型, 根據業務模型的處理結果, 更新
轉發視圖界面. 控制器中包含界面的控制邏輯.
4) MVC 請求流程: 用戶訪問View, 發起請求, 請求由控制器處理,
控制器請求業務模型完成業務處理, 控制器根據業務處理結果更新用戶
界面.
核心業務抽象(接口) ExamService
包含方法
User login(int id, String pwd)
throws IdOrPwdException;
2. Swing 控件事件響應
1) 發生事件時候回調接口方法
login.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Login Click");
}
});
2) 事件方法中不要放置過多邏輯代碼
3. MVC 登錄流程實現
1)增加LoginFrame界面登錄事件響應代碼:
login.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
clientContext.login();//將請求轉發給控制器
}
});
2)在 LoginFrame 界面增加 控制器(ClientContext) 的引用和
對象注入代碼
private ClientContext clientContext;
public void setClientContext(ClientContext context) {
this.clientContext = context;
}
3) 創建控制器類ClientContext類, 添加登錄響應方法
public void login(){
//System.out.println("Login ");
try{
int id = loginFrame.getUserId();
String pwd = loginFrame.getPwd();
User user = examService.login(id, pwd);
//登錄成功
loginFrame.setVisible(false);
menuFrame.updateView(user);
menuFrame.setVisible(true);
}catch(IdOrPwdException e){
//登錄失敗
JOptionPane.showMessageDialog(
loginFrame, e.getMessage());
}
}
4) 創建控制器類ClientContext類, 中添加界面對象引用和
注入方法. 達到控制器能夠操作這些對象的目的
private LoginFrame loginFrame;
private MenuFrame menuFrame;
private ExamFrame examFrame;
private WelcomeWindow welcomeWindow;
public void setExamFrame(ExamFrame examFrame) {
this.examFrame = examFrame;
}
//IOC
public void setLoginFrame(LoginFrame loginFrame) {
this.loginFrame = loginFrame;
}
public void setMenuFrame(MenuFrame menuFrame) {
this.menuFrame = menuFrame;
}
public void setWelcomeWindow(WelcomeWindow welcomeWindow) {
this.welcomeWindow = welcomeWindow;
}
5) 為登錄界面增加方法, 用來獲取用戶的ID和PWD
//務必將idField 引用到界面控件對象
private JTextField idField;
public int getUserId() {
String str = idField.getText();
return Integer.parseInt(str);
}
//務必將pwdField 引用到界面控件對象
private JPasswordField pwdField;
public String getPwd() {
char[] pwd = pwdField.getPassword();
return new String(pwd);
}
6) 增加業務處理模型接口 ExamService, 並且提供登錄方法
/** 考試軟件的核心業務模型 */
public interface ExamService {
User login(int id, String pwd)
throws IdOrPwdException;
}
7) 為ClientContext 增加業務層接口的引用
private ExamService examService;
public void setExamService(ExamService examService) {
this.examService = examService;
}
8) 為MenuFrame界面增加更新用戶信息的方法 updateView
//務必將info 引用到界面控件對象
private JLabel info;
public void updateView(User user) {
String str = "歡迎 "+user+" 參加殺手考試!";
info.setText(str);
}
9) 為ClientContext 增加show() 方法, 用來顯示軟件界面.
public void show(){
loginFrame.setVisible(true);
}
10) 創建LoginTest, 創建ExamService測試實現. 組裝對象, 測試軟件
public class MVCDemo {
public static void main(String[] args) {
//初始化軟件組件(零件)
LoginFrame loginFrame = new LoginFrame();
ExamFrame examFrame = new ExamFrame();
MenuFrame menuFrame = new MenuFrame();
WelcomeWindow welcomeWindow = new WelcomeWindow();
ClientContext clientContext = new ClientContext();
ExamService service = new ExamServiceDemo();
//組裝組件
loginFrame.setClientContext(clientContext);
clientContext.setExamService(service);
clientContext.setLoginFrame(loginFrame);
clientContext.setExamFrame(examFrame);
clientContext.setMenuFrame(menuFrame);
clientContext.setWelcomeWindow(welcomeWindow);
//啟動軟件界面
clientContext.show();
}
static class ExamServiceDemo implements ExamService{
public User login(int id, String pwd)
throws IdOrPwdException {
if(id==1000 && pwd.equals("1234")){
return new User("Robin", 1000, "1234");
}
throw new IdOrPwdException("用戶名/密碼錯誤!");
}
}
}
4. 實現退出系統的功能
1) 為ClientContext添加exit方法
public void exit(JFrame from) {
int val = JOptionPane
.showConfirmDialog(from, "走嗎?");
if(val==JOptionPane.YES_OPTION){
System.exit(0);
}
}
2) 綁定到 登錄界面的cancel 按鈕上
cancel.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
clientContext.exit(LoginFrame.this);
}
});
5. 裝載用戶信息到用戶集合 , 從文件中加載用戶數據到users集合
1) 增加類EntityContext實現數據訪問功能
private HashMap users =
new HashMap();
private Config config;
public EntityContext(Config config) {
this.config = config;
loadUsers(config.getString("UserFile"));
//loadQuestions("corejava.txt");
}
public User getUser(int id){
return users.get(id);
}
/** 從文件中加載用戶數據到users集合 */
private void loadUsers(String filename){
try {
BufferedReader in =
new BufferedReader(new InputStreamReader(
new FileInputStream(filename), "GBK"));
String str;
while((str=in.readLine())!=null){
if(str.startsWith("#")){
continue;
}
if(str.trim().equals("")){
continue;
}
User u = parseUser(str);
users.put(u.getId(), u);
}
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** 1000:寧麗娟:1234:13810381038:ninglj@tarena.com.cn */
private User parseUser(String str) {
//1000:寧麗娟:1234:13810381038:ninglj@tarena.com.cn
//用正則表達式建議輸入規則
String[] data = str.split(":");
User u = new User();
u.setId(Integer.parseInt(data[0]));
u.setName(data[1]);
u.setPasswd(data[2]);
u.setPhone(data[3]);
u.setEmail(data[4]);
return u;
}
2) 測試加載過程和結果
public static void main(String[] args) {
EntityContext ctx = new EntityContext(new Config("client.properties"));
ctx.loadUsers("user.txt");
System.out.println(ctx.users);
}
6. 利用用戶數據實現登錄業務邏輯
1) 實現業務功能實現類 ExamServiceImpl 的login方法
/** 登錄業務邏輯實現 */
public User login(int id, String pwd)
throws IdOrPwdException {
User user = entityContext.getUser(id);
if(user==null){
throw new IdOrPwdException("查無此人!");
}
if(user.getPasswd().equals(pwd)){
return user;//登錄成功
}
throw new IdOrPwdException("密碼錯誤!");
}
2) 實例EntityContext 的注入方法
private EntityContext entityContext;
public void setEntityContext(EntityContext entityContext) {
this.entityContext = entityContext;
}
7. 系統配置文件的加載
1) Properties 類繼承於Hashtable 是一個散列表.
2) Properties 提供了load方法可以將 client.properties 文件
讀取為散列表對象, 簡潔方便
3) Properties 提供散列表查找方法 getProperty(key) 讀取key
對應的value值.
4) 創建Config 類封裝Properties 方便配置文件的讀取:
public class Config {
//private String file;
private Properties cfg = new Properties();
public Config(String file){
try {
cfg.load(new FileInputStream(file));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public String getString(String key){
return cfg.getProperty(key);
}
public int getInt(String key){
return Integer.parseInt(cfg.getProperty(key));
}
public double getDouble(String key){
return Double.parseDouble(getString(key));
}
}
8. 創建整合測試 Main.class
public static void main(String[] args) {
//初始化軟件組件(零件)
LoginFrame loginFrame = new LoginFrame();
ExamFrame examFrame = new ExamFrame();
MenuFrame menuFrame = new MenuFrame();
WelcomeWindow welcomeWindow = new WelcomeWindow();
ClientContext clientContext = new ClientContext();
ExamServiceImpl service = new ExamServiceImpl();
Config config = new Config("client.properties");
EntityContext entityContext = new EntityContext(config);
//組裝組件
service.setEntityContext(entityContext);
loginFrame.setClientContext(clientContext);
clientContext.setExamService(service);
clientContext.setLoginFrame(loginFrame);
clientContext.setExamFrame(examFrame);
clientContext.setMenuFrame(menuFrame);
clientContext.setWelcomeWindow(welcomeWindow);
//啟動軟件界面
clientContext.show();
}
9. 參考實現裝載Question 的方法 loadQuestions();
1) 實現 loadQuestions() 方法
2) 使用main方法測試
public static void main(String[] args) {
EntityContext ctx = new EntityContext(new Config("client.properties"));
//ctx.loadUsers("user.txt");
System.out.println(ctx.users);
System.out.println(ctx.questions);
}
10 為MenuFrame 添加退出功能