Struct—自定义一个简单的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>

  

最后我们登入的时候就会看到这个效果了:

时间: 2024-10-02 09:40:04

Struct—自定义一个简单的mystruct的相关文章

用C#自定义一个简单的集合

作为一个C#初学者,我也闲来无聊来自己做了一个简单的'集合',用来加深自己对集合的理解 class listNode { private object value; public listNode(object _value) { this.value = _value; } public object Value { get { return value; } } public listNode Next { get; set; } public listNode Prev { get; se

自定义一个简单的django页面

博文地址:    http://www.thedream.pub/yong-djangozi-ding-yi-ge-wang-ye/

自定义一个简单的web框架

from wsgiref.simple_server import make_server def book(request):     #视图函数 return [b'<h1> book !!! </h1>']def web(request): return [b'<h1> web !!! </h1>'] def routers(): urlpatterns = ( ('/book',book),      #url 映射    ('/web',web),

ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局 一.实现效果 二.使用纯代码自定义一个tableview的步骤 1.新建一个继承自UITableViewCell的类 2.重写initWithStyle:reuseIdentifier:方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中

iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目文件结构和plist文件 二.实现效果 三.代码示例 1.没有使用配套的类,而是直接使用xib文件控件tag值操作 数据模型部分: YYtg.h文件 // // YYtg.h // 01-团购数据显示(没有配套的类) // // Created by apple on 14-5-29. // Copyright (c) 2014年 itcase. All rights reserved. //

Custom UIView 通过xib实现一个简单地自定义视图

1 /** 2 * 使用Custom UIView的这条路,我走的很不顺利,前期犯2,中期有事,浪费了很多时间! 3 * 现在空闲的时间不多了,只能抓紧时间写两个小demo,一来做练习,二来整理下也许能给要学习的人一些帮助! 4 */ 1 /** 2 * Custom UIView常用的三种实现方法: 3 * Method_1:通过初始化的方式(eg:UITableViewCell的重写) 4 Method_2:通过drawRect的方法,使用代码自己画出想要的视图 5 Method_3:通过x

一个简单的jsp自定义标签

学到了一个简单的jsp自定义标签,后面有更多的例子,会更新出来: 例子1: 步骤: 1.编写标签实现类: 继承javax.servlet.jsp.tagext.SimpleTagSupport; 重写doTag,实现在网页上输出: 2.在web-inf目录或其子目录下,建立helloword.tld文件,即自定义标签的说明文件 注意:标签处理类必须放在包中,不能是裸体类:不需要修改web.xml: //tld: tag lib description 标签库描述 java代码: package

iOS开发UI基础—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

ios开发UI基础-使用纯代码自定义UItableviewcell实现一个简单的微博界面布局 一.实现效果 二.使用纯代码自定义一个tableview的步骤 1.新建一个继承自UITableViewCell的类 2.重写initWithStyle:reuseIdentifier:方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中) 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片) 3.提供2个模型 数据模型:

Github项目解析(十一)--&gt;一个简单,强大的自定义广告活动弹窗

转载请标明出处:一片枫叶的专栏 上一篇文章中讲解了我最近写的一个快速集成二维码扫描库,其核心的实现扫描的功能,是通过调用ZXing库实现的.由于在实现二维码扫描功能的时候发现集成二维码扫描功能并不是特别方便,于是有了将其制作成标准库的想法,这个二维码库能够快速,方便的集成二维码扫描功能,项目地址是在:android-zxingLibrary**,在项目开源后有不少同学提出了许多不错的意见,目前也在不断的迭代中,自己也学到了很多. 本文我们将讲解一个简单,强大的广告活动弹窗控件.不少App在打开的