`
山有峰则灵
  • 浏览: 28408 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

闲人笔记1:HelloServlet

阅读更多
从一个servlet开始吧
建立一个页面做一个简单的输入,比如用户登录
<form action="./XXXX " method="post">
    	<table>  
    		<tr><td><input name="name" type="text" size="10"/></td></tr>
    		<tr><td><input name="pwd" type="password" size="10"/></td></tr>
    		<tr><td><input type="submit" value="submit"/></td></tr>
    	</table>
</form>

然后我们的业务逻辑方法,在Business类中实现这样一个方法
public String goSomePageOrDoSomeThing(String name,String pwd){
		if(name.equals("user")&&pwd.equals("pwd"))
			return "sucess";
		else
			return "error";
	}

最后新建一个Action类继承HttpServlet复写其中的service方法
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String name = req.getParameter("name");
		String pwd  = req.getParameter("pwd");
		Business business = new Business();
		//调用我们的业务逻辑,最终判断是否成功
		if(business.goSomePageOrDoSomeThing(name,pwd).equals("Sucess")) {
			req.getRequestDispatcher("/sucess.jsp").forward(req, resp);
		}else{
			req.getRequestDispatcher("/error.jsp").forward(req, resp);
		}
	}

这是一个很简单的servlet的使用,在web.xml中配置了servlet的相关参数便可以实现这样的一个业务逻辑。之后根据返回结果,我们判断是到哪一个页面。但,在一个J2EE应用中有成百上千个业务逻辑,我们不可能为每一个方法都配置一个servlet。当然我们可以用一个特定的参数,比如method在每一个url后缀中添加要执行的Business类的方法名,比如”/XXXX?method=add”. 可如果每一个servlet中都要对应一个模型的crud操作的话,最后的代码可能会变成这样
if(method.equals("add")){
		//business do some add op, business.addSomeThing();
			....
		}else if(method.equals("delete")){
			....
		}else if(method.equals("update")){
			...
		}else if(method.equals("detail")){
			...
		}.....


在doPost或是doGET方法中会有很多if else语句的出现,这样使得代码变得很糟,难于维护。
有没有更好的方法?虽然这比把所有的代码都写在JSP中清晰了一些了,可依然难于构建一个满意的程序。

我们想要做的是:隔离变化的部分

试想千百个servlet都做这些工作,他们的名字不同,逻辑不同,但他们都重复的做着三件事。

1 从页面采集数据
2 唤醒相应的业务逻辑层的方法
3 将返回的参数放入到request中,转发或重定向请求.

首先,我们把Action的web.xml映射配置做一下修改,比如
<servlet-mapping>  
  	<servlet-name>Action</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

我们把url-pattern 中的过滤规则改为 *.do,即所有以.do结尾的请求,都会由我们的Action管理,这里Action类作为前端控制器。
同样在service方法中,我们可以通过
req.getRequestURI();得到它的url路径比如:/test/login.do
截取字符串
		String name = req.getRequestURI();
       int from = req.getRequestURI().lastIndexOf("/");
		   int  end  = req.getRequestURI().lastIndexOf(".do");
name = name.substring(from, end);

这里我们最后得到的name是“/login”在这里我们需要一个配置文件能够和业务逻辑相对应。比如一个XML文件,用它来描述业务逻辑所在的类和执行之后的页面
<action-config>
	<action id="/login" class="com.hello.servlet.Business">
		<vo class="com.hello.servlet.valobj.VO"/>
		<forward name="success" path="/sucess.jsp"/>
		<forward name="error" path="/error.jsp"/>
	</action>
</action-config>

假设我们有一个Map在servlet初始化得时候,我们写一段程序,去读这个xml文件,然后把key(id) value(class)放置入这个Map中,而现在我们所需要做的就是在这个Map中找寻是否存在这样的一个action
用dom4j实现一个很粗陋的程序,仅为演示这样一个过程
HashMap<String,String> actionConfig = new HashMap<String,String>();

	public void xmlRead() throws DocumentException, FileNotFoundException {
		SAXReader saxReader = new SAXReader();
		Document doc = saxReader.read(Thread.currentThread()
		.getContextClassLoader().getResourceAsStream("action.xml"));
		xmlRead(doc.getRootElement());
	}

	public void xmlRead(Element element) {
		Iterator<Element> it = element.elementIterator();
		while (it.hasNext()) {
			Element e = it.next();
			String key = e.getParent().attributeValue("id");
			if (e.getName().equals("action")) {
				actionConfig.put(e.attributeValue("id"), e.attributeValue("class")+"");
			}
			if (e.getName().equals("vo")) {
				actionConfig.put(key+".vo", e.attributeValue("class")+"");
			}
			if(e.getName().equals("forward")){
			actionConfig.put(key+".forward."+e.attributeValue("name"), e.attributeValue("path")+"");
			}
			xmlRead(e);
		}
	}

在init方法中加入xmlRead();这样在servlet启动时,会自动读取我们的配置文件
key 为/login 值为com.hello.servlet.Login
forward 的key 我们取,/login + 一个”.forward.”字符串+name的值
actionform 的key 取  /login + 一个“actionform”字符串
这样我们就知道了,所有映射关系

接下来我们要接触的一个设计模式:命令设计模式
public interface Action {
	public String execute();
}

非常简洁,但这是一个非常实用的设计模式。只需要实现这个接口,所有的类便可以统一使用XX.execute()调用其所需的方法,每个类实现的内容虽然不同,但在这一步,却都在进行一个相同的过程,唤醒业务逻辑层。
恩,我们需要把参数传递给业务层的组件。
可能,你会想要这么做
public interface Action {
	public String execute(HttpServletRequest req,HttpServletResponse resp);
}

看上去不错,有了request和response我们不但可以拿取参数,还可以转向。但这样做无法避免一堆一堆类似于
req.getParameter("name");
如此的重复的劳动。

用一个VO做参数的传递对象,一段粗陋的程序仅仅为了演示这个过程
Class clzz = Thread.currentThread().getContextClassLoader().loadClass("com.hello.servlet.VO");
			Object o = clzz.newInstance();
			for(Field f :clzz.getFields()){
				f.set(o, req.getParameter(f.getName()));
			}

找到配置中对应的VO,反射机制实例化它,然后注入参数。
com.hello.servlet.VO将VO从前面的配置map中取出

最后在需要的地方VO vo = (VO) o;进行转型

这样一来我们execute中的方法又变成了这样
public String execute(HttpServletRequest req,HttpServletResponse resp,Object object);

object 为传递的参数。但这样做我们如何来做服务器端得验证?
我们不如建立一个新的类比如 ValueObject
在其中加入
public ActionErrors validate(HttpServletRequest request…) {}

这样一个方法,然后所有的VO都去继承该类。然后再实例化VO后总是调用该方法

同理我们也从配置文件中拿到对应的action类,实例化然后调用它的execute方法。
//init action
Class actClz = Thread.currentThread().getContextClassLoader().loadClass(actionConfig.get(name));
			Object actObj = actClz.newInstance();
			Class args[] = { HttpServletRequest.class,HttpServletResponse.class, ValueObject.class };
			Method meth = actClz.getMethod("execute", args);
			Object[] objs = { req, resp, vo };
			//invoke the method get the result
			Object resultObj = meth.invoke(actObj, objs);

在业务逻辑中实现
public String execute(HttpServletRequest req, HttpServletResponse resp,ValueObject vo) {
		VO userVO = (VO) vo;
		if(userVO.getName().equals("user")&&userVO.getPwd().equals("pwd"))
			return "success";
		else
			return "error";
	}

最后
//从map中找到其对应的页面
			req.getRequestDispatcher(actionConfig.get(name + ".forward."+resultObj.toString())).forward(req, resp);


这可能是我们拿到这个问题后,想要解决它的最本能的想法,但很显然还需要慢慢细化,然后不断的改进,甚至推翻它。
代码见附件
2
0
分享到:
评论
3 楼 山有峰则灵 2009-07-25  
facing 写道
我晕,你错误页面和正确页面都是一句话Welcome!你死不死?

不然生活中不是少了很多乐趣?是吧
2 楼 山有峰则灵 2009-07-25  
这是个惊喜嘛~
1 楼 facing 2009-07-24  
我晕,你错误页面和正确页面都是一句话Welcome!你死不死?

相关推荐

    01------helloServlet.rar

    1.写java代码 2.web.xml配置文件 3.源码编译为字节码,部署到tomcat 当前程序主要讲解: 1、输出HTML代码到浏览器:浏览器只能执行html css javascript,所以输出的内容也必须是html css javascript代码 2、...

    HelloServlet:测试詹金斯

    1. **Servlet基础** Servlet是Java Web开发中的核心组件,它是一个Java类,遵循Servlet API(Java Servlet API)定义的接口。Servlet的主要职责是接收来自客户端(如浏览器)的请求,处理这些请求,并返回响应。...

    helloservlet.rar

    1. **Servlet**: Servlet是Java EE(Enterprise Edition)平台中的核心组件之一,主要用于扩展服务器的功能,处理来自客户端(如Web浏览器)的请求,并向客户端发送响应。"HelloServlet"这个名字暗示了这个示例会...

    HelloServlet.class

    HelloServlet.class

    HelloServlet.java

    HelloServlet.java

    超详细的ServletL学习笔记

    ### 超详细的Servlet学习笔记 #### 一、Servlet简介 **Servlet** 是Java平台上的一个重要的技术标准,主要用于扩展Web服务器的功能。它允许开发者创建能够处理动态内容的应用程序组件,这些组件通常被称为...

    HelloServlet

    1. **web.xml**:这是Web应用的部署描述符,用于配置Servlet。在`web.xml`中,你会看到一个名为`HelloServlet`的Servlet配置,它将Servlet类映射到一个URL路径,比如`/hello`。例如: ```xml &lt;servlet-name&gt;...

    Servlet&JSP学习笔记

    ### Servlet&JSP 学习笔记精要 #### 一、Servlet 基础 ##### 1.1 Web 容器 - **概念**: Web 容器是支持 Servlet 和 JSP 运行的基础环境,主要功能是加载和管理 Servlet 实例,处理客户端请求并返回响应。常见的 ...

    helloservlet

    "HelloServlet"是一个初学者常常接触的示例,它展示了如何创建并运行一个基本的Servlet。在这个简单的项目"helloservlet-master"中,我们将深入探讨Servlet的基础知识、它的作用以及如何设置和运行一个Servlet。 ...

    2021-2022计算机二级等级考试试题及答案No.17926.docx

    13. Servlet部署:HelloServlet类应放在Web应用的WEB-INF/classes目录下,并且按照包结构组织,所以正确路径是D。 14. Word操作:在Word中,可以通过在正文区拖动鼠标快速选定文本,选项正确。 15. 检索Session...

    springboot课堂笔记,如果觉得好给我留言要教学视频

    public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute...

    06_尚硅谷_Servlet_王振国 - 课堂笔记1

    1. 构造器方法执行:首次请求Servlet时,服务器会创建Servlet实例,并调用其构造器。 2. init初始化方法执行:Servlet实例创建后,会调用init方法进行初始化操作,只在Servlet的生命周期中调用一次。 3. service方法...

    2021-2022计算机二级等级考试试题及答案No.16993.docx

    24. **Servlet部署**:HelloServlet类位于特定包下,class文件应放在应用的WEB-INF/classes目录下,对应选项D。 25. **JSP页面显示变量**:在JSP中显示name的值,可以使用`&lt;%=name%&gt;`,选项B正确。 这些知识点涵盖...

    2021-2022计算机二级等级考试试题及答案No.9953.docx

    19. Servlet部署:HelloServlet类位于org.javathinker包下,对应的class文件应放在helloapp/WEB-INF/classes/org/javathinker/HelloServlet.class目录下。 20. 打印命令位置:与打印输出相关的命令通常在文件菜单中...

    java web笔试题集锦经典2011年8月经典笔试题

    按照Java Web的标准,Servlet的.class文件应该放在WEB-INF/classes目录下,如果类位于包结构中,如org.javathinker.HelloServlet,那么实际的路径应为(D) helloapp/WEB-INF/classes/org/javathinker/HelloServlet....

    Servlet笔记2

    1. 创建一个类并实现Servlet接口,包含`service`方法,用于处理请求。 2. 在web.xml配置文件中设置Servlet的映射,通过`servlet-name`指定Servlet的名称,`url-pattern`定义访问URL。 例如: ```xml ...

    helloservlet:一个小型而简单的Web应用程序

    带有嵌入式Jetty 9和spring-boot-maven-plugin的HelloServlet 3.0 Maven项目 我的代码。 一个小型而简单的Web应用程序。 我为Rasperry Pi设计,但是它可以在任何平台上使用。 /丹尼尔·马雷尔(Daniel Marell)

    severlet与Jsp的web组件开发

    1. **请求**:客户端通过建立TCP连接向服务器发送HTTP请求,请求通常包括请求方法(GET、POST等)、请求URL和可能的请求头。 2. **响应**:服务器接收到请求后,解析并处理请求,然后生成一个HTTP响应,其中包含状态...

Global site tag (gtag.js) - Google Analytics