接着前面的登录模块的进化史,带大家回顾java学习历程(一)
前面我们去实现登录功能,都是想着要完成这个功能,直接在处理实际业务的类中去开始写具体的代码一步步实现,也就是面向过程的编程。
那么现在我们站在设计的角度上去实现该如何做呢?实际上在项目开发的时候,需求规划和数据库设计好之后,我们开始写代码,往往只用写一些接口出来,接口里面只有一些各个业务对应的空方法,没有具体的实现,在架构师进行接口设计的时候,就已经想好了该功能之后通过实现与调用这个接口肯定是可以实现的,等各个功能相关的接口设计好之后,剩下的就是程序员去实现与调用这些接口,就跟填空一样。在做接口设计的时候只用关心方法的形参与返回值类型,可以写好对应的接口文档,描述每个接口的作用,接口中每个方法的形参的含义和返回值的含义,这样可以更好的方便团队开发。其实这个跟做房子很像,做房子也是先把设计图做好,然后搭建框架,剩下的就是码砖了。
在我们使用函数(方法)的时候,我们要理解一个概念。一去一回(也可以说是请求与响应),特别是在做http请求时更加明显。在非void返回类型的函数中,都是需要retrun一个返回值的,而调用函数给形参传递实参的时候,这个过程我们就可以看做是“去”,在函数体类做一大堆的逻辑与业务的处理,待处理完之后,就返回一个结果回去,这个就是“回”。
比如做一个网页登陆的功能,首先是从html里面的输入框将用户名和密码信息(实参)传递到服务端,服务端就存在一个checkLogin的函数来接收前端传递过来的实参,然后去查询数据库,处理完结果之后返回一个结果告知前端是否登录成功,前端可以根据这个返回值进行UI界面的提示与界面跳转等工作。在做分成业务涉及的时候,前面的用户名和密码可能还要经过几次函数之间的传递,但是都是又去有回。像web设计中的ajax与android网络请求retorfit中都体现的特别明显,大家充分理解了一去一回的原理之后,可以更加的方便我们对功能模块进行设计。
好下面,我们具体来通过代码进行展示。
我们新建一个java工程,然后此时我们不着急去写代码,先做个分包(package)的工作,相当于一个组织架构,使代码结构更加清晰,也更方便阅读与维护。
dao这个包下面就用来存放我们的接口,daoimpl下面用来存放我们的接口实现类,main作为项目的主入口,用来存放具体业务的实现,pojo用来存放数据模型类(等下具体讲解pojo的作用),utils用来存放工具类(把上一章我们写好的DBHelper放到这个包下)。
POJO(Plain Old Java Objects)简单的Java对象,实际就是普通JavaBeans,其中有一些属性及其getter setter方法的类,有时可以作为value object或dto(Data Transform Object)来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,可以看成是与数据库中的表相映射的 java 对象。
我们在pojo包下面新建一个User类
/**
*
*/
package com.xdw.pojo;
/**
* @author xiadewang
*2018年1月14日
*/
public class User {
private int id;
private String username;
private String password;
/**
* @param id
* @param username
* @param password
*/
public User(int id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
}
下面我们面向接口进行编程,比如说我们现在的业务有如下:
1、登录
2、注册
3、根据id查询用户信息
4、根据username查询用户信息
5、修改用户密码
这时候,如果是面向过程设计的话,我们就想着先去完整的完成登录的功能,然后完成注册的功能,然后继续下面的345的业务。
换成接口设计的话,就是我们先在dao下面新建一个接口UserDao,具体代码如下
/**
*
*/
package com.xdw.dao;
import com.xdw.pojo.User;
/**
* @author xiadewang
*2018年1月14日
*/
public interface UserDao {
/**
* 传递用户名和密码来校验登录
* @param username
* @param password
* @return
*/
public boolean checkLogin(String username,String password);
/**
* 传递user对象来校验登陆
* @param user
* @return
*/
public User checkLogin(User user);
/**
* 传递user对象进来,返回值1代表注册成功,0代表注册失败
* @param user
* @return
*/
public int register(User user);
/**
* 传递int型的id参数,返回值为user对象
* @param id
* @return
*/
public User getUserById(int id);
/**
* 传递字符串类型的用户名,返回值为user对象
* @param username
* @return
*/
public User getUserByUsername(String username);
/**
* 传递要修改密码的user对象,和要修改的密码,返回值1代表修改成功,0代表修改失败
* @param user
* @param password
* @return
*/
public int modifyPassword(User user,String password);
}
由于这里的功能很简单,直接把接口说明文档写到了注释之中,这个时候设计工作就完了,下面换个程序员来完成程序的完整功能。
在daoimpl包下面写一个接口实现类UserDaoImpl,如下
/**
*
*/
package com.xdw.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.xdw.dao.UserDao;
import com.xdw.pojo.User;
import com.xdw.utils.DBHelper;
/**
* @author xiadewang
*2018年1月14日
*/
public class UserDaoImpl implements UserDao {
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#checkLogin(java.lang.String, java.lang.String)
*/
@Override
public boolean checkLogin(String username, String password) {
// TODO Auto-generated method stub
return false;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#checkLogin(com.xdw.pojo.User)
*/
@Override
public User checkLogin(User user) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#register(com.xdw.pojo.User)
*/
@Override
public int register(User user) {
// TODO Auto-generated method stub
return 0;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#getUserById(int)
*/
@Override
public User getUserById(int id) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#getUserByUsername(java.lang.String)
*/
@Override
public User getUserByUsername(String username) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#modifyPassword(com.xdw.pojo.User, java.lang.String)
*/
@Override
public int modifyPassword(User user, String password) {
// TODO Auto-generated method stub
return 0;
}
}
这些都是编译器自动生成的代码,这个时候我们甚至都不用去完成里面每个方法的具体内容,可以直接跳到实现业务的主类中去实现我们的业务,因为这些方法都会存在一个默认的返回值,并不影响程序的编译与运行。
这个时候我们在main包中创建一个实现业务的类MainClass,如下
/**
*
*/
package com.xdw.main;
import com.xdw.dao.UserDao;
import com.xdw.daoimpl.UserDaoImpl;
import com.xdw.pojo.User;
/**
* @author xiadewang
*2018年1月14日
*/
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
UserDao userDao=new UserDaoImpl();
if(userDao.checkLogin("xdw","123456")) {
System.out.println("用户xdw登录成功");
}else {
System.out.println("用户xdw登录失败");
}
if(userDao.checkLogin("xxx","1234")) {
System.out.println("用户xxx登录成功");
}else {
System.out.println("用户xxx登录失败");
}
User user1=new User(1,"xdw","123456");
User user2=new User(2,"xxx","ttt");
if(userDao.checkLogin(user1) !=null) {
System.out.println("用户xdw登录成功");
}else {
System.out.println("用户xdw登录失败");
}
if(userDao.checkLogin(user2) !=null) {
System.out.println("用户xxx登录成功");
}else {
System.out.println("用户xxx登录失败");
}
}
}
这里,我只用2个重载的checkLogin方法做了业务展示,大家现在可以运行下,运行结果如下
进行到了,其实整个业务的设计与实现就完成了,剩下的工作我们就是要去具体的完善接口实现类的内容了,让他们更加的符合实际的业务处理,比如要连接数据库做真实的数据处理,这里只用第一个checkLogin做下举例,完善后的UserDaoImpl如下:
/**
*
*/
package com.xdw.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.xdw.dao.UserDao;
import com.xdw.pojo.User;
import com.xdw.utils.DBHelper;
/**
* @author xiadewang
*2018年1月14日
*/
public class UserDaoImpl implements UserDao {
private String sql = null;
private DBHelper db1 = null;
private ResultSet ret = null;
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#checkLogin(java.lang.String, java.lang.String)
*/
@Override
public boolean checkLogin(String username, String password) {
// TODO Auto-generated method stub
try {
sql = "select * from user where username= ? and password= ?";// SQL语句
db1 = new DBHelper(sql);// 创建DBHelper对象
db1.pst.setString(1, username);
db1.pst.setString(2, password);
ret = db1.pst.executeQuery();// 执行语句,得到结果集
if(ret.next()) {
return true;
}
ret.close();
db1.close();// 关闭连接
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#checkLogin(com.xdw.pojo.User)
*/
@Override
public User checkLogin(User user) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#register(com.xdw.pojo.User)
*/
@Override
public int register(User user) {
// TODO Auto-generated method stub
return 0;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#getUserById(int)
*/
@Override
public User getUserById(int id) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#getUserByUsername(java.lang.String)
*/
@Override
public User getUserByUsername(String username) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.xdw.dao.UserDao#modifyPassword(com.xdw.pojo.User, java.lang.String)
*/
@Override
public int modifyPassword(User user, String password) {
// TODO Auto-generated method stub
return 0;
}
}
到这里就不用我来啰嗦接口的重要作用了吧,java的核心个人觉得就是类、对象与接口,特别是面向接口编程。
初学者往往会觉得接口没什么鸟用,本来可以几行代码实现的功能,偏偏要添加一个接口出来,还要再添加一个实现类,不光增加代码还绕来绕去。
通过这里的接口编程的演示,大家有没有发现可以让我们做项目的时候思路更加清晰,代码可阅读和可扩展性也越强。我们要有一个概念,编程不是代码越少越好,而是要设计与思路越清晰越好。
这篇就到此为止,下一篇将引入servlet+jsp,到时候就会有UI界面了,前面的都还是console控制台输出,可能会觉得不过瘾,还是觉得代码没有什么用,不能运用到实际中。