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

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S