案例学生管理系统,获取所有学生的功能
1.控制层
@WebServlet("/GetAllStuServlet")
public class GetAllStuServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");//解决post中文乱码问题
resp.setContentType("text/html;charset=UTF-8");//解决响应到前台中文乱码的问题
StudentService ss=new StudentService();
ArrayList<Student> arrayList= null;
try {
arrayList = ss.getAllStu();
} catch (SQLException e) {
e.printStackTrace();
}
req.setAttribute("stulist",arrayList);
req.getRequestDispatcher("/stulist.jsp").forward(req,resp);
}
}
2.业务层
public class StudentService {
public ArrayList<Student> getAllStu() throws SQLException {
StudentDao std=new StudentDao();
ArrayList<Student> arrayList= std.getAllStu();
return arrayList;
}
}
3.dao层
public class StudentDao {
public ArrayList<Student> getAllStu() throws SQLException {
ArrayList<Student> arrayList = new ArrayList<>();
Connection con = GetCon.getCon();
if (con!=null){
Statement statement = con.createStatement();
String sql="SELECT * FROM student ";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
String id = resultSet.getString("id");
String name = resultSet.getString("stuname");
String gender = resultSet.getString("gender");
String age = resultSet.getString("age");
arrayList.add(new Student(name,Integer.parseInt(age),gender));
}
con.close();
}
return arrayList;
}
}
开始BB
上面的dao层是用的jdbc实现获取连接,如果要求采用c3p0连接池技术获取连接,按照开闭原则,我们得重写这个StudentDao,当然过两天又可能又使用Druid来获取连接的需求,那么按照开闭原则我们又得重新写一个StudentDao。几个StudentDao不能删除就导致业务层造对象得一直改
StudentDao111 std=new StudentDao111();
StudentDaoJdbc std=new StudentDaoJdbc();
StudentDaoDruid std=new StudentDaoDruid();
那么我们就可以开展解耦的第一个阶段了,使用多态对上面的三个操作进行解耦,为了解决把左边写死的问题,我们可以为上面三个类抽取一个接口。
StudentDao std=new StudentDaoImpl111();
StudentDao std=new new StudentDaoJdbcImpl();
StudentDao std=new StudentDaoDruidImpl();
我们又发现一个问题,左边的耦合解开了,右边的还没有解开,我们得想一个方法来动态的创造右边的实例,接下来就到了解耦的第二阶段。我们可以在src下创建一个配置文件,里面写上Dao实现类的全类名,然后通过加载配置文件动态获取全类名,有了全类名就可以通过反射来造对象了。
studentDao=com.it.mark.dao.StudentDaoImpl
InputStream rs = StudentServiceImpl.class.getClassLoader().getResourceAsStream("bean.properties");
Properties properties =new Properties();
StudentDao std=(StudentDao) Class.forName(properties.getProperty("studentDao")).newInstance()
此时右边的耦合也解开了,我们觉得这个方法很赞,想把这样的方法应用到业务层,可是发现一个问题,业务层也要写上读配置文件,加载配置文件,反射造对象的代码。所以我们可以对上面的代码进行抽取。这就到了解耦升级阶段–使用工厂类来动态造对象
public class MyBeanFactory {
public static Object getBean(String id){
try {
InputStream ras = MyBeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
Properties properties=new Properties();
properties.load(ras);
return Class.forName(properties.getProperty(id)).newInstance();
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private MyBeanFactory() {
}
}
我们对外暴露一个String类型的id,通过它就可以获取加载到集合中的类的全路径,进而造对象。
至此解耦完毕。