Struts—自定义一个简单的mystruct
传统mvc开发总结:
1. 跳转代码写死,不灵活
2. 每次都去写servlet,web.xml中配置servlet!
(配置目的: 请求, Servlet处理类)
一个简单的struct案例,描述如下
登陆、注册
登陆成功 首页
登入失败 登入页
注册成功 登陆页
整理如下
项目列表如下
代码实现
前台页面登入页:
<form action="${pageContext.request.contextPath }/login.action" name="frmLogin" method="post">
用户名: <input type="text" name="name"> <br/>
密码: <input type="text" name="pwd"> <br/>
<input type="submit" value="登陆"> <br/>
</form>
注册页:
<form action="${pageContext.request.contextPath }/register.action" name="frmRegister" method="post">
用户名: <input type="text" name="name"> <br/>
密码: <input type="text" name="pwd"> <br/>
<input type="submit" value="注册"> <br/>
</form>
首页
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>index</title>
</head> <body>
欢迎你的到来,${sessionScope.userInfo.name }
</body>
</html>
后台处理代码
1、假设有一个用户类
package com.gqx.entity; public class User { private String name;
private String pwd;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
} }
2、还有一个UserDao类,处理用户的登入问题与注册问题,然后则是还有一个业务逻辑层service
package com.gqx.dao; import com.gqx.entity.User;
public class UserDao { // 模拟登陆
public User login(User user){
if ("gqxing".equals(user.getName()) && "888".equals(user.getPwd()) ){
// 登陆成功
return user;
}
// 登陆失败
return null;
} // 模拟注册
public void register(User user) {
System.out.println("注册成功:用户," + user.getName());
}
}
service
package com.gqx.service; import com.gqx.dao.UserDao;
import com.gqx.entity.User; public class UserService {
private UserDao dao=new UserDao();
// 模拟登陆
public User login(User user){
return dao.login(user); } // 模拟注册
public void register(User user) {
dao.register(user);
}
}
3、mystruct.xml文件,对整个页面跳转的逻辑的配置,每一action对应的result表示要跳转的页面的信息和处理他的相关类
<?xml version="1.0" encoding="UTF-8"?>
<mystruct>
<package>
<!-- 配置请求路径,与处理action类的关系 -->
<!--
1. 请求路径与处理Action的关系
/login = LoginAction login
success = /index.jsp 登陆成功(重定向)
loginFaild = /login.jsp 登陆失败
-->
<action name="login" class="com.gqx.framework.action.LoginAction" method="login" >
<result name="loginSuccess" type="redirect">/index.jsp</result>
<result name="loginFailed">/login.jsp</result> <!-- 默认是转发 -->
</action> <action name="register" class="com.gqx.framework.action.RegisterAction" method="register">
<result name="registerSuccess">/login.jsp</result>
</action>
</package>
</mystruct>
4、写两个类分别用来处理登入和注册响应这两个事件(注册事件和登入事件)。注意这不和servlet相同,这里返回的是一种状态(对应着前面的struct配置的xml文件中要跳转的页面)。
LoginAction类
package com.gqx.framework.action; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.gqx.entity.User;
import com.gqx.service.UserService;
/**
* Action表示动作类
* 1. 一个servlet对应一个action
* 2. action中负责处理具体的请求
*/
public class LoginAction { /**
* 处理登陆请求
*/
public Object login(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Object uri = null; // 1. 获取请求数据,封装
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
User user = new User();
user.setName(name);
user.setPwd(pwd); // 2. 调用Service
UserService userService = new UserService();
User userInfo = userService.login(user);
// 3. 跳转
if (userInfo == null) {
// 登陆失败
uri="loginFailed"; //login.jsp
} else {
// 登陆成功
request.getSession().setAttribute("userInfo", userInfo);
// 首页
uri ="loginSuccess"; //index.jsp
}
return uri;
}
}
RegisterAction类
package com.gqx.framework.action; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.gqx.entity.User;
import com.gqx.service.UserService; public class RegisterAction {
/*
* 处理注册事件
*/
public Object register(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 获取请求数据,封装
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
User user = new User();
user.setName(name);
user.setPwd(pwd); // 2. 调用Service
UserService userService = new UserService();
userService.register(user);
return "registerSuccess"; //login.jsp }
}
5、为了能更好的解析mystruct.xml文件,这里写了几个javabean去封装这个xml文件的信息
首先是对result(<result name="loginSuccess" type="redirect">/index.jsp</result>)的信息封装类
package com.gqx.framework.bean;
/**
* 封装结果视图
* <result name="loginSuccess" type="redirect">/index.jsp</result>
* @author Administrator
*
*/
public class Result {
private String name; //封装结果的标记
private String type; //封装跳转类型,默认为“redirect”—重定向
private String page; //封装跳转的页面
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
}
然后是action节点的封装
package com.gqx.framework.bean; import java.util.Map; /**
* 封装action节点
* <action name="login" class="com.gqx.framework.action.LoginAction" method="login" >
<result name="loginSuccess" type="redirect">/index.jsp</result>
<result name="loginFailed">/login.jsp</result> <!-- 默认是转发 -->
* </action>
*/
public class ActionMapping { private String name; //封装路径名称
private String className; //封装action的类全名
private String method; //封装处理方法
private Map<String, Result> result; //封装视图集合
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Map<String, Result> getResult() {
return result;
}
public void setResult(Map<String, Result> result) {
this.result = result;
} }
最后一个则是对整个action的管理,即管理着mystruct的类,在这里去解析xml文件(这里用到了dom4j的jar包)同时将解析的信息封装到action中去,在这里的构造方法中传入了init()函数(该函数用于封装action信息),然后通过本类去操控需求
package com.gqx.framework.bean; import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import javax.management.RuntimeErrorException; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; /**
* 加载配置文件,封装整个mystruct.xml
* @author Administrator
*
*/ public class ActionMappingManager {
//保存action的集合(根据action的name去拿result)
Map<String , ActionMapping> allAction; //由于init方法无法被外界被调用(private修饰),这里要写一个无参的构造方法去调用
public ActionMappingManager() {
// TODO Auto-generated constructor stub
allAction=new HashMap<String, ActionMapping>();
//初始化
this.init();
} /**
* 根据请求路径名称,返回action映射对象
* 即有action的name返回一个由actionMapping包装的如下结构
* <action name="login" class="com.gqx.framework.action.LoginAction" method="login" >
<result name="loginSuccess" type="redirect">/index.jsp</result>
<result name="loginFailed">/login.jsp</result> <!-- 默认是转发 -->
</action>
*/
/**
*
* @param actionName 当前返回路径
* @return 返回配置文件中代表action节点的actionMapping对象
*/
public ActionMapping getActionMapping(String actionName) {
// TODO Auto-generated method stub
if (actionName == null) {
throw new RuntimeException("传入参数不能为空!");
}
ActionMapping actionMapping=allAction.get(actionName);
if (actionMapping==null) {
throw new RuntimeException("路径在mystruct中找不到!请检查。");
}
return actionMapping;
} //初始化allAction集合
private void init() {
// TODO Auto-generated method stub
/****************dom4j读取配置文件**********/
try {
//1、得到解析器
SAXReader reader=new SAXReader();
//得到src/下的文件流
InputStream insStream=this.getClass().getResourceAsStream("/mystruct.xml");
//2、加载文件
Document doc=reader.read(insStream);
//3、得到根文件
Element rootElement=doc.getRootElement();
//4、得到package节点
Element elem_package=rootElement.element("package");
//5/5得到package节点下的所有action节点
List<Element> listAction=elem_package.elements("action");
//6、遍历action且封装
for (Element element : listAction) {
//6、1封装一个ActionMapping对象
ActionMapping actionMapping=new ActionMapping();
/**
* <action name="login" class="com.gqx.framework.action.LoginAction" method="login" >
<result name="loginSuccess" type="redirect">/index.jsp</result>
<result name="loginFailed">/login.jsp</result> <!-- 默认是转发 -->
</action>
*/
//封装action
actionMapping.setName(element.attributeValue("name"));
actionMapping.setClassName(element.attributeValue("class"));
actionMapping.setMethod(element.attributeValue("method")); //封装action下的result
Map<String, Result> results=new HashMap<String, Result>();
//得到当前action下所有的result子节点
Iterator<Element> iterator=element.elementIterator("result");
while (iterator.hasNext()) {
//当前迭代的每一result
Element element2 = (Element) iterator.next();
Result result =new Result();
//封装
result.setName(element2.attributeValue("name"));
result.setType(element2.attributeValue("type"));
result.setPage(element2.getTextTrim());
//添加到results中
results.put(result.getName(), result);
} actionMapping.setResult(results);
//6、2actionMapping添加到Map集合中
allAction.put(actionMapping.getName(), actionMapping); }
} catch (Exception e) {
// TODO Auto-generated catch block
throw new RuntimeException("xml读取失败,初始化错误!");
}
} }
6、最后则是写全局的控制器ActionServlet,由它来管理ActionMappingManager中要跳转的页面信息,如外界通过访问http://localhost:8080/mystruct/login.jsp发来http://localhost:8080/mystruct/login.action请求,首先将其解析成login,根据这个login名字在mystruct中找到对应的class类(class="com.gqx.framework.action.LoginAction")和方法(method="login"),同时根据方法名称和参数得到类中的方法,通过反射得到调动其方法,便可得到一个返回的uri(表是状态,如:loginSuccess),然后由配置文件(管理类ActionMappingManager)依据uri来控制要跳转的相应页面。
package com.gqx.framework; import java.io.IOException; import java.lang.reflect.Method; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.gqx.framework.bean.ActionMapping;
import com.gqx.framework.bean.ActionMappingManager;
import com.gqx.framework.bean.Result; public class ActionServlet extends HttpServlet { /**
* 核心控制器,此项目只有一个servlet
* 拦截所有的以action结尾的请求
*/
private static final long serialVersionUID = 1L; ActionMappingManager actionMappingManager;
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
//第一次访问时启动时候执行,希望启动的时候执行,在xml文件中配置load-on-startup在启动的是执行 //配置文件的读取,在ActionMappingManage的构造方法中调用了init方法。
actionMappingManager=new ActionMappingManager();
} public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
//1、获取请求的uri,得到请求的路径名称【login】
String uri=request.getRequestURI(); //得到login,根据login去mystruct.xml配置文件去第2步
String actionName=uri.substring(uri.lastIndexOf("/")+1,uri.indexOf(".action")); // 2、根据路径名称,读取配置文件,得到类的全名
ActionMapping actionMapping=actionMappingManager.getActionMapping(actionName);
String className=actionMapping.getClassName(); //当前请求的处理方法【method="login】
String method=actionMapping.getMethod();
//3、通过反射创建对象,调用方法,获取方法返回的标记
Class<?> clazz=Class.forName(className);
//实例化,创建对象
Object object=clazz.newInstance();
/**
* 这里的参数只能是HttpServletRequest.class,不能是request.class。
* 因为request是一个实现类,而这里必须是以接口.class为参数
*/
Method m=clazz.getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class); //调用方法返回的标记
String returnValue=(String) m.invoke(object,request,response); //4、拿到标记,读取配置文件,对应的标记页面
Result result=actionMapping.getResult().get(returnValue);
//跳转类型
String type=result.getType();
//页面
String page=result.getPage(); //5、跳转
if ("redirect".equals(type)) {
response.sendRedirect(request.getContextPath()+page);
}else {
request.getRequestDispatcher(page).forward(request, response);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
} }
最后则是配置这个Actionservlet在服务器的web.xml文件了
<!-- 核心控制器 -->
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>ActionServlet</servlet-name>
<servlet-class>com.gqx.framework.ActionServlet</servlet-class>
<!-- 启动的时候执行servlet的初始化方法 -->
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>ActionServlet</servlet-name>
<!-- 拦截所有的action -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
最后我们登入的时候就会看到这个效果了:
Struts—自定义一个简单的mystruct的更多相关文章
- 自定义一个简单的JDBC连接池
一.什么是JDBC连接池? 在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码: public static Connection getCo ...
- 自定义一个简单的SegmentedControl
先大概看下我们想实现简单的效果 源码 // // DSegmentedControl.swift // IOS学习之自定义UISegmentedControl // // Created by din ...
- 用C#自定义一个简单的集合
闲来无聊来自己做了一个简单的'集合',用来加深自己对集合的理解 class listNode { private object value; public listNode(object _value ...
- 代码调试--自定义一个简单的debug函数
function debug(){ $num_args = func_num_args(); //实参个数 $arg_list = func_get_args(); //返回某一个实参,必须是实参数组 ...
- 自定义一个简单的web框架
from wsgiref.simple_server import make_server def book(request): #视图函数 return [b'<h1> book ...
- Eclipse搭建Struts框架,及一个简单的Struts例子
一.下载struts2.0.1 http://struts.apache.org/downloads.html,下载struts-2.0.1-all.zip,这个压缩包中包含了开发struts2所需的 ...
- struts1:(Struts重构)构建一个简单的基于MVC模式的JavaWeb
在构建一个简单的基于MVC模式的JavaWeb 中,我们使用了JSP+Servlet+JavaBean构建了一个基于MVC模式的简单登录系统,但在其小结中已经指出,这种模式下的Controller 和 ...
- [安卓] 18、一个简单的例子做自定义动画按钮和自定义Actionbar
在做安卓UI的时候有时候需自定义具有动画效果的按钮或需要自定义一下actionbar~ 本节用一个简单的demo讲如何自定义具有动画效果的按钮,以及个性化的actionbar 下面是效果: 其中: △ ...
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...
随机推荐
- Oracle Exception 处理
1.问题来源Oracle中可以用dbms_output.put_line来打印提示信息,但是很容易缓冲区就溢出了.可以用DBMS_OUTPUT.ENABLE(1000000);来设置缓冲区的大小.但是 ...
- Upload/download/UrlConnection/URL
文件上传的核心点 1:用<input type=”file”/> 来声明一个文件域.File:_____ <浏览>. 2:必须要使用post方式的表单. 3:必须设置表单的类型 ...
- GCC编译C程序源代码
编译简单的 C 程序 C 语言经典的入门例子是 Hello World,下面是一示例代码: #include <stdio.h> int main(void) { printf ...
- ASP.NET中的FileUpload文件上传控件的使用
本篇文章教大家如何将客户端的图片或者文件上传到服务器: 无论是上传图片(.jpg .png .gif等等) 文档(word excel ppt 等等). 第一步:放入以下三个控件 Image控件,Fi ...
- Java [leetcode 29]Divide Two Integers
题目描述: Divide two integers without using multiplication, division and mod operator. If it is overflow ...
- Mysql加密方式
MySQL数据库的认证密码有两种方式, MySQL 4.1版本之前是MySQL323加密,MySQL 4.1和之后的版本都是MySQLSHA1加密, MySQL数据库中自带Old_Password(s ...
- mysql slave 错误解决
执行CHANGE MASTER TO master_host............后报错 ERROR 1201 (HY000): Could not initialize master info s ...
- java惯用法转载
目录 实现: equals() hashCode() compareTo() clone() 应用: StringBuilder/StringBuffer Random.nextInt(int) It ...
- 自定义 SharePoint 2010 快速启动栏和顶部链接栏
转:http://vickynuli.blog.163.com/blog/static/180438492201281434249486/ 在网上找到篇文章,自定义快速启动栏和顶部链接栏,以下为代码, ...
- Diamond
Diamond主要提供持久配置的发布和订阅服务,最大特点是结构简单,稳定可靠.Diamond的主要使用场景是用来进行动态数据库切换与扩容,进行一些业务系统运行时开关配置的推送.Diamond产品专注于 ...