众所周知,Struts2是一款优秀的Java MVC框架,由控制器决定展现那个视图给用户。从开发者角度来认识一个框架,第一步是能快速搭建一个基于该框架的应用或demo,在会使用的基础上进一步了解其实现原理更有助于运用。
关于Struts2实现原理,以后会详细阐述,我们先来做一个小小实验,也就是在Web 应用中最常见的用户登录。
1. 配置Web.xml
在Web.xml中加上如下内容:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
该配置就是告诉Web容器(在作者的应用中就是tomcat)也就是:对于所有的url请求都是用一个叫struts2的Filter进行处理,这个Filter就是Struts2 程序的入口。通过这个Filter及相关类的处理才能实现MVC控制。
2. 配置Struts.xml
在程序中引入Struts2相关类库(jar包)之后,必须配置Struts.xml,告诉容器:对那些url请求应该调用哪个Action类处理,根据处理的结果展示某个视图。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="true" />
<package name="Main" namespace="/" extends="struts-default">
<action name="login_*" class="com.struts.action.LoginAction" method="{1}">
<result name="input">/Login.jsp</result>
<result name="success">/Success.jsp</result>
</action>
</package>
</struts>
Note:这里使用了DynamicMethodInvocation,根据action的名字调用对应的method,如果请求的url是http://<hostname:port>/<Application Name>/login_Input,容器会调用com.struts.action.LoginAction类的Input 方法进行处理,该方法不做任何处理,直接返回字符串”input”,Struts2会展示Login.jsp页面给浏览器;如果请求的url是http://<hostname:port>/<Application Name>/login_Login, 容器会调用com.struts.action.LoginAction类的Login方法(在struts2中,没有指定method时,默认调用execute方法),在该方法中进行校验用户名和密码,如果校验不通过返回字符串”input”,展示登陆页面给浏览器,如果校验成功返回字符串”success”,就展示登陆成功页面”Success.jsp”给浏览器<一般情况下是跳转到某个合适的页面,result 的type可以是redirct/redirectAction>。
3.JSP 页面
很显然Login.jsp是一个用户登录页面,要求输入用户名和密码,提交到login_Login Action进行登录验证。
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="GB18030"%>
<%@taglib uri="/struts-tags" prefix ="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Welcome to CRM!</title>
</head>
<body>
<s:form action="login_login" method="post">
<s:textfield name="username" label="username"/>
<s:password name="password" label="password"/>
<s:submit/>
</s:form>
</body>
</html>
登录成功页面Success.jsp:在这里只是模拟成功登录,为简便起见,只是提示给用户”Success”
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="GB18030"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Login Success</title>
</head>
<body>
<h1>Login Success!</h1>
</body>
</html>
4. LoginAction类(com.struts.action.LoginAction)
package com.struts.action;
import com.opensymphony.xwork2.ActionSupport;
import com.struts.model.*;
import com.struts.service.*;
public class LoginAction extends ActionSupport {
private String username;
private String password;
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;
}
public String input(){
return INPUT;
}
public String login() {
if (!Validation())
return INPUT;
// Start of business
Connection cn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Boolean LoginSuccess = false;
try {
Class.forName("com.mysql.jdbc.Driver");
cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/personal?user=root&password=root");
String getUserSql = "select * from userinfo where username = ? and password = ?";
pstmt = cn.prepareStatement(getUserSql);
pstmt.setString(1, userName);
pstmt.setString(2, passWord);
rs = pstmt.executeQuery();
if (rs.next()){
LoginSuccess = true;
}
} catch (SQLException e) {
//记录日志
} finally{
try{
rs.close();
pstmt.close();
cn.close();
}catch(SQLException e1){
//记录日志
}
}
//End of business
if (LoginSuccess)
return SUCCESS;
return INPUT;
}
public boolean Validation() {
if (username != null && !username.trim().equals("") && password != null
&& !password.trim().equals(""))
return true;
else
return false;
}
}
这里必须有get/set 方法(确切的说是set方法),Struts才会帮你自动将页面提交的username 和password赋值给Action类的username 和password字段。
比较好的做法是将业务逻辑封装成一个单独的模块,在login方法中new 一个业务逻辑类对象,调用对应方法根据用户名密码去数据库校验,get一个Model实例,如果该实例不为空,表明对应用户名和密码的用户存在,返回成功,否则返回input,跳转到登录页面,要求重新输入用户名和密码。
对于初学者而言,这已经足够了。
5. 写给自己
不积跬步,无以至千里,记录点滴,激励自己,帮助来者,与君共勉。