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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl