话说:
各位读者,下午好!JavaWeb_news前面一直升级,升级到增加了分页和文件上传,今天在写Web框架前做最后一次“打怪升级”,整体原则是把框架底层的一些东西用之前的各种版本串联起来实现,继续实现新闻列表显示。这里主要展现新闻显示,文件上传及分页暂不重复实现。
整体思路是:大体按照MVC设计模式,实现接口编程。增加一个用户登陆判断用户是否存在的功能,但不做细化。有本书《大话设计模式》,蛮好的,不过不是以Java为案例编写的,可以借鉴。
目录
一、整体布局
二、准备工作
三、设计接口
四、实现dao层
五、实现Controler层(Servlet)
六、页面
七、总结
一、整体布局
二、准备工作
1、后台依旧使用news_db数据库和t_news数据表;增加一个数据库
my_news_db和数据表t_user,主要实现后台用户管理。读者可以根据实际情况自行设计。
2、导入的jar包还是和之前一样,导入Tomcat的lib库和jstl-1.2.0.jar
也就是我们的model。
User
package com.hmc.news.model;
/**
* User:Meice
* 2017/10/18
*/
public class User {
private int id;
private String username;
private String password;
public User() {}
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public User(String username,String password) {
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
News
package com.hmc.news.model;
/**
* User:Meice
* 2017/10/22
*/
public class News {
private int id;
private String title;
private String author;
private String pic;
public News () {}
public News(int id, String title, String author, String pic) {
this.id = id;
this.title = title;
this.author = author;
this.pic = pic;
}
public News(String title, String author, String pic) {
this.title = title;
this.author = author;
this.pic = pic;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
@Override
public String toString() {
return "News{" +
"id=" + id +
", title='" + title + '\'' +
", author='" + author + '\'' +
", pic='" + pic + '\'' +
'}';
}
}
这两个实体类基本无变化。User实现后台用户管理(只有符合条件的用户才能登陆新闻管理界面)
三、设计接口
这次最核心的变化就是实现接口编程。把一些固定的方法抽象成接口,然后用BaseDao和对应的业务类(UserDao、NewsDao)实现。
IUserDao
package com.hmc.news.dao;
import com.hmc.news.model.User;
public interface IUserDao {
//定义获取用户登陆的接口
public User getUser(String username,String password);
}
--------------------------------------------------------------------------------
编写UserDao,实现该接口,对后台是否存在当前用户做一些列业务逻辑判断。如果用户属于管理员,则允许登陆到新闻管理界面,否则就提示无权限。这里不做细化,仅仅只是体现这样一个接口。
IBaseDao
--------------------------------------------------------------------------------
package com.hmc.news.dao;
import java.util.List;
public interface IBaseDao {
//这个接口可以定义很多高层次的抽象
/**
* 根据参数获取对象
* 比如,你给我一个username,password这2个参数,我就能给你返回一个User对象
* 其他对象也是可以的
*/
T getByParam(String sql,Object... objects);
/**
* 获取对象列表
*/
List getList(String sql);
//同样分页也可以这么封装
//Pager getPager(int pageIndex,int pageSize);
//把整个分页作为一个对象传入
//Pager getPager(Pager pager);
/**
* 新增
*/
int add(String sql,Object... objects);
/**
* 修改
*/
int update(String sql,Object... objects);
/**
* 删除
*/
int del(String sql,int id);
}
这个接口高度抽象了我们前面所能想到的所有方法:
查询单个对象、所有对象以及CUD.
INewsDao
package com.hmc.news.dao;
import com.hmc.news.model.News;
public interface INewsDao extends IBaseDao<News> {
}
写好IBaseDao、BaseDao之后,在实现News对象就非常方便了。不论你给我什么对象,我都可以秒秒钟实现CURD.
四、实现dao层
几个Dao层类的顺序是,首先BaseDao==>JdbcDao==>UserDao==>NewsDao
其中JdbcDao和之前升级后的版本一样,BaseDao增加了最为核心的一个方法:获取泛型化参数
BaseDao
package com.hmc.news.dao;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* User:Meice
* 2017/10/18
*/
public class BaseDao extends JdbcDao implements IBaseDao {
//定义获取泛型化参数的方法getCls()
private Class getCls() {
//获取泛型化父类
Type type =this.getClass().getGenericSuperclass();
System.out.println(type);
//获取泛型化参数类型
ParameterizedType pt = (ParameterizedType)type;
Class cls = (Class)pt.getActualTypeArguments()[0];
return cls;
}
@Override
public T getByParam(String sql,Object... params) {
List list = (List) executeQuery(sql,getCls(),params);
list =(List) executeQuery(sql,getCls(),params);
if(list != null && list.size()>0) {
return list.get(0);
}
return null;
}
@Override
public List getList(String sql) {
List list = (List) executeQuery(sql,getCls(),null);
return list;
}
@Override
public int add(String sql, Object... params) {
return executeCUD(sql,params);
}
@Override
public int update(String sql, Object... params) {
return executeCUD(sql,params);
}
@Override
public int del(String sql, int id) {
return executeCUD(sql,id);
}
}
JdbcDao
package com.hmc.news.dao;
import com.hmc.news.model.News;
import com.hmc.news.util.ConfigUtil;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* User:Meice
* 2017/10/18
*/
public class JdbcDao {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
//定义静态语句块加载JDBC驱动
static{
try {
Class.forName(ConfigUtil.getPro("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//定义查询对象的方法executeQuery()
public List> executeQuery(String sql,Class> cls,Object... params) {
//定义一个object类型的集合,用于存放查询的数据
List
UserDao
package com.hmc.news.dao;
import com.hmc.news.model.User;
/**
* User:Meice
* 2017/10/18
*/
public class UserDao extends BaseDao<User> implements IUserDao {
@Override
public User getUser(String username, String password) {
String sql = "select * from t_user where username = ? and password = ?";
Object[] params = {username,password};
User user = getByParam(sql,params);
return user;
}
}
NewsDao
package com.hmc.news.dao;
import com.hmc.news.model.News;
/**
* User:Meice
* 2017/10/22
*/
public class NewsDao extends BaseDao<News> implements INewsDao {
}
NewsDao只需要继承BaseDao,实现接口INewsDao,什么方法也不用写了。这里既可以深刻体会到接口编程的便利!接口编程最核心的就是可扩展性强。
五、实现Controler层(Servlet)
BaseServlet
这个和之前一样,没有变动。最核心的就是Method方法映射,页面请求什么参数,就能主动调用和参数名相同的方法。
package com.hmc.news.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* User:Meice
* 2017/10/16
*/
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//设置方法映射
String op = req.getParameter("op");
if(op != null && !"".equals(op)) {
try {
Method method = this.getClass().getDeclaredMethod(op,HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}else {
System.out.println("参数缺失....");
}
}
}
NewsServlet
package com.hmc.news.Servlet;
import com.hmc.news.dao.NewsDao;
import com.hmc.news.model.News;
import com.hmc.news.util.StringConvertUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* User:Meice
* 2017/10/22
*/
@WebServlet(urlPatterns = "/news.do")
public class NewsServlet extends BaseServlet{
NewsDao nd = new NewsDao();
//调用显示新闻方法
public void list(HttpServletRequest req,HttpServletResponse resp) {
//直接调用方法
String sql = "select * from t_news";
List list = (List) nd.executeQuery(sql, News.class,null);
req.setAttribute("list",list);
//页面跳转
try {
req.getRequestDispatcher("index.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void add(HttpServletRequest req,HttpServletResponse resp) {
//接受参数
String title = req.getParameter("title");
String author = req.getParameter("author");
//调用方法
String sql = "insert into t_news (title,author) values (?,?)";
Object[] params = {title,author};
nd.executeCUD(sql,params);
//页面跳转
try {
req.getRequestDispatcher("news.do?op=list").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//定义显示要修改新闻的方法
public void updateShow(HttpServletRequest req,HttpServletResponse resp) {
//接受参数
String strId = req.getParameter("id");
int id = StringConvertUtil.getStr(strId);
//调用方法
String sql = "select * from t_news where id = ?";
Object[] params = {id};
News news = nd.getByParam(sql,params);
//设置参数
req.setAttribute("news",news);
//页面跳转
try {
req.getRequestDispatcher("newsUpdate.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//定义修改新闻方法update()
public void update(HttpServletRequest req,HttpServletResponse resp) {
//接收参数
String strId = req.getParameter("id");
int id = StringConvertUtil.getStr(strId);
String title = req.getParameter("title");
String author = req.getParameter("author");
//调用方法
String sql = "update t_news set title=?,author=? where id = ?";
Object[] params ={title,author,id};
nd.executeCUD(sql,params);
//页面跳转
try {
req.getRequestDispatcher("news.do?op=list").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void del(HttpServletRequest req,HttpServletResponse resp) {
String strId = req.getParameter("id");
int id = StringConvertUtil.getStr(strId);
String sql = "delete from t_news where id = ?";
Object[] params = {id};
nd.executeCUD(sql,params);
try {
req.getRequestDispatcher("news.do?op=list").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
工具类:ConfigUtil、StringConvertUtil
工具类:ConfigUtil——数据库连接参数
StringConvertUtil——id转换
ConfigUtil
package com.hmc.news.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* User:Meice
* 2017/10/21
*/
//为了更加方便调用,我们把它定义为静态的
public class ConfigUtil {
//定义获取MySQL数据库参数的方法getPro()
public static String getPro(String name) {
Properties pro = new Properties();
//this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
InputStream is = ConfigUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
pro.load(is);
return pro.getProperty(name);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//测试getPro()方法
System.out.println(ConfigUtil.getPro("driver"));
}
}
StringConvertUtil
package com.hmc.news.util;
/**
* User:Meice
* 2017/10/22
*/
public class StringConvertUtil {
public static int getStr(String strId) {
int id = 0;
if(strId != null && !"".equals(strId)) {
id = Integer.parseInt(strId);
}else {
id = 0;
}
return id;
}
}
六、页面
页面就不在赘述。
七、总结
一、获取参数化类型,明白list<问号>与List<梯>的区别;
二、面向接口编程
以在下愚见,接口其实就类似战略,高度抽象化,其他的只是实现。面向接口编程,就是要有一种整体化思维,有一种高屋建瓴的思维方式,而不是被细节所吞没。
三、这次重复写了下,出现不少Bug,都是之前犯过的错误。所以,伤疤要常揭,揭伤疤不要只是看一看,不要只是同情的看一看,要实在的去重复、重复再重复。
好了,晚安!