在网站架构上,采用MVC设计模式,实现将网站的页面显示与业务逻辑分离,使其各司其职;在数据库操作上,利用DAO模式(Data Access Object数据存取对象)技术,将程序中的类对象映射成为数据库表中相应的记录,在代码里只需直接操纵对象即可实现对数据库数据的操作,数据库釆用性能稳定的MySQL,前台采用javascript技术实现动态效果。
前台部分功能用JSP技术进行开发,JavaScript脚本使开发有更高的效率 。后台的部分功能用到了JAVA开发技术和MYSQL数据库技术。
Java Web应用程序的主要组件
1.Servlet组件
2.JSP组件
3.JavaBean组件
4.XML语言——是一种用来创建自定义标记的标记语言。
5.Web服务器和应用服务器
Servlet是Sun提供的用于开发动态Web资源的技术。Sun公司在其API中提供了一个servlet接口来控制应用程序的流程。 如果用户想要发送动态网络资源(即开发一个Java程序将数据输出到浏览器),则需要完成以下两个步骤:首先,编写一个实现servlet接口的Java类。 其次,根据习惯惯例,将一个完善的Java类部署到Web服务器。 通常我们也实现一个实现了servlet接口的java程序。 Servlet , JSP主要完成输入输出功能,主要由HTML代码,客户端脚本(JavaScript等),JSP标签和指令,自定义标签库组成。
Servlet技术可以完成与JSP相同的功能,但其表现形式与JSP不同。 JSP以脚本文件的形式存在,并且Servlet以Java文件的形式存在。
Servlet也是一个Java类,是一个特殊的Java类,主要是在Java Web技术中完成控制功能,负责协调JSP页面和JavaBean之间的函数关系]。
Servlet是一种独立于平台和协议的服务器端的Java应用程序,可以生成动态的web页面。它担当Web浏览器或其他http客户程序发出请求、与http服务器上的数据库或应用程序之间交互的中间层。
Servlet是用Java编写的Server端程序,它与协议和平台无关。Servlet运行于Java服务器中。
Java Servlet可以动态地扩展服务器的能力,并采用请求-响应模式提供Web服务。
Servlet是使用Java Servlet应用程序设计接口及相关类和方法的Java程序。它在Web服务器上或应用服务器上运行并扩展了该服务器的能力,Servlet装入Web服务器并在Web服务器内执行。
Servlet是以Java技术为基础的服务器端应用程序组件,Servlet的客户端可以提出请求并获得该请求的响应,它可以是任何Java程序、浏览器或任何设备,MVC模式中的servlet:仅作为控制器使用,J2EE应用架构正是遵循MVC模式的,其中JSP仅作为表现层技术,其作用有两点:1.负责收集用户请求参数;2. 将应用的处理结果、状态、数据呈现给用户。
JavaScript是直译式的脚本语言。JavaScript的解释器被人们称为JavaScript引擎,是浏览器组件的一部分,js是广泛用于客户端的脚本语言,用来给HTML网页添加动态交互的功能。
jQuery是一个快速、简洁的JavaScript框架,它的设计宗旨是“write Less,Do More”,即提倡写很少的代码,却做到更多的事情。它封装了JavaScript一些常用的功能代码,提供一种简单的设计模式。
jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的CSS选择器,并且可对CSS选择器进行扩展
Web服务器在接收到HTTP请求之时,会先判断请求内容的情况,自动处理静态页面的数据,之后产生响应信息;若是动态数据则请求转发到Servlet容器。之后Servlet容器会找到对应的Servlet实例来处理该请求,最后将结果送回Web服务器,最后由Web服务器送回用户。值得注意的是,当servlet容器首次接收到HTTP请求时,servlet容器将创建一个servlet实例,然后启动一个线程。 第二次收到HTTP请求时,servlet的容器不需要创建相同的servlet实例,而是启动第二个线程来提供它。 客户端请求和多线程方法不仅可以提高Web应用程序的执行效率,还可以减少网络服务器的系统负载
请求到容器到servlet周期流程:
JDBC(Java Database Connectivity)是为 Java 应用程序中访问数据库而设计的 Java API, JDBC 中包含了一组由 Java 语言编写的接口和类,这些接口和类都是独立于特定的 DBMS(数据库管理系统)[23]。JDBC 是 Java 数据库应用开发过程中的一项重要的核心技术。
有了 JDBC 技术,开发人员可以方便地在 Java 语言中使用标准 SQL 语句,从而使 Java 应用程序可以实现对分布在网络上的各种各样的关系数据库的访问。 若要程序员将精力大部分用于上层的功能实现则JDBC技术可以实现,可以不必关心底层的实现和具体的数据库的连接和访问的过程。
目前基于 JDBC 技术的高层 API 主要是从关系数据库直接映射到 Java 类;在这“对象/关系”映射中,数据库中每个表的每一行都将变成这一类的一个对象的,每一列的值对应该对象实例的一个属性; JDBC 包含了两部分与数据库相互独立的 API:面向开发人员的 JDBC API 以及面向底层的 JDBC Driver API;面向开发人员的 JDBC API 被描述成抽象的 Java接口,通过这些接口 Java 程序可以对某个特定的数据库打开连接,执行相应的SQL 语句并且处理执行结果; JDBC 的驱动管理器负责管理各种类型的数据库管理系统的 JDBC 驱动程序。同时也负责和用户的应用程序交互,从而为 Java 程序建立数据库连接;Java 程序通过 JDBC API 向 JDBC 驱动管理器发出相应的请求,指定需要装载的 JDBC 驱动程序类型以及数据源[24]。驱动管理器此时会根据这些要求来装载合适的 JDBC驱动程序并且使该驱动连接到相应的数据源。一旦连接成功,该 JDBC 驱动程序将会负责 Java 应用程序与该数据源的全部交互,即作为中间的翻译将 Java 应用程序中对 JDBC API 的系统调用转换成特定的数据库管理系统能够理解的命令,最后将数据库返回的结果转换为 Java 应用程序所能够识别的数据。
考虑到本系统的规模、系统的灵活性以及系统开发的成本,我们选择 My SQL数据库作为本系统的数据存储的数据库管理系统。 My SQL 是最受欢迎的数据库管理系统,它是由 My SQL AB 开发以及发布和支持的。其服务器支持了关键任务和重负载生产系统的使用,同时它也可以嵌入到一个大配置的软件中去。由于该数据库系统的强大的功能、丰富的应用编程接口(API)、灵活性以及精巧的系统结构[25],让广大软件爱好者甚至是商业的软件用户为之青睐,特别是该数据库系统与 Apache 和 PHP 结合[26],为建立在基于数据库的动态网站应用程序提供了强大的动力。
My SQL 主要的特点与作用:My SQL 数据库是一个能够让很多用户同时访问的数据库,从数据库的内部实现来说,数据库的操作能够多线程的连接实现,提高了数据库的操作效率和减少了数据库的数据处理时间。该数据库应用的网络结构是 C/S 网络应用程序结构的数据库,并且在数据库中有不同的守护进程以及不同的用户组来对数据库访问权限的控制。 结构化查询语言(SQL)是一种标准化的语言,它使得信息的存储、存取和更新更为容易。比如我们可以用结构化查询语言为一个网站来检索产品的信息以及其存储的客户信息,同时 My SQL 也可以提供足够快和灵活的性能来允许我们存储记录的文件盒相关的图像信息。 My SQL 数据库主要目标是健壮、快速和易用[26],最初我们是需要一个像这样的 SQL 服务器,它能够处理与任何不昂贵的硬件平台上来提供数据库的厂家并且在一个数量级上的大型的数据库,但是其速度更快,My SQL 就因此产生了。 My SQL 数据库的主要功能只是在组织和管理庞大或者复杂的信息以及基于Web 的库存量的查询请求,不仅仅是为客户提供信息,同时也可以为客户自己使用数据库提供诸多的功能:减少了记录编档的时间,减少了记录检索的时间,拥有灵活的查找序列,提供灵活的输出数据格式,允许多个用户同时访问数据库中的数据记录。
主要分为三大模块,用户界面,业务逻辑和数据库部分。其中,用户界面采用JQuery框架开发,包括若干个JSP页面与JS脚本文件。
主要是运用了16页面文件,定义表单Form文件,定义页面title文件,定义javascript函数文件和系统所需要的所有标签文件。下面以个人主页main.jsp页面文件为例,说明了各部分的定义。
在MVC设计模型中,View用来呈现数据处理结果,可以是JSP、XML、HTML;Model用来存储数据的状态,可利用JavaBean来实现;Controller负责协调应用程序的运行流程,可用Servlet来实现。运用这种模式可以将数据呈现方式与数据处理方式分离,提高了代码的利用率。
实现了将类对象的实体信息存入数据库的目的,此过程的大致步骤如下:
本系统涉及的业务对象有15个,根据其中的派生、关联等关系映射成了12张表,为了完成业务对象的持久化和数据库的维护操作,就要定义一个DAO数据库连接类。
DAO是数据处理接口,提交数据到数据库。数据库操作类的通常包括执行查询语句的方法,数据库交互层,增删改查等。
一般而言DAO主要实现增、删、改、查操作,而查包括查询单条数据和多条数据,以UsersDao借口为例:
public class UsersDao {
public int getDayUp(String time) {
String sql = "select * from signin where DATE_FORMAT(stime,'%Y-%m-%d')=? ";
List<Signin> result = DBUtil.query(Signin.class, sql, time);
return result.size();
}
public int getUserNum() {
return DBUtil.queryUserNum();
}
public Users checkLogin(String username, String password) {
String sql = "select uid, uname, urealname, uaite, ustate, utime, uonline from users where (uname=? and upwd=?) or (uaite=? and upwd=?) limit 1";
List<Users> list = DBUtil.query(Users.class, sql, username, password, username, password);
if (list.size() > 0) {
return list.get(0);
}
return null;
}
public Users findById(int uid) {
String sql = "select uid, uname, urealname, uaite, ustate, utime, uonline from users where uid=? limit 1";
List<Users> list = DBUtil.query(Users.class, sql, uid);
if (list.size() > 0) {
return list.get(0);
}
return null;
}
public boolean checkUsername(String username) {
String sql = "select uid, uname, urealname, uaite, ustate, utime from users where uname=? limit 1";
List<Users> list = DBUtil.query(Users.class, sql, username);
if (list.size() > 0) {
return true;
}
return false;
}
public int addUser(String username, String password, String urealname, String aite, Timestamp utime) {
String sql = "insert into users(uname, upwd, urealname, uaite,utime) values(?,?,?,?,?)";
int n = DBUtil.update(sql, username, password, urealname, aite, utime);
return n;
}
public boolean checkUaite(String uaite) {
String sql = "select uid, uname, urealname, uaite, ustate, utime ,uonline from users where uaite=? limit 1";
List<Users> list = DBUtil.query(Users.class, sql, uaite);
if (list.size() > 0) {
return true;
}
return false;
}
public int updateOnline(int uonline, int uid) {
String sql = "update users set uonline=? where uid=?";
int n = DBUtil.update(sql, uonline, uid);
return n;
}
public int updateState(String uid, String state) {
String sql = "update users set ustate=? where uid=?";
int n = DBUtil.update(sql, state, uid);
return n;
}
}
Pojo为数据库表映射的对象类.是多个具有getXXX()、setXXX()方法的类。用于获取或者设置HTML表单数据库,同时这多个类也可以与数据库的表相对应。
本系统涉及的业务对象主要有:管理员类(Admins)、用户类(Users)、关注(Concern)、转发(Forwards)、点赞类(Likes)、说说(Tweets)、私信(Messageall)、通知(Notification)等。 通常情况下的业务对象类都是用JAVA编写的,说白了就是一个java类。并且在java类中定义了许多的逻辑业务和属性,然后采用了对外接口的get和set的方法来访问类里的值。 下面列举一个重要的业务对象类Users类的私有属性uid及其get和set方法的定义。
public class Users {
//其中的一个属性,uid相关操作
private int uid;
//相应的get和set方法
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
}
JSP负责视图,业务逻辑等将由JavaBean去实现,Controller负责来协调程序的运作流程,通过用Servlet来实现。
核心是Servlet,一般在Servlet里完成页面的逻辑跳转工作。各个模块的Servlet实现类继承于HttpServlet类,在该类中首先定义一些必要的属性,例如DAO对象。Servlet实现类的主要方法涉及到具体的事务,例如核查id,删除信息等。如Uid为1的用户关注了Uid为2的用户,只需在ConcernServlet类中调用concernDao.hasFollow(Integer.parseInt(1), 2)即可,而业务层的处理和调用Dao层方法的具体实现对上层又是透明的。
以ConcernServlet为例,ConcernServlet类继承自 HttpServlet类,首先实例化一些对象类
private ConcernDao concernDao = new ConcernDao();
private UsersinfoDao usersinfoDao = new UsersinfoDao();
private NotificationDao notificationDao = new NotificationDao();
而后重写service() 方法,这是 Servlet 的核心方法,servlet容器把所有请求发送到该方法,这里我们覆盖了service方法来处理添加关注的业务
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
String suid = req.getParameter("suid");
HttpSession session = req.getSession();
Users user = (Users) session.getAttribute("user");
int n = 0;
int uid = user.getUid();
int mode = concernDao.hasFollow(Integer.parseInt(suid), uid);
Timestamp ctime = Times.getSystemTime();
if ("add".equals(method)) {
if (mode > 0) {
int m = concernDao.updateFollow(suid, uid, 1);
}
n = concernDao.addFollow(uid, suid, mode, ctime);
if (n > 0) {
notificationDao.addNotify(uid, 1, 0, 0, 0, 0, Integer.parseInt(suid), 0, 0, null, ctime, 0);
usersinfoDao.addFansNum(Integer.parseInt(suid), 1);
usersinfoDao.addFollowNum(uid, 1);
}
Usersinfo info = usersinfoDao.getInfos(uid);
session.setAttribute("info", info);
}
if ("del".equals(method)) {
if (mode > 0) {
int m = concernDao.updateFollow(suid, uid, 0);
}
n = concernDao.delFollow(uid, suid);
if (n > 0) {
usersinfoDao.addFansNum(Integer.parseInt(suid), 0);
usersinfoDao.addFollowNum(uid, 0);
}
Usersinfo info = usersinfoDao.getInfos(uid);
session.setAttribute("info", info);
}
if (n > 0) {
resp.getWriter().print("1");
} else {
resp.getWriter().print("0");
}
}
}
util包括一些工具类,比如DBUtil类主要用于获取数据库链接、关闭数据库链接,Md5Util类主要用于登录密码的加密算法,MySessionListener类进行在线人数的统计。
以DBUtil为例。用连接池来管理Connection,这可以重复使用Connection。有了池,我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用Connection后,调用Connection的close()方法也不会真的关闭Connection,而是Connection“还”给池。池就可以再利用这个Connection对象了。结合系统的业务结构,需要访问数据库的操作并不是非常多。即系统的并发负荷不是很高,我们可采取一些简单的并发解决方案便能达到一个满足系统正常运行的效果,比如使用高性能的WEB容器(Apache+Tomcat)、MYSQL数据库、高效率的编程语言(JAVA)和给HTML网页增加动态功能的JavaScript等方案。
//MySQL数据库连接池
public class DBUtil {
static Vector<Connection> conPool = new Vector<Connection>();
//存放连接池中数据库连接的向量。
static {
for (int i = 0; i < 20; i++) {
// 存放连接池中数据库连接的向量 20个
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/zone?characterEncoding=utf8", "tester", "666666");
conPool.add(con);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//定义关于连接池操作的各种方法
public static Connection getConnection() {
//从连接池中获得一个可用的连接
Connection con = conPool.get(0);
conPool.remove(0);
//连接使用完后释放连接到连接池
return con;
}
public static void releaseConnection(Connection con) {
//关闭数据库连接池,耗时较大
conPool.add(con);
}
DBUtil类中实现连接数据库、执行数据库操作、关闭数据库,其中返回查询的记录存储在集合List里面,上文提到的对象类保证了查询出数据库的一条记录映射到相应的dao中。
` public static List query(Class<?> c, String sql, Object... obj) {
Connection con = getConnection();
List<Object> list = new ArrayList<Object>();
try {
PreparedStatement pre = con.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
pre.setObject(i + 1, obj[i]);
}
ResultSet rs = pre.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
while (rs.next()) {
Object object = c.newInstance();
for (int i = 1; i <= count; i++) {
String filedName = rsmd.getColumnLabel(i);
Field field = c.getDeclaredField(filedName);
field.setAccessible(true);
field.set(object, rs.getObject(i));
}
list.add(object);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseConnection(con);
}
return list;
}
}
Java web的核心配置为web.xml。在web.xml文件中注册监听器。当我们访问jsp页面时,HttpSession对象就会创建,此时就可以在HttpSessionListener观察到HttpSession对象的创建过程。
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<listener>
<listener-class>com.zone.util.MySessionListenerlistener-class>
listener>
<session-config>
<session-timeout>10session-timeout>
session-config>
web-app>