Java Web总结(一)
一、Servlet在应用中的作用
① Servlet是Java Web中MVC模式中的C部分,即控制部分,下面展示一下其所处的位置和整个客户端(浏览器)和服务器端的交互过程。(如图1)
图1
② 由图1可以看到浏览器通过请求将其数据提交到Servlet中,然后Servlet进行控制,即Servlet充当调度员的角色,其作用主要集中在三个方面:接收数据、调用业务逻辑、对客户端做出简单的响应。
③ 然后Servlet将要继续处理的数据提交给JavaBean,然后JavaBean进行验证,然后如果涉及到数据库的操作,就会继续用到DAO(数据访问模型),然后调用数据库中间件JDBC进行数据库的相关操作,然后到数据库中访问数据。
二、实现整个过程
① 为了实现整个过程,首先编写一个html(JSP)前台页面,如图2:

图2
代码如下:
<html>
<head>
<title>系统登陆</title>
</head>
<body>
<p> </p>
<p> </p>
<p> </p>
<div align="center">
<br>
<br>
<div style="margin:0 auto; width:230px;margin-top:70px;">
<form id="login" action="/JavaWeb/loginServlet" method="post">
<fieldset>
<legend>用户登陆</legend><br/>
<div>用户:
<input name="username" id="username"/>
</div>
<br/>
<div>密码:
<input name="password" id="pwd"/>
</div>
<br/>
</fieldset>
<div style="text-align: center;margin: 20px;">
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</div>
</form>
</div>
</div>
</body>
</html>
② 由上面的代码可以看到将<form>中的内容提交到/JavaWeb/loginServlet这个Servlet,这里涉及到了配置web.xml配置文件,只需要在配置文件中加入如下的部分:
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>cn.edu.nwsuaf.cie.group4.servlet.LoginServlet</servlet-class>
<load-on-startup>0</load-on-startup>//在开启服务时,就调用init方法
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
③ Servlet中的代码如下所示
package cn.edu.nwsuaf.cie.group4.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.edu.nwsuaf.cie.group4.service.LoginService;
public class LoginServlet extends HttpServlet{
private String userName;
private String password;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
System.out.println("init....");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
userName = req.getParameter("username");
password = req.getParameter("password");
LoginService loginService = new LoginService();
boolean flag = loginService.validate(userName,password);
if (flag){
req.getRequestDispatcher("index.jsp").forward(req, resp);
}else{
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy...");
}
}
然后对上面的代码中的一部分进行解释。这个类继承了HttpServlet,然后并对其中的init()、destroy()、service()方法进行重写,其中Servlet是单例的(设计模式中的singleton model),因为所有的客户端自服务器开启并对servlet进行初始化以后,所有的客户端都是调用这里边的同一个对象,直到调用destroy方法销毁之。
其中红色斜体中部分,做出一点备注。其实在Servlet中有两种进行跳转的方法:req.getRequestDispatcher("index.jsp").forward(req,resp)、req.sendRedirect("index.jsp");对比这两种方式,得出如下的几点不同。
a. 第一种方式是请求转发方式,是单线程,相对效率比较高,因为它不需要请求两次,一次就可以调用完毕,可以看到其在跳转时,地址栏维持跳转前的地址不变。并且它可以通过session.setAttribute方法进行传递参数、值。
b. 第二种方式是重定向方式,属于多线程,效率偏低,因为有多次请求过程,不等待调用请求结束,就继续向下执行,等调用完成时,再次响应。其地址栏变为跳转之后的地址。其不等传递参数、值。
④ 通过上面可以看到蓝色斜体部分,可以看到这边还是一个Servlet,是进行后台的处理,会和数据库进行关联。
package cn.edu.nwsuaf.cie.group4.service;
import cn.edu.nwsuaf.cie.group4.dao.LoginDAO;
public class LoginService {
public boolean validate(String userName, String password) {
// TODO Auto-generated method stub
LoginDAO dao = new LoginDAO();
return dao.validate(userName,password);
}
}
⑤上面的程序中调用到了一个DAO,然后可以看到LoginDAO类是继承了DAO,如下:
package cn.edu.nwsuaf.cie.group4.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
public class LoginDAO extends DAO{
public boolean validate(String userName, String password) {
// TODO Auto-generated method stub
try {
String sql = "select * from g4user where username='"+userName+"' and pwd='"+password+"'";
DAO类
ResultSet rs = this.executeQuery(sql);
if (rs.next()){
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
package cn.edu.nwsuaf.cie.group4.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DAO {
private final static String URL = "jdbc:oracle:thin:@192.168.19.90:1521:softwareengineer";
private final static String USERNAME = "group4";
private final static String PASSWORD = "group4";
static{
try {
//DriverManager.registerDriver(new OracleDriver());
Class.forName("oracle.jdbc.OracleDriver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public ResultSet executeQuery(String sql){
try {
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@192.168.19.90:1521:softwareengineer",
"group4","group4");
Statement stm = con.createStatement();
return stm.executeQuery(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
⑥ 上面的DAO类中,可以看到其中使用了两种加载其中oracle的数据库驱动类,但是通过咨询和查找资料发现,应该是DriverManager注册的方式是在编译阶段进行判断是否存在这个类,但是Class.forName是在编译完成后,运行阶段判断,是属于动态加载的方法。