众所周知,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. 写给自己
不积跬步,无以至千里,记录点滴,激励自己,帮助来者,与君共勉。