如果需要编译Java 文件时能使用Struts 的类库,则应将struts的zip包的lib 路径下的struts.jar 文件添加到CLASSPATH 的环境变量中即可。
MVC是一种模式,struts是一种实现方式。
一、基本的MVC实例
Model 由JavaBean 充当; View 由JSP 页面充当; 而Controller 则由Servlet 充当。
一个简单的登录页面示例:
(1)VIEW部分
登录页面login.jsp
登录成功页面welcome.jsp
错误页面error.jsp
(2)Model部分
Model 由DbDao 充当,该DbDao 仅是一个数据库访问的JavaBean ,并不包含任何业务逻辑,对于严格的J2EE 应用而言,该JavaBean 更像一个DAO 对象,而不是业务逻辑对象。对于分层更清晰的J2EE 应用,在Model 下隐藏了更加清晰的分层:业务逻辑层及DAO 层等。
(3)Controller部分
该控制器是一个标准的Servlet,负责拦截用户请求,解析用户请求参数,并调用合适的Model.即JavaBean 处理用户请求。
该控制器通过调用DbDao 来处理用户请求,而DbDao 则是本系统中的Model,负责持久层访问。但是该控制器存在少许问题,因为该控制器里出现了JDBC API。在严格的J2EE 架构分层里,这是不允许出现的。可将所有传到控制器的值都应封装成VO(值对象) ,而不应该与JDBC API 耦合。
二、struts基本实例
Struts 框架的应用使开发更加规范、统一。所有的控制器都由两部分组成——核心控制器与业务逻辑控制器。核心控制器负责拦截用户请求,而业务逻辑控制器则负责处理用户请求。
为了让核心控制器能拦截到所有的用户请求,应使用模式匹配的Struts 的核心控制器Servlet 的URL。配置Struts 的核心控制器,需要在web.xml 文件中增加如下代码:
从上面的配置可出,所有以.do 结尾的请求都会被actionServlet拦截,该Servlet 由Struts 提供,它将拦截到的请求转入Struts 体系内。
(1)VIEW部分
与上一个实例类似,只是将form中的action改为login.do
(2)Controller部分
核心控制器ActionServlet 由系统提供,负责拦截用户请求。
业务控制器用于处理用户请求, Struts 要求业务控制器继承Action,下面是业务控制器LoginAction 的源代码:
execute 方法中除了包含HttpServletRequest , HttpServletResponse 参数外,还包括了两个类型的参数: ActionForm, ActionForward。这两个参数分别用于封装用户的请求参数和控制转发。可以注意到: Action 的转发无须使用RequestDispatcher 类,而是使用ActionForward 完成转发。
注意:业务控制器Action 类,应尽量声明成public ,否则可能出现错误。并注意重写的execute 方法,其后面两个参数的类型是HttpServletRequest 和HttpServlet Response ,而不是ServletRequest 和SedvetResponse 。
(3)Struts配置文件
在转发时也没有转向一个实际的JSP 页面,而是转向逻辑名error, input, welcome 等。逻辑名并不代表实际的资源,因此还必须将逻辑名与资源对应起来。实际上,此处的控制器没有作为Servlet 配置在web.xml 文件中,因此必须将该Action配置在Struts 中,让ActionServlet 了解将客户端请求转发给该Action 处理。而这一切都是通过struts-config.xml 文件完成的。下面是struts-config.xml 文件的源代码:
从上面的配置文件可看出, Action 必须配置在struts-config.xml 文件中。注意其中Action 的path 属性: /login,再查看login.jsp 登录form 的提交路径login.do。两个路径的前面部分完全相同, ActionServlet负责拦截所有以.do 结尾的请求,然后将.do 前面的部分转发给struts-config.xml文件中Action 处理,该Action 的path 属性与请求的.do 前面部分完全相同。
配置Action 时,还配置了三个局部Forward。
• welcome: 对应IWEB-INF/jsp/welcome.jsp 。
• error: 对应IWEB-INF/jsp/error.jsp 。
• input: 对应/login.jsp 。
Forward 有局部Forward 和全局Forward 两种,前者只对于某个Action 有效,后者则对于整个Action 都有效。
注意:将JSP 页面放在WEB-INF 路径下,可以更好地保证JSP 页面的安装。因为大多数Web容器不允许直接访问WEB-INF 路径下的资源。因此,这些JSP 页面不能通过超级链接直接访问,而必须使用Struts 的转发才可以访问。
MVC是一种模式,struts是一种实现方式。
一、基本的MVC实例
Model 由JavaBean 充当; View 由JSP 页面充当; 而Controller 则由Servlet 充当。
一个简单的登录页面示例:
(1)VIEW部分
登录页面login.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"
errorPage="error.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
</head>
<script>
//Javascript 校验完成客户端校验
function check(form)
{
//如果没有输入用户名
if (form.username.value==null || form.username.value=="" ){
alert ('请输入用户名,然后再登录');
return false;
}
//如果没有输入密码
else if(form.pass.value==null || form.pass.value=="" ){
alert ('请输入密码,然后再登录');
return false;
}
//两者都已经输入
else return true;
}
</script>
<body>
<font color="red"> <%
//用于输出出错提示,出错提示保存在request 的err 属性里。
if (request.getAttribute("err") != null) {
out.println(request.getAttribute("err"));
}
%> </font>
<!-- 下面是登录表单 -->
请输入用户名和密码:
<form id="login" method="post" action="login"
onsubmit="return check(this); ">
用户名:
<input type="text" name="username" />
<br>
密 码:
<input type="password" name="pass" />
<br>
<input type="submit" value="登录" />
<br>
</form>
</body>
</html>
登录成功页面welcome.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"
errorPage="error.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
</head>
<body>
欢迎您,
<%=session.getAttribute("name")%><br>
</body>
</html>
错误页面error.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8"
isErrorPage="true"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>系统错误</title>
</head>
<body>
<font color="red"> <!-- 输出出错提示 --> <%
if (exception != null)
out.println(exception.getMessage() + "<br>");
%>
</font>
</body>
</html>
(2)Model部分
Model 由DbDao 充当,该DbDao 仅是一个数据库访问的JavaBean ,并不包含任何业务逻辑,对于严格的J2EE 应用而言,该JavaBean 更像一个DAO 对象,而不是业务逻辑对象。对于分层更清晰的J2EE 应用,在Model 下隐藏了更加清晰的分层:业务逻辑层及DAO 层等。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class DbDao {
private static DbDao op;
// 数据库连接
private Connection conn;
// 数据库驱动
private String driver;
//数据库服务的url
private String url;
// 数据库用户名
private String username;
//数据库密码
private String pass;
// 构造器私有,准备做成单态模式
private DbDao() {
}
// 带参数的构造器
private DbDao(String driver, String url, String username, String pass)
throws Exception {
this.driver = driver;
this.url = url;
this.username = username;
this.pass = pass;
Class.forName(driver);
conn = DriverManager.getConnection(url, username, pass);
}
// 各属性的setter 方法
public void setDriver(String driver) {
this.driver = driver;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPass(String pass) {
this.pass = pass;
}
//各属性的getter 方法
public String getDriver() {
return (this.driver);
}
public String getUrl() {
return (this.url);
}
public String getUsername() {
return (this.username);
}
public String getPass() {
return (this.pass);
}
//获取数据库连接
public void getConnection() throws Exception {
if (conn == null) {
Class.forName(this.driver);
conn = DriverManager.getConnection(this.url, this.username,
this.pass);
}
}
//静态方法,返回DbDao 实例
public static DbDao instance() {
if (op == null) {
op = new DbDao();
}
return op;
}
//静态方法,返回DbDao 实例
public static DbDao instance(String driver, String url, String username,
String pass) throws Exception {
if (op == null) {
op = new DbDao(driver, url, username, pass);
}
return op;
}
//数据库访问操作,执行插入操作
public boolean insert(String sql) throws Exception {
//初始化数据库连接
getConnection();
//创建Statement 对象
Statement stmt = this.conn.createStatement();
if (stmt.executeUpdate(sql) != 1) {
return false;
}
return true;
}
//数据库访问操作,执行查询操作
public ResultSet query(String sql) throws Exception {
// 初始化数据库连接
getConnection();
// 创建Statement 对象
Statement stmt = this.conn.createStatement();
return stmt.executeQuery(sql);
}
// 数据库访问操作,执行删除操作
public void delete(String sql) throws Exception {
//初始化数据库连接
getConnection();
//创建Statement对象
Statement stmt = this.conn.createStatement();
stmt.executeUpdate(sql);
}
//数据库访问操作,执行更新操作
public void update(String sql) throws Exception {
//初始化数据库连接
getConnection();
//创建Statement对象
Statement stmt = this.conn.createStatement();
stmt.executeUpdate(sql);
}
}
(3)Controller部分
该控制器是一个标准的Servlet,负责拦截用户请求,解析用户请求参数,并调用合适的Model.即JavaBean 处理用户请求。
import java.sql.ResultSet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet {
// Servlet 的服务响应方法
public void service(ServletRequest request, ServletResponse response)
throws ServletException, java.io.IOException {
RequestDispatcher rd;
// 解析请求参数,获取用户名
String username = request.getParameter("username");
// 解析请求参数,获取密码
String pass = request.getParameter("pass");
String errMsg = "";
// 完成服务器端校验
// 校验用户名
if (username == null || username.equals("")) {
errMsg += "您的用户名丢失或没有输入,请重新输入";
}
// 校验密码
else if (pass == null || pass.equals("")) {
errMsg += "您的密码丢失或没有输入,请重新输入";
}
// 如果用户名、密码都通过校验
else {
try {
// 调用JavaBean ,创建JavaBean 实例
DbDao dd = DbDao.instance("com.mysql. jdbc.Driver",
"jdbc:mysql://localhost:3306/liuyan", "root", "32147");
// 调用JavaBean 的方法
ResultSet rs = dd
.query("se1ect password from user_table where username = '"
+ username + "'");
// 判断用户是否存在
if (rs.next()) {
// 用户名存在,密码符合,则正常登录
if (rs.getString("password").equals(pass)) {
// 向Session 中存入用户名
HttpServletRequest hrequest = (HttpServletRequest) request;
HttpSession session = hrequest.getSession(true);
session.setAttribute("name", username);
// 跳转到成功后的JSP页面
rd = request.getRequestDispatcher("/welcome.jsp");
rd.forward(request, response);
} else {
// 用户名存在,但用户名密码不符合
errMsg += "您的用户名密码不符合,请重新输入";
}
} else {
// 用户名不存在
errMsg += "您的用户名不存在,请先注册";
}
} catch (Exception e) {
// 如果出现异常,跳转到error.jsp 页面
rd = request.getRequestDispatcher("/error.jsp");
request.setAttribute("exception", "业务异常");
rd.forward(request, response);
}
}
// 如果出错提示不为空,表明无法正常登录,返回登录页面
if (errMsg != null && !errMsg.equals("")) {
rd = request.getRequestDispatcher("/login.jsp");
request.setAttribute("err", errMsg);
rd.forward(request, response);
}
}
}
该控制器通过调用DbDao 来处理用户请求,而DbDao 则是本系统中的Model,负责持久层访问。但是该控制器存在少许问题,因为该控制器里出现了JDBC API。在严格的J2EE 架构分层里,这是不允许出现的。可将所有传到控制器的值都应封装成VO(值对象) ,而不应该与JDBC API 耦合。
二、struts基本实例
Struts 框架的应用使开发更加规范、统一。所有的控制器都由两部分组成——核心控制器与业务逻辑控制器。核心控制器负责拦截用户请求,而业务逻辑控制器则负责处理用户请求。
为了让核心控制器能拦截到所有的用户请求,应使用模式匹配的Struts 的核心控制器Servlet 的URL。配置Struts 的核心控制器,需要在web.xml 文件中增加如下代码:
<!-- 将Struts 的核心控制器配置成标准的Servlet -->
<servlet>
<servlet-name>actionSevlet</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
</servlet>
<!-- 采用模式匹配来配置核心控制器的URL -->
<servlet-mapping>
<servlet-name>actionSevlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
从上面的配置可出,所有以.do 结尾的请求都会被actionServlet拦截,该Servlet 由Struts 提供,它将拦截到的请求转入Struts 体系内。
(1)VIEW部分
与上一个实例类似,只是将form中的action改为login.do
(2)Controller部分
核心控制器ActionServlet 由系统提供,负责拦截用户请求。
业务控制器用于处理用户请求, Struts 要求业务控制器继承Action,下面是业务控制器LoginAction 的源代码:
import java.sql.ResultSet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class LoginAction extends Action {
//必须重写该核心方法,该方法负责处理用户请求
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//解析用户请求参数
String username = request.getParameter("username");
String pass = request.getParameter("pass");
// 出错提示
String errMsg = "";
// 进行服务器端的数据校验
if (username == null || username.equals("")) {
errMsg += "您的用户名丢失或没有输入,请重新输入";
} else if (pass == null || pass.equals("")) {
errMsg += "您的密码丢失或没有输入,请重新输入";
} else {
//如果可以通过服务器端校验,则调用JavaBean处理用户请求
try {
DbDao dd = DbDao.instance("com.mysql. jdbc. Driver",
"jdbc:mysql:lllocalhost:3306/liuyan", "root", "32l47");
ResultSet rs = dd
.query("select password from user_table where username ='"
+ username + "'");
//判断用户名和密码的情况
if (rs.next()) {
// 如果用户名和秘码匹配
if (rs.getString("password").equals(pass)) {
HttpSession session = request.getSession(true);
session.setAttribute("name", username);
return mapping.findForward("welcome");
} else {
//用户名和秘码不匹配的情况
errMsg += "您的用户名密码不符合,请重新输入";
}
} else {
//用户名不存在的情况
errMsg += "您的用户名不存在,请先注册";
}
} catch (Exception e) {
request.setAttribute("exception", "业务异常");
return mapping.findForward("error");
}
}
if (errMsg != null && !errMsg.equals("")) {
// 如果出错提示不为空,跳转到input
request.setAttribute("err", errMsg);
return mapping.findForward("input");
} else {
//否则跳转到welcome
return mapping.findForward("welcome");
}
}
}
execute 方法中除了包含HttpServletRequest , HttpServletResponse 参数外,还包括了两个类型的参数: ActionForm, ActionForward。这两个参数分别用于封装用户的请求参数和控制转发。可以注意到: Action 的转发无须使用RequestDispatcher 类,而是使用ActionForward 完成转发。
注意:业务控制器Action 类,应尽量声明成public ,否则可能出现错误。并注意重写的execute 方法,其后面两个参数的类型是HttpServletRequest 和HttpServlet Response ,而不是ServletRequest 和SedvetResponse 。
(3)Struts配置文件
在转发时也没有转向一个实际的JSP 页面,而是转向逻辑名error, input, welcome 等。逻辑名并不代表实际的资源,因此还必须将逻辑名与资源对应起来。实际上,此处的控制器没有作为Servlet 配置在web.xml 文件中,因此必须将该Action配置在Struts 中,让ActionServlet 了解将客户端请求转发给该Action 处理。而这一切都是通过struts-config.xml 文件完成的。下面是struts-config.xml 文件的源代码:
<struts-config>
<actlon-mappings>
<!-- 配置Struts 的Action. Action 是业务控制器-->
<action path="/login" type="LoginAction">
<!-- 配置该Action 的转发-->
<forward name="welcome" path="/WEB-INF/jsp/welcome.jsp" />
<!-- 配置该Action 的转发-->
<forward name="error" path="/WEB-INF/jsp/error.jsp" />
<!-- 配置该Action 的转发-->
<forward name="input" path="/login.jsp" />
</action>
</actlon-mappings>
</struts-config>
从上面的配置文件可看出, Action 必须配置在struts-config.xml 文件中。注意其中Action 的path 属性: /login,再查看login.jsp 登录form 的提交路径login.do。两个路径的前面部分完全相同, ActionServlet负责拦截所有以.do 结尾的请求,然后将.do 前面的部分转发给struts-config.xml文件中Action 处理,该Action 的path 属性与请求的.do 前面部分完全相同。
配置Action 时,还配置了三个局部Forward。
• welcome: 对应IWEB-INF/jsp/welcome.jsp 。
• error: 对应IWEB-INF/jsp/error.jsp 。
• input: 对应/login.jsp 。
Forward 有局部Forward 和全局Forward 两种,前者只对于某个Action 有效,后者则对于整个Action 都有效。
注意:将JSP 页面放在WEB-INF 路径下,可以更好地保证JSP 页面的安装。因为大多数Web容器不允许直接访问WEB-INF 路径下的资源。因此,这些JSP 页面不能通过超级链接直接访问,而必须使用Struts 的转发才可以访问。