Java之旅Struts系列(2)——Struts1(精华)

2024-05-26 07:38

本文主要是介绍Java之旅Struts系列(2)——Struts1(精华),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  上篇已经基本介绍了关于MVC的一些知识,现在我们来讲解Struts估计很容易就会理解了。

 1.      理论讲解

  Struts1的程序流程图:

  流程详解:

  Struts1框架是以ActionServlet作为核心控制器,整个的应用由客户端请求驱动,当我们的客户端向web发送请求的时候,请求将被Struts1的核心控制器ActionServlet拦截,ActionServlet根据请求决定是否调用业务逻辑控制器来处理用户的请求,当结果处理完毕后,处理结果将通过JSP呈现给用户。

  整个框架的核心就是控制器,控制器包括两个部分,一个是核心控制器,另一个就是业务逻辑控制器。ActionServlet是核心控制器,而我们定义的action就是我们说的业务逻辑控制器,下面的例子会进行一一的讲解。

  核心控制器的职责是将用户相应的请求转发给相应的业务逻辑控制器进行处理。

那么MVC是如何在Struts1中进行体现的呢?

  Struts1的MVC体现

   Model部分:Struts1的Model部分主要由底层业务逻辑处理来担当,封装了业务逻辑以及数据访问层实现,Model部分的组成对于大型的项目来说,不仅仅是一个简单的javaBean就可以完成,比如在ITOO这个项目中,我们业务逻辑层用到是多个EJB组件,并且存在远程调用其他的服务,也就是说整个的model提供了一套完整的业务逻辑处理。

   View视图部分的显示是通过渲染实现的。View采用的是jsp来实现的,利用Struts1丰富的标签库或者是el表达式等等,从而减少脚本的出现,方便的进行处理结果的显示。

   Controller部分:包含上面我们讲解到的核心控制器ActionServlet以及业务逻辑控制器Action。

 2.       实战应用

  俗话说的好“光说不练假把式,光练不说傻把式,又练又说真把式”,讲解了那么多的理论,下面我们来实战一下吧。

       对应上面的理论讲解,我们来进行项目的实战。以登录为例。

  拷贝相应的配置文件和jar包

  新建一个web项目,Structs只能是web项目,因为其是对servlet做了一个包装。

  拷贝相应的jar以及Struts1的核心配置文件struts-config.xml,这里进行了相关的相应的业务逻辑控制器的相关的配置。

   struts-config.xml:

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE struts-config PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN""http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"><struts-config><form-beans><form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/></form-beans><action-mappings><action path="/login" type="com.bjpowernode.struts.LoginAction"name="loginForm"		scope="request"		><forward name="success" path="/login_success.jsp" /><forward name="error" path="/login_error.jsp"/>		</action></action-mappings>
</struts-config></strong></span>

  这里面的东西一会我们一一解释。

  我们先来建立一个ActionForm类,命名为LoginActionForm:

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>package com.bjpowernode.struts;import org.apache.struts.action.ActionForm;/*** 登录ActionForm,负责表单收集数据* 表单的属性必须和ActionForm中的get和set的属性一致* @author Administrator**/
@SuppressWarnings("serial")
public class LoginActionForm extends ActionForm {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;}
}</strong></span>

  ActionForm类的主要作用就是负责收集表单上的数据,建立的属性字段与表单上的是统一的,用专门的类来收集表单上数据故而很方便,但是我们可以看到这个类并不是一个pojo对象,而是一个具有侵入性也就是存在了依赖,体现在上面的就是继承了某一个类。

   建立一个业务逻辑控制器Action实例:

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>package com.bjpowernode.struts;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;/*** 登录Action* 负责取得表单数据、调用业务逻辑、返回转向信息* * @author Administrator**/
public class LoginAction extends Action {@Overridepublic ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {		LoginActionForm laf = (LoginActionForm)form;String username = laf.getUsername();String password = laf.getPassword();UserManager userManager = new UserManager();try {userManager.login(username, password);//request.setAttribute("username", username);return mapping.findForward("success");}catch(UserNotFoundException e) {e.printStackTrace();request.setAttribute("msg", "用户不能找到,用户名称=【" + username + "】");}catch(PasswordErrorException e) {e.printStackTrace();request.setAttribute("msg", "密码错误");}return mapping.findForward("error");}}</strong></span>

  这个是一个业务逻辑处理的控制器,不仅仅可以获取到表单上的数据,细心的同学会发现调用了JavaBean来处理页面的请求,没有看错,就是UserManager userManager = new UserManager();但是我们也是可以看到的Action实例不仅仅是继承了Action,并且其方法excute方法中的参数也是依赖于Struts api以及Servlet api的,这样的依赖注定其具有不灵活性或者良好的维护性,怎么办?之后我们会讲解。

   javaBean(UserManager)

  这是控制器调用业务逻辑层的处理逻辑的写法,那么我们的javaBean(UserManager)是如何书写的呢?

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>package com.bjpowernode.struts;public class UserManager {public void login(String username, String password) {if (!"admin".equals(username)) {throw new UserNotFoundException();}if (!"admin".equals(password)) {throw new PasswordErrorException();}}
}</strong></span>

  这里我们并没有和数据库进行交互,自己手动书写的用户名和密码,并且进行了相关的异常处理,这些都是属于运行时的异常,具体异常的代码不在这里进行展示了。这里展示对于前台的进行如何去进行相关的处理并且将结果进行返回。

   页面的相关处理

   处理结果返回成功后页面:

   在Action中我们看到:return mapping.findForward("success");这其实是将处理的结果返回给jsp页面,经过视图的处理和渲染最终输送到浏览器客户端进行显示,呈现给用户。

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><%@ page language="java" contentType="text/html; charset=GB18030"pageEncoding="GB18030"%>
<!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=GB18030">
<title>Insert title here</title>
</head>
<body>${loginForm.username },登录成功
</body>
</html></strong></span>

  那么我们是如何向Action发送请求的呢?

  登录页面了 login.jsp

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><%@ page language="java" contentType="text/html; charset=GB18030"pageEncoding="GB18030"%>
<!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=GB18030">
<title>Insert title here</title>
</head>
<body><form action="login.do" method="post">用户:<input type="text" name="username"><br>密码:<input type="password" name="password"></br><input type="submit" value="登录"></form>
</body>
</html></strong></span>

   Web.xml配置

   还有一个最重要就是我们的web配置文件,这是全局最重要的配置文件,因为默认这是程序运行时自动加载的项,如果Struts-config.xml文件没有在此处进行配置是无法进行加载的

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><servlet><servlet-name>action</servlet-name><servlet-class>org.apache.struts.action.ActionServlet</servlet-class><init-param><param-name>config</param-name><param-value>/WEB-INF/struts-config.xml</param-value></init-param><init-param><param-name>debug</param-name><param-value>2</param-value></init-param><init-param><param-name>detail</param-name><param-value>2</param-value></init-param><load-on-startup>2</load-on-startup></servlet><!-- Standard Action Servlet Mapping --><servlet-mapping><servlet-name>action</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>  
</web-app></strong></span>

  这里配置了一些在初始化的时候的参数

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><init-param><param-name>config</param-name><param-value>/WEB-INF/struts-config.xml</param-value>
</init-param></strong></span>

  就是我们的业务逻辑控制器的配置,<servlet-name>action</servlet-name>

   <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>,这个就是我们的核心控制器的配置。

  此时来解析Struts-config.xml的配置就容易了。

   解析Struts-config.xml

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong><struts-config><form-beans><form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/></form-beans><action-mappings><action path="/login" type="com.bjpowernode.struts.LoginAction"name="loginForm"		scope="request"		><forward name="success" path="/login_success.jsp" /><forward name="error" path="/login_error.jsp"/>		</action></action-mappings>
</struts-config></strong></span>

  这里配置了我们的Actionform以及action实例,当我们请求一个Action的时候,通过核心控制器ActionServlet进行action的分发,直到找到相应的action实例进行处理,利用action-mappings进行相关的action查找,

  其中path的名字与jsp请求的路径名称是一样的,这是form表单中的<form action="login.do" method="post">;<url-pattern>*.do</url-pattern>,.do是映射通配符。

         Type:是action实例的具体路径;name就是我们获取表单数据的ActionForm类,scope是作用域的范围;而forward是对于处理结果相应的返回页面的显示和处理。至此是不是明白多了。

 3.      小结

  Struts1是MVC模式的一个体现,虽然很好地将表现层与业务逻辑进行了很好的分离,但是是还是存在很多的不足。

   第一就是:支持的表现层的技术单一,此时的Struts1只是支持JSP表现层技术,而不支持其他的(Velocity,FreeMaker技术(此时这些技术还没有出现,与时间的出现晚也存在关系))。

  但是不得不承认Struts1确实是存在很大的优势的,比如Action实例处理完用户的请求后,并没有直接转到特定的资源,而是返回的是一个ActionForward对象,其实实质上是一个逻辑视图名,这个名字与具体的视图资源的关系在我们Struts-config.xml中进行了定义,这样的好处的是可以根据action处理结果将相应的视图资源程序给用户,从而达到了视图名字与视图资源的解耦。

   第二就是与ServletAPI 以及Struts API的严重耦合。我们知道Struts1是基于Model2发展起来的,因此是完全基于Servlet API的,因此在Action实例中,我们可以看到大量的Servlet API。

<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {	}</strong></span>

   我们可以看出execute方法中存在四个参数,HttpServletRequest request, HttpServletResponse response就是Servlet API,通常这两个参数由web容器负责进行初始化,故而严重依赖于web容器。

   而我们说代码严重依赖于Struts1API,在于action实例必须继承Action基类,其中包含了大量的Struts1API,比如:ActionMapping,ActionForm以及ActionForward等等,从设计上说属于侵入性设计,这种侵入性的设计会使得一旦重构,代码复用率极低,故而使得代码复用变得不现实。

   看到了Struts1 的不足,聪明的人类绝对不会止步于此,是不是有新的解决方法呢?请继续关注下面的博客~


这篇关于Java之旅Struts系列(2)——Struts1(精华)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1003845

相关文章

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位