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

相关文章

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码

SpringBoot利用@Validated注解优雅实现参数校验

《SpringBoot利用@Validated注解优雅实现参数校验》在开发Web应用时,用户输入的合法性校验是保障系统稳定性的基础,​SpringBoot的@Validated注解提供了一种更优雅的解... 目录​一、为什么需要参数校验二、Validated 的核心用法​1. 基础校验2. php分组校验3

Java Predicate接口定义详解

《JavaPredicate接口定义详解》Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值,:本文主要介绍JavaPredicate接口的定义... 目录Java Predicate接口Java lamda表达式 Predicate<T>、BiFuncti

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

《SpringSecurity方法级安全控制@PreAuthorize注解的灵活运用小结》本文将带着大家讲解@PreAuthorize注解的核心原理、SpEL表达式机制,并通过的示例代码演示如... 目录1. 前言2. @PreAuthorize 注解简介3. @PreAuthorize 核心原理解析拦截与

一文详解JavaScript中的fetch方法

《一文详解JavaScript中的fetch方法》fetch函数是一个用于在JavaScript中执行HTTP请求的现代API,它提供了一种更简洁、更强大的方式来处理网络请求,:本文主要介绍Jav... 目录前言什么是 fetch 方法基本语法简单的 GET 请求示例代码解释发送 POST 请求示例代码解释

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++