14. Struts1.x note

Day1:
overview:
1.MVC概述
2.Struts框架 (技术概览)
3.Struts开发步骤
4.Struts新手上路
5.Struts详解
6.使用工具构建struts应用
**************************************************************

一 MVC概述 (教材Page 219)
1 起源

2 设计理念
图(Page 219)

Controller:
Model:
View:

3.分层设计对Model的影响

4.Web MVC的发展(Page 221 ~ 227)
Model1 ---> Model2 ---> Framework
1)Model1的特点(Page 222)
2)Model2的特点(Page 224)
3)Framework的引入(Page 226)

引入框架的作用
A. 使得功能组件松散耦合,甚至可配置
B. 提供公用的服务:
例如:i18n,安全,表单的重复提交,文件上传……
C. 简化开发模型——使得开发人员的精力集中在业务逻辑之上
框架的分类
A.设计的思路
白盒框架:使用时,需要了解其内部结构(extends);入侵性框架
黑盒框架:不需了解其代码细节,最多实现其接口;非入侵性框架
B.功能、作用
Web:Strusts1.x, WebWork, Strusts2.x(发展1.x和webwork), JSF(抗衡.net), Tapestry,
Shale, ZK, Echo, (根本全是Servlet规范) ……
Business:Spring, Seam
Persistence(持久层):Hibernate, Toplink, OpenOJB, ……
评价框架的优劣?
A.设计理念 先进?
B.编程模型 简单?
C.是否拥抱规范、标准?
D.社区是否庞大?第三方的支持程度?


程序设计思路
可维护性:预见需求(预见多年后的事)
可重用:
代码可重用(最低级别):粒度:方法(常用代码块),类,包,组件(类库)
设计的可重用:框架(半成品,如Hibernate);产品(开发软件);算法、设计模式
分析的可重用(最高级别,见不到代码):文档、规范、标准(ISO:CMM,CMMI)
可扩展性:

*****************************************************

二、Struts框架 (技术概览)
1.Struts简介
Apache
OpenSource
官方网站:http://jakarta.apache.org

MVC
Servlet, JSP, 资源文件, 定制标签库

Struts框架的位置


2.Struts快速上手
需求描述:
系统的登录

开发步骤
1) 创建项目、搭建环境
下载Struts开发包
把%STRUTS_HOME%/lib/*.jar拷贝到WEB-INF/lib
把%STRUTS_HOME%/contrib/struts-el/lib/*.jar拷贝到WEB-INF/lib
把%STRUTS_HOME%/lib/*.tld拷贝到WEB-INF(新版本无需这么做)
将%STRUTS_HOME%/contrib/struts-el/lib/*.tld 拷贝到WEB-INF(新版本无需这么做)
2) 配置WEB-INF/web.xml文件

<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>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

3) 在WEB-INF创建struts-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
<form-beans />
<global-exceptions />
<global-forwards />
<action-mappings />
<message-resources parameter="com.yourcompany.struts.ApplicationResources" />
</struts-config>

4) 提供login.jsp
引入struts标签库
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

<html:form action="/login">
<table>
<tr>
<td>用户名:</td>
<td><html:text property="username"></html:text></td>
</tr>
<tr>
<td>密 码:</td>
<td><html:password property="password"></html:password></td>
</tr>
<tr>
<td colspan=2 align=center>
<html:submit value="登录"></html:submit>
</td>
</tr>
</table>
</html:form>

5) 提供Form Bean
com.form.LoginForm
public class LoginForm extends ActionForm {

private String username;
private String password;

//getter, setter
}

配置文件更新:
<form-beans>
<form-bean name="loginForm" type="com.form.LoginForm"></form-bean>
</form-beans>

6) 提供action:LoginAction extends Action
public class LoginAction extends Action {

@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LoginForm loginForm = (LoginForm)form;
String username = loginForm.getUsername();
String password = loginForm.getPassword();

boolean isLogin = false;
if("maxwell".equals(username) && "123".equals(password)) {
isLogin = true;
}

if(isLogin) {
return mapping.findForward("success");
} else {
return mapping.findForward("error");
}
}

}

配置文件更新:
<action-mappings>
<action path="/login" type="com.action.LoginAction" name="loginForm">
<forward name="success" path="/success.jsp"></forward>
<forward name="error" path="/error.jsp"></forward>
</action>
</action-mappings>


3.Struts技术详解
1) struts的MVC模型 (Page229)
2) 主要组件详解
1)ActionServlet
继承HttpServlet类,需要在web.xml中配置
<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>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

2)Action
开发人员必须继承这个Action类,供ActionServlet所驱动。
职责:调用业务逻辑方法
将控制权返回给ActionServlet并且提供相关的路由信息
public class LoginAction extends Action {
......
}
步骤:
(1) 继承Action类。
(2) 覆盖 execute(...)方法。
(3) 返回ActionForward对象 (提供决策信息给ActionServlet选择适当的视图响应用户) 。
(4) 在struts-config.xml中配置

<action-mappings>
<action input="/index.jsp" :ActionForm验证失败的跳转页面
name="aForm" :与Action对应的FormBean对象
path="/myAction" :请求URI(/myAction.do)
scope="session" :FormBean作用域范围
type="action.LoginAction" :自定义的Action类
validate="true" :FormBean是否调用validate(...)方法
>
<forward name="success" path="/success.jsp" /> :成功跳转的页面
</action>
......
</action-mappings>
注:scope的值可以是request和session,默认是session

3)ActionForm:封装HTTP请求中的数据
将用户提交的数据自动填充(在相应的action的execute方法被调用之前)到form的属性中
无需手工调用request.getParameter(…)
开发人员必须继承这个ActionForm类
public class LoginForm extends ActionForm {
......
}
3) 处理流程(程序中的关系)


****************************************************************************
三、使用IDE工具生成struts项目


Day2:
1 视图选择
2 国际化
3 Struts中的异常处理
4 动态表单
5.标签库
*************************************************************************

1 视图选择
局部转发与全局转发(优先级:局部转发的优先级比全局转发的优先级高)
1) 局部转发:只对某个Action可见
<action ...>
<forward name="success" path="/success.jsp" />
</action>

2) 全局转发:对所有的Action可见(共享)
<global-forwards>
<forward name="success" path="/globalsuccessful.jsp"></forward>
</global-forwards>


例子:
把登录例子中的成功跳转设置为全局转发。


2 I18N
I18N解决办法
创建多个资源文件,根据用户设置选择不同资源文件
ApplicationResources.properties
ApplicationResources_en.properties
ApplicationResources_zh.properties


资源文件:
用于映射页面中的静态信息、按钮标签、错误信息等,
通过一个属性文件(.properties) 把所有页面的静态信息集中在一起,便于修改。

例子:
编写资源文件的步骤:
1) 编辑资源文件

login_en.properties
login.title=Login Page
login.success=Congratuation! You successfully login our System!
login.username=User Name
login.password=Password

添加对中文的支持txt:
login.title=登录页面
login.success=恭喜你!你已经成功登录我们的系统了!
login.username=用户名
login.password=密码
login.submit=登录


转换本地编码为Unicode:
native2ascii login.txt login_zh.properties ----->生成login_zh.properties文件
login.title=\u767b\u5f55\u9875\u9762
login.success=\u606d\u559c\u4f60\uff01\u4f60\u5df2\u7ecf\u6210\u529f\u767b\u5f55\u6211\u4eec\u7684\u7cfb\u7edf\u4e86\uff01
login.username=\u7528\u6237\u540d
login.password=\u5bc6\u7801
login.submit=\u767b\u5f55


2)在struts-config.xml文件中配置资源文件<message-resources parameter="login" />

3)在JSP文件中使用<bean:message key="login.title"/>标签输出资源文件中的值

4)演示效果:
修改浏览器的设置
英文界面少写了"login.submit";则是找出中文的


3 Struts中的异常处理

java class: try/catch/finally/throws/throw/custom Exception class
jsp: page指令 + web.xml配置<error-page>
struts: try/catch/finally/throws/throw/custom Exception class

声明方式(*)------->struts-config.xml
定制异常处理器(*)

ActionErrors(或ActionMessages):异常的集合类
ActionMessage:具体异常类
关系图


方法一:
在actionform的validate方法中处理(很少使用,一般用验证框架实现用户输入合法性验证)

(1)重写action form的validate方法
@Override
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if(username == null || username.equals("") || username.length() > 50) {
ActionMessage msg = new ActionMessage("error.username");
errors.add("errorusername", msg);
}
return errors;
}

login_en.properties的内容
error.username=Please input the correct user name!
login_zh
error.username=请输入正确的用户名信息!
error.username=\u8bf7\u8f93\u5165\u6b63\u786e\u7684\u7528\u6237\u540d\u53ca\u5bc6\u7801\uff01

(2)配置struts-config.xml文件
在action标记内添加一个input属性和validate属性
其中,
input属性的值-----表示发生错误后跳转到的页面
validate属性的值-----表示ActionServlet是否去执行ActionForm的validate(...)方法,并且这个属性默认值是true
<action-mappings>
<action name="loginForm"
path="/login"
type="com.action.LoginAction"
input="/login.jsp"
validate="true">
<forward name="fail" path="/fail.jsp"></forward>
</action>
</action-mappings>


(3)在login.jsp页面中加入<html:errors/>输出错误。


方法二:
在action的execute方法中处理(极少使用,知道这种方法就可以了)
(1)在action的execute方法中写错误处理的代码(和action form里valdiate方法的代码基本一致)


例如:
对于登录用户例子----把narci的都列为黑名单。
Action:
ActionMessages errors = new ActionMessages();
if("narci".equals(loginform.getUsername())) {
System.out.println("narci");
ActionMessage msg = new ActionMessage("error.user.blacklist");
errors.add("blacklist", msg);
this.saveErrors(request, errors);
return mapping.findForward("current");
}

(2)
//比在form的validate方法多出的一步
saveErrors(request, errors);
return mapping.findForward("current");

并且在struts-config.xml中配置
<forward name="current" path="/login.jsp"></forward>

login_en.properties加入内容
error.user.blacklist=this user in blacklist!
login_zh
error.user.blacklist=该用户已被列入黑名单!
正式的: error.user.blacklist=\u8be5\u7528\u6237\u5df2\u88ab\u5217\u5165\u9ed1\u540d\u5355\uff01

(3)
<html:errors/>---->用于页面中显示异常信息(通过资源文件映射)


方法三:
通过抛出异常处理错误(推荐使用:处理业务逻辑方面出现的错误)
(1)在action的方法中抛出异常
(2)在struts-config.xml声明该异常的处理方法(通过exception标记) 局部异常
<action-mappings>
<action name="loginForm"
path="/login"
type="com.action.LoginAction"
input="/login.jsp"
validate="true">
<exception key="errors.noauthorization"
type="com.exception.NoAuthorizationException"
path="/noauthorization.jsp">
</exception>
<forward name="fail" path="/fail.jsp"></forward>
<forward name="current" path="/login.jsp"></forward>
</action>
</action-mappings>

key="errors.noauthorization" 异常提示信息仍然通过资源文件作映射
path="/noauthorization.jsp" 出现异常时的处理页面
type="exception.NoAuthorizationException" Action处理业务过程中有可能出现的异常类型

资源文件加入:
errors.noauthorization=no authorization
errors.noauthorization=当前用户没有授权!


全局异常(对所有的action共享的,所以优先级应该比较低)
<global-exceptions>
<exception key="errors.global" type="java.lang.Exception" path="/error.jsp"></exception>
</global-exceptions>
资源文件加入:
errors.global=System Error! Please contact our administrators!
errors.global=系统错误!请联系管理员!


在LoginAction中加入
if("admin".equals(loginform.getUsername())
&& "".equals(loginform.getPassword())) {
throw new Exception();
}


4 动态表单
可以减少ActionForm的数量,完成对html form属性的动态映射,更便于应用维护。
实现动态表单功能:通过struts-config.xml配置
<form-beans >
<form-bean name="dynForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="name" type="java.lang.String"></form-property>
<form-property name="age" type="java.lang.String"></form-property>
<form-property name="city" type="java.lang.String"></form-property>
<form-property name="gender" type="java.lang.String"></form-property>
</form-bean>
</form-beans>

<action-mappings >
<action name="dynForm"
path="/enroll"
scope="request"
type="com.tarena.struts.action.EnrollAction" >
<forward name="success" path="/success.jsp" />
<forward name="fail" path="/fail.jsp" />
</action>
</action-mappings>
<message-resources parameter="com.tarena.struts.ApplicationResources" />

Struts中表单使用技巧:
1)同类型或结构相近的html form通过一个ActionForm类型映射
2)在都能满足需要的前提下,尽量使用动态表单
3)ActionForm的作用域范围应尽量小,对于存放在session中的ActionForm,当不再使用时应销毁
4)ActionForm主要用于控制器与视图之间传数据,不应包含任何业务逻辑


Struts 标签
************************************************************************************************

一、Struts标签库概述

1.回顾已经学了JSTL标签库
标签库的作用:
1.使得(jsp)页面开发人员不再依赖Java(EL表达式的作用也是如此)
2.功能封装:可重用

2.Struts的五类标签库
Bean Tags :用来创建bean、访问bean
HTML Tags :用来创建 html 页面的动态元素,对html进行了封装;
Logic Tags:逻辑判断、集合迭代和流程控制。
Nested Tags:该标签库建立在前三个标签库的基础上,具有前三个标签库的所有功能,只是允许标签间的嵌套。
Tiles Tags :该标签库包含的标签可以用来创建tiles样式的页面;布局专用。

3.重点学习前3类标签库


二、Bean标签
可以看成 <jsp:useBean> 的增强版,
它可以定义bean :获取某些数据(cookie,请求参数,请求头),将之定义成一个脚本变量,并同时置于某个作用域(缺省pagaContext) 中;

bean标签的公共属性:
id - 定义一个变量
name - 引用一个存在的bean或对象的名字
property - 被引用的bean的属性
scope - 放置或搜索bean的范围,若没有制定,则依次 page--request---session--application

1.<bean:define/>
作用: 把一个bean 或其属性, 定义成一个变量

* 通过<bean:define/>定义的变量可以通过JSP脚本、EL以及Struts本身的<bean:write/>标记访问。
Example1:
1) 定义一个Java bean:student,并且对其属性进行赋值
2) 通过<bean:define/>定义stuName、stuAge、stuGender三个变量,将student这个对象的属性值赋值给这些变量
<bean:define id="stuName" name="student" property="name"></bean:define>
<bean:define id="stuAge" name="student" property="age"></bean:define>
<bean:define id="stuGender" name="student" property="gender"></bean:define>
3) 输出
<%=stuName%> //jsp形式
${stuAge } //EL表达式
<bean:write name="stuGender"/> //Struts方式


* 如果JavaBean的属性是List等类型,可以指定type属性
Example2:
1)在Java Bean中添加List属性,并提供get/set方法。
private List songs;
public List getSongs() {
List list = new ArrayList();
list.add("我爱北京");
list.add("我和你");
list.add("我不做大哥好多年");
return list;
}
2)<bean:define id="songs" name="student" property="songs"></bean:define>
3)输出
${mySongs[0] }

* 定义新变量,例如:
<bean:define id="bookName" value="Effective Java"></bean:define>

2.<bean:write/>
作用: 输出 bean 或bean属性;
等价于:
${} 或者 <%= %>

3.<bean:message/>
作用:读取属性静态文本内容,支持国际化(i18n)
Example:
1)确认在类路径上含有
com/ApplicationResources.properties
配置路径: <message-resources parameter="com.ApplicationResources" />
2)在文件中加入key,value对
page.title=\u9875\u9762\u6807\u9898
3)提供message.jsp
使用<bean:message key="page.title"/>

4.<bean:size/>
作用:获得一个集合或者数组的大小
Example:
1)定义Java Bean : student
2)读取student这个java bean的songs的size
<jsp:useBean id="student" class="com.bean.Student"></jsp:useBean>
<bean:size id="songsize" name="student" property="songs"/>
3)输出songsize值

Exapmple:定义一个列表,输出其size,要求使用<bean:size/>获取该值
1)<%定义一个List,并初始化%>
2)使用 <bean:size id="listsize1" collection="<%=list %>"/> 获取值
注意:如果使用${},必须要把list放置到范围对象中
3)输出

5.<bean:cookie/>
作用:读取请求头中cookie的信息
* <bean:cookie id="cid" name="customid">
获得指定的名为 "customid" 的coockie,并将其赋值给脚本变量 cid
* 若找不到id为costCookie这个cookie,所以系统创建一个cookie,并将它的值设置为"uu11"
<bean:cookie id="cost" name="costCookie" value="uu11"/>
输出: <bean:write name="cost" property="value"/>

6.<bean:header/>
作用:获取请求头的属性信息
<bean:header id="userAgent" name="User-Agent"/>
//打印出:Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.8.0.7) Gecko/20061011....未完
<bean:header id="host" name="host"/>
//打印出:127.0.0.1:8080
<bean:header id="dummy" name="UNKNOWN-HEAD" value="no defined Header"/>
// no defined Header

7.<bean:include/>
作用:对指定url(由forward、href或page确定)处的资源做一个请求,
将响应数据作为一个String类型的bean绑定到page作用域,
同时创建一个scripting变量。我们可以通过id值访问它们。

Example:
1)在根目录下定义一个文件:include.txt
2)获取文件的内容数据,并赋于words
<bean:include id="words" page="/include.txt"/>
3)输出内容

8.<bean:resource/>
作用:获取指定的资源,以String或者InputStream的方式来读取,其中input属性是决定了对应的方式。
默认(false)是以字符串的方式来读取。
例如:
<bean:resource id="r1" name="/include.txt" /> //打印文件原内容: Hello World!
<bean:resource id="r2" name="/include.txt" input="true" />
//打印出:java.io.ByteArrayInputStream@735f45 input="false"时同样这打印

9.<bean:parameter/>
作用:取出url中queryString中指定参数名称的值
例子:
<bean:parameter id="target" name="action" />
只会读取第一个名字为"action"的参数

<bean:parameter id="ps" name="hobby" multiple="true" />
把url中queryString中名字叫hobby的所有值赋值给变量ps,所以ps应该是一个数组

10.<bean:page/>
作用:把pageContext中的特定的隐含对象(application, request, response, config, session) 取出来,
绑定到某个id中,本页的其他地方就可以使用id来操纵这些隐含对象了。

Example:
<bean:page id="res" property="response" />
<bean:page id="sess" property="session" />

<bean:write name="res" property="contentType"/>
<bean:write name="res" property="characterEncoding"/>
<bean:write name="sess" property="id"/>
<bean:write name="sess" property="maxInactiveInterval"/>


三、HTML标签库
使用taglib指令引入标签库
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

通常是配合bean标签一起使用,是struts中最常用的标签之一。

1.<html:form/>
作用:对html的form表单进行简单的封装,满足struts中表单请求的处理
<html:form action="/login">

</html:form>
如果你有上述一个标签,那么你的Struts配置文件的元素中必须有一个如下内容:
<action-mappings>
<action input="/login.jsp" name="loginForm" path="/login"
type="action.LoginAction" validate="true">
<forward name="success" path="/success.jsp" />
<forward name="error" path="/error.jsp" />
</action>
</action-mappings>
这就是说一个form标签是和form bean相关联的。
任何包含在<form>中用来接收用户输入的标签
(<text>、<password>、<hidden>、<textarea>、<radio>、<checkbox>、<select>)
必须在相关的form bean中有一个指定的属性值。<form>标签中method属性的缺省值是POST

2.<html:link>
作用:超文本连接
属性:page,指定一个页面的路径,必须以/开始。

Example:
当前页面跳转到/bean/parameter.jsp
需要提供参数:
<bean:define id="beanName" value="beanValue"></bean:define>
<html:link page="/bean/parameter.jsp"
paramId="action" paramName="beanName">
<html:param name="hobby" value="sports"></html:param>
跳转到bean:parameter.jsp
</html:link>

这等价于:
http://localhost:8080/工程名/bean/parameter.jsp?hobby=sports&action=beanValue
<a href="/工程名/bean/parameter.jsp?hobby=sports&action=beanValue">跳转到parameter.jsp</a>


3.<html:errors/>
作用:输出错误信息
异常处理会介绍

Example:
1)在资源文件中定义
property1.error1=Property1 Error1
property2.error1=Property2 Error1
property2.error2=Property2 Error2
property2.error3=Property2 Error3
property3.error1=Property3 Error1
property3.error2=Property3 Error2

globalError=Global Error

property1.message1=Property1 Message1
property2.message1=Property2 Message1
property2.message2=Property2 Message2
property2.message3=Property2 Message3
property3.message1=Property3 Message1
property3.message2=Property3 Message2

globalMessage=Global Message

messages.header=<table border=1><tr><td>错误变量</td><td>错误信息</td></tr>
messages.footer=</table>
2)添加jsp文件并编辑
<%@ page import="org.apache.struts.action.*"%>
<%@page import="org.apache.struts.Globals"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

<%
ActionMessages errors = new ActionMessages();
errors.add("property1", new ActionMessage("property1.error1"));
errors.add("property2", new ActionMessage("property2.error1"));
errors.add("property2", new ActionMessage("property2.error2"));
errors.add("property2", new ActionMessage("property2.error3"));
errors.add("property3", new ActionMessage("property3.error1"));
errors.add("property3", new ActionMessage("property3.error2"));
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("globalError"));
request.setAttribute(Globals.ERROR_KEY, errors);

ActionMessages messages = new ActionMessages();
messages.add("property1", new ActionMessage("property1.message1"));
messages.add("property2", new ActionMessage("property2.message1"));
messages.add("property2", new ActionMessage("property2.message2"));
messages.add("property2", new ActionMessage("property2.message3"));
messages.add("property3", new ActionMessage("property3.message1"));
messages.add("property3", new ActionMessage("property3.message2"));
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("globalMessage"));
request.setAttribute(Globals.MESSAGE_KEY, messages);
%>

3)输出相应的(出错) 信息:
<table border=1>
<tr>
<td>错误变量</td>
<td>错误信息</td>
</tr>
<tr>
<td>property1</td>
<td><html:errors property="property1" /></td>
</tr>
<tr>
<td>property2</td>
<td><html:errors property="property2" /></td>
</tr>
<tr>
<td>property3</td>
<td><html:errors property="property3" /></td>
</tr>
<tr>
<td>org.apache.struts.action.GLOBAL_MESSAGE</td>
<td><html:errors
property="org.apache.struts.action.GLOBAL_MESSAGE" /></td>
</tr>
<tr>
<td>All</td>
<td><html:errors /></td>
</tr>
</table>

<html:messages message="true" id="msg"
header="messages.header" footer="messages.footer">
<tr>
<td></td>
<td><bean:write name="msg" /></td>

</tr>
</html:messages>
4.<html:image>与<html:img>
作用:在页面中产生图像的输出
最重要的属性page:图象文件的路径,前面必须带有一个斜线。
其它属性:height、width(只有 img 可以设置长和宽)、alt(不知何用)。

Example:
<html:image page="/f4icmu.jpg" alt="软件工程之通俗版"></html:image>
<html:img page="/f4icmu.jpg"/>
等价于:
<input type="image" name="" src="/工程名/f4icmu.jpg" alt="软件工程详解">
<img src="/工程名/f4icmu.jpg">


5.<html:checkbox/>
生成一个checkbox。这里的value值可以是true,yes或on。
checkboxForm的属性:
private boolean one = false;
private boolean two = false;
private boolean three = false;

<html:checkbox name="checkboxForm" property="one">One</html:checkbox>
<html:checkbox name="checkboxForm" property="two">Two</html:checkbox>
<html:checkbox name="checkboxForm" property="three">Three</html:checkbox>
如果选中后被提交则相应的属性的值为true。

6.<html:radio/>
生成一个radio。主要的用法有两种。
下面的代码示例了html:radio标签的一般用法,
如果被提交则选中的radio的value值将被提交到radioForm中的id中。
<html:radio name="radioForm" property="id" value="00001"> One </html:radio>
<html:radio name="radioForm" property="id" value="00002"> Two </html:radio>

7.<html:select>标签和<html:option>标签
作用:对html中的下拉选择标签与选项标签做了封装

单选下拉
Example1:
<html:select property="singleSelect" size="3">
<html:option value="Single 0">Single 0</html:option>
<html:option value="Single 1">Single 1</html:option>
<html:option value="Single 2">Single 2</html:option>
</html:select>

Example2:性别
1)提供label和value的数组
<% String[] label = { "男", "女", "未知" };
String[] value = { "male", "female", "unknown" };
pageContext.setAttribute("label", label);
pageContext.setAttribute("value", value);
%>
2)标签使用:
<html:select property="sex" size="1">
<html:options labelName="label" name="value" />
</html:select>

Example3:兴趣爱好多选
1)提供列表
<% List options = new ArrayList();
options.add(new LabelValueBean("电脑游戏", "PCGame"));
options.add(new LabelValueBean("看电视", "TV"));
options.add(new LabelValueBean("阅读", "Reading"));
options.add(new LabelValueBean("唱歌", "Singing"));
pageContext.setAttribute("opt", options);
%>

其中,
public class LabelValueBean {
private String label;
private String value;
public LabelValueBean(String label, String value){}
}

2)提供多选标签
<html:select property="favors" multiple="true">
<html:options collection="opt" property="value"
labelProperty="label" />
</html:select>

Example4:联系方式多选
1)提供多选列表
<% List myPhones=new ArrayList();
myPhones.add(new LabelValueBean("小灵通","33213322"));
myPhones.add(new LabelValueBean("固话","80512010"));
myPhones.add(new LabelValueBean("手机","13711221113"));
pageContext.setAttribute("myPhones",myPhones);
%>
2)标签的使用
<html:select property="phones" multiple="true">
<html:optionsCollection name="myPhones"/>
</html:select>

8.<html:submit>标签
<html:submit value="Submit" />


9.<hmtl:text>标签
文本输入框
<html:text property="username" />

10.<html:password>标签
<html:password property="password"/>

11.<html:cancel/>取消标签


四、Logic标记 :
该标签库包含的标签可以用来进行逻辑判断、集合迭代和流程控制。
1.<logic:iterate/>
作用:<logic:iterate/>标签用来迭代集合
Example:
<%
List stuList=new ArrayList();
Student stu=new Student();
stu.setName("Alice");
...
stuList.add(stu);
request.setAttribute("stuList",stuList);
%>
<logic:iterate id="stu" name="stuList">
<tr>
<td>${stu.id }</td>
<td>${stu.name }</td>
<td>${stu.sex }</td>
<td>${stu.age }</td>
<td>${stu.desc }</td>
</tr>
</logic:iterate>

(2) logic:empty
用来判断是否为空的。如果为空,该标签体中嵌入的内容就会被处理。该标签用于以下情况:
当Java对象为null时
当String对象为""时
当java.util.Collection对象中的isEmpty()返回true时
当java.util.Map对象中的isEmpty()返回true时
下面的代码示例了logic:empty标签判断集合persons是否为空:

<logic:empty name="stu" property = "books">

<div>集合books为空!</div> </logic:empty>
logic:notEmpty标签的应用正好和logic:empty标签相反。


(3) logic:equal
这里要介绍的不只是logic:equal(=)标签,而是要介绍一类标签,这类标签完成比较运算,
包括:
logic:equal(=)
logic:notEqual(!=)
logic:greaterEqual(>=)
logic:lessEqual(<=)
logic:graterThan(>)
logic:lessThan(<)

Example:
<logic:equal name="stu" property="name" value="Alice">
I am Alice.
</logic:equal>

<bean:define id="count" value="168"/>
<logic:equal name="count" value="168">
Good lucky number.
</logic:equal>


Day3:
1 定制Action
2 禁止表单重复提交
3 定制Controller
4 验证框架
************************************************************************

1 定制Action

1) DispatchAction:可以将相关的一组操作放在一个Action类中(同一模块功能)
特点(优点) :
1)一个 Action可以对应多个业务方法(CRUD),而无需通过增加隐藏域的方式来处理。
2)避免Action类数量随业务复杂度而膨胀,可以共享公共的业务逻辑代码。
3)无需重写execute方法
4)DispatchAction类本身已经重写了Action类的execute方法。

实现DispatchAction的步骤:
1) 继承DispatchAction
SuperGileAction extends DispatchAction
2) 定义自己的处理方法,不要覆盖execute()方法

3) struts-config.xml中action元素增加parameter属性
<action path="/super" name="superForm" parameter="method"
type="com.tarena.action.SuperGileAction">
<forward name="success" path="/success.jsp"></forward>
</action>
用户请求URL应有如下格式:
a)Get方法
http://localhost:8080/super/SuperGileAction.do?method=<method_name>
b) Post方法
在表单中添加参数来完成

2) LookupDispatchAction:
特点:它是DispatchAction的子类,所以具备DispatchAction的所有特性,
支持一个表单对应多个业务方法。

实现LookupDispatchAction的步骤:
1) 继承LookupDispatchAction
2) 定义自己的处理方法,覆盖getKeyMethodMap()方法,不要覆盖execute()方法
getKeyMethodMap()完成资源文件中Key与Action中方法映射

@Override
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("submit.modify", "modify");
map.put("submit.add", "register");
return map;
}

public ActionForward modify(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response){
...
}
public ActionForward register(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response){
...
}

3)struts-config.xml中为Action增加parameter属性
<action path="/lookupAction"
name="superForm"
type="com.tarena.action.SuperGirlLookupAction"
parameter="method">
<forward name="success" path="/success.jsp"></forward>
</action>

4) 提交页面按钮有如下格式
html:submit的property属性值与Action中的parameter属性值映射
<html:submit property="method">
<bean:message key="submit.add"/>
</html:submit>

<html:submit property="method">
<bean:message key="submit.modify"/>
</html:submit>

3) Action编程技巧(建议) :
1)尽量避免使用实例变量或静态变量
(servlet是单实例多线程,所以要自己维护成员变量的同步问题)
2)使用自己的BaseAction完成Action的公共操作,其余Action可从BaseAction派生
3)Action不要代替Model工作
在设计多层架构时,使用Business Delegate可降低层与层之间的耦合度


2 禁止表单重复提交
1)客户端实现(JavaScript)
2)JSP实现(脚本)
图解
实现代码
3)Struts实现
(1)Struts内置实现,无需额外配置
(2)需要在前一个action的方法中调用saveToken()方法
saveToken(request);
(3)在后一个执行业务逻辑的方法中使用isTokenValid(request)判断表单是否被重复提交
if (isTokenValid(request)) {
// invoke business method
//......

// reset transaction token after transaction success!
this.resetToken(request);
return mapping.findForward("success");
} else {
System.out.println("duplicate token");
return mapping.findForward("error");
}

3 定制Controller(可选)
扩展控制器功能
ActionServlet与RequestProcessor的作用
1)继承RequestProcessor
2)通过processPreprocess()增加定制功能
//自定义控制器需要派生自RequestProcessor
package com.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.RequestProcessor;
public class SecurityRequestProcessor extends RequestProcessor {
@Override
protected boolean processPreprocess(HttpServletRequest request,
HttpServletResponse response) {
System.out.println("start controller ...");
request.getSession().getServletContext().log("URL="+request.getRequestURL());//写日志
String ip = request.getRemoteAddr();
if (ip.equals("127.0.0.1")) {
System.out.println("valid client: 127.0.0.1");
return true; //只允许此IP登录
}
int lastPoint = ip.lastIndexOf(".");
String fourth = ip.substring(lastPoint + 1);
int fourthInt = Integer.parseInt(fourth);
if (ip.startsWith("192.168.1.") && fourthInt > 50 && fourthInt < 60) {
System.out.println("invalid client: 192.168.1.[50~60]");
return false; //限制黑名单IP的登录
}
return false;
}}
3)struts-config.xml中配置 <controller .../> (一般只有一个controller)
写在<action-mappings /> 之后;<message-resources .../> 之前
<controller processorClass="com.controller.SecurityRequestProcessor"/>

补充说明:
通常的一个struts-config.xml只能配置一个controller
一般地,在开发时通过定制controller来增强系统功能,例如:日志、安全限制等。
但在实际的应用中比较少使用。
举例:
public class SecurityRequestProcessor extends RequestProcessor {
public boolean processPreprocess(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response){
String ip=request.getRemoteAddr();
if(ip.equals("127.0.0.1"))
return true;

int lastPoint = ip.lastIndexOf(".");
String fourth=ip.substring(lastPoint+1);
int fourthInt=Integer.parseInt(fourth);
if(ip.startsWith("192.168.1.")&&fourthInt>50&&fourthInt<60){
return true;
}
return false;
}
}

4 验证(校验) 框架
(1)有三种数据验证方式:
a.在ActionForm.validate() 当中进行
b.在Action.execute()方法中进行(这两种参看day2的异常处理,前两种)
c.引入validator框架(apache.jakata)
(2)声明式的数据验证(为什么能使用声明式?)--配置
原因:对于数据的验证有模式

(3)validator框架已经定义了一部分通用的验证规则和逻辑
开发者只需对特定数据指定具体的验证规则(业务)--使用
包含在validation.xml

使用验证框架的步骤:
1)在struts-config.xml配置校验插件(validate plugin)
放在<message-resources ../> 之后
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>

注释:
1.验证插件:
1) validator-rules.xml :定义验证规则
规则名(如:required, maxlength.....)
验证方法
验证失败时出错提示(放到上下文中)
2)validation.xml
使用规则:对指定的表单属性进行校验
2.基本的结构:
1)验证逻辑:
validateXxx()方法
2)在validator-rule.xml中定义的都是校验规则
3)在validation.xml中(声明式验证)
a.引入了struts-config.xml的表单名字(form-bean的名字)
b.声明域的验证依赖规则
depends = "required,Integer"


2)add validator-rule.xml and validation.xml to /WEB-INF/
copy validator-rule.xml from struts framework
edit validation.xml
注意版本的一致

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

<form-validation>
<formset>
<form name="enrollForm">
<field property="name" depends="required">
<arg key="register.name"/>
</field>
<field property="age" depends="required, integer">
<arg key="register.age"/>
</field>
<field property="city" depends="required">
<arg key="register.city"/>
</field>
<field property="gender" depends="required">
<arg key="register.gender"/>
</field>
<field property="email" depends="required,email">
<arg key="register.email"/>
</field>
<field property="birthday" depends="required, date">
<arg key="register.birthday"/>
<var>
<var-name>datePattern</var-name>
<var-value>yyyy-MM-dd</var-value>
</var>
</field>
</form>
</formset>
</form-validation>

注意:如果是使用1.3.x以上的版本,只需要引入:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/org/apache/struts/validator/validator-rules.xml, /WEB-INF/validation.xml"/>
</plug-in>

validation.xml为:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">

<form-validation>
<formset>
<form name="enrollForm">
<field property="name" depends="required">
<arg key="register.name"/>
</field>
<field property="age" depends="required, integer">
<arg key="register.age"/>
</field>
<field property="city" depends="required">
<arg key="register.city"/>
</field>
<field property="gender" depends="required">
<arg key="register.gender"/>
</field>
<field property="email" depends="required,email">
<arg key="register.email"/>
</field>
<field property="birthday" depends="required, date">
<arg key="register.birthday"/>
<var>
<var-name>datePattern</var-name>
<var-value>yyyy-MM-dd</var-value>
</var>
</field>
</form>
</formset>
</form-validation>


3)develop ur ActionForm (服务器端验证需要遵循的规范)
(1) 自定义ActionForm 要继承 ValidatorForm
最好不要重写validate方法!如果重写validate方法,则必须显式调用 return super.validate(...)方法
(2) 动态form要使用org.apache.struts.validator.DynaValidatorForm

4)(服务器端验证需要遵循的规范)
<action ..... validate="true" input="假如出错的页面" >

5)copy validation rules to ApplicationResources.properties


register.title=Super Boy Register Form
register.name=Name:
register.gender=Gender:
register.age=Age:
register.city=City:
register.email=Email:
register.birthday=Birthday:

errors.required={0} is required.
errors.integer={0} must be an integer.
errors.date={0} is not a date.
errors.email={0} is an invalid e-mail address.

6)active javaScript in Jsp page.(采用客户端验证才需要这一步)
<html:javascript formName="enrollForm"/>
<html:form action="/enroll" onsubmit="return validateEnrollForm(this)" method="post">


建议:(1) 客户端能做的验证,一般不要在服务器端验证。
一般输入格式等方面的验证
(2) 客户端实在没有能力进行验证的情况,发到服务器端做验证。


禁止表单重复提交:

1.客户端方案(Java Script)
使用js来实现禁止表单重复提交的方法很多,大体有如下几种:

1)提交时,使提交按钮不可用(disable),或者隐藏按钮,使用进度条
参考实现:


/*
函数名称:disableButtons
函数功能:提交前,将所有表单中的button,reset,submit禁用disabled;
如果是submit按钮,则添加与之相同隐藏文本框hidden对象,让提交的信息无一漏网
*/
function disableBtns()
{
for(k=0;k<document.all.length;k++ )
{
//当前节点对象
var obj = document.all(k)
if( obj.type=='button' || obj.type=='submit' || obj.type=='reset')
{
obj.disabled = true
if (obj.type=='submit')
{
//添加隐藏节点
var oNewNode = document.createElement("input");
oNewNode.type = "hidden"
oNewNode.name = obj.name
oNewNode.value = obj.value
obj.insertAdjacentElement("afterEnd",oNewNode);
}
}
}
}


/*
函数名称:disButtons2
函数功能:提交前,将所有表单中的button,reset,submit禁用disabled;
如果是submit按钮,则添加与之相同隐藏文本框hidden对象,让提交的信息无一漏网

函数说明:与上面的函数功能一样,但适用浏览器范围更广,推荐使用此函数。
*/
function disableBtns()
{
for(k=0;k<document.forms.length;k++ )
{
//获取当前表单
var frm = document.forms[k]
for(i=0;i<frm.length;i++)
{
var obj = frm.elements[i]
if ( obj.type=='button' || obj.type=='submit' || obj.type=='reset' )
{
obj.disabled = true
if (obj.type=='submit')
{
var oNewNode = document.createElement("input");
oNewNode.type = "hidden"
oNewNode.name = obj.name
oNewNode.value = obj.value
//frm.insertAdjacentElement("beforeEnd",oNewNode);
obj.insertAdjacentElement("afterEnd",oNewNode);
}
}
}
}
}


/*
函数名称:hiddenForm
函数功能:提交时让表单自动隐藏,而不影响数据的提交
*/
function hideForm(form)
{
//waitStr 提交过程中出现的提示,可以自行设置
var waiting = "<center><img src='progress.jpg'>数据正在提交中,请等候</center>";
form.innerHTML = "<div style='display:none;'>"+form.innerHTML+"</div>"+waiting;
}


2)使用标识来实现控制客户端多次点击

<script type="text/javascript">
//控制标志
var submitted = false;
function checkSubmit() {
if(submitted == true) {
alert("submitted == true");
return false;
}
submitted = true;
return true;
}

//控制页面双击行为
document.ondblclick = function docOnDblClick() {
window.event.returnValue = false;
}

//控制页面单击行为
document.onclick = function docOnClick() {
if(submitted) {
window.event.returnValue = false;
}
}
</script>


<html:form action="/logon" method="post" onsubmit="return checkSubmit();">
<html:text property="name"></html:text>
<html:submit value="login">
</html:submit>
</html:form>


2.服务器端方案
原理:使用transaction token
1)jsp版


Day4:
一、 文件上传
步骤:
1)定义表单
<html:form action="/fileupload" enctype="multipart/form-data">
<table>
<tr>
<td><b>请选择上传的文件:</b></td>
<td><html:file property="file"></html:file></td>
</tr>
<tr></tr>
<tr>
<td colspan=2 align=center>
<html:submit>上传</html:submit>
</td>
</tr>
</table>
</html:form>
2)配置stuts-config.xml
*定义Form
*定制Action

a)form
public class FileUploadForm extends ActionForm {
private FormFile file;
public FormFile getFile() { return file; }
public void setFile(FormFile file) { this.file = file; }
}

b)action
//处理文件
FormFile file = fileUploadForm.getFile();
InputStream is = file.getInputStream();
OutputStream os = new FileOutputStream(path + filename);
输出文件


二、Struts Tiles----强大的页面模板与页面布局技术

1.作用:Tiles框架提供模板机制,完成页面布局和内容展示逻辑的解耦
-------分离变与不变的元素:布局是不变的,而内容是变化的

2.如何使用tiles框架
步骤:
1) 在struts-config.xml配置tiles插件
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config"
value="/WEB-INF/tiles-define.xml"/>
</plug-in>

2) 定义tiles:tiles-define.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.3//EN"
"http://struts.apache.org/dtds/tiles-config_1_3.dtd">

<tiles-definitions>
<definition name="definition1" page="/layout/baselayout.jsp">
<put name="title" value="mainspace"></put>
<put name="header" value="/layout/header.jsp"></put>
<put name="footer" value="/layout/footer.jsp"></put>
<put name="body" value="/layout/body.jsp"></put>
<put name="navigator" value="/layout/navigator.jsp"></put>
</definition>

<definition name="user" extends="definition1">
<put name="title" value="another mainspace"></put>
<put name="body" value="/usermanager/user.jsp"></put>
</definition>
</tiles-definitions>

3) 定义布局以及所有的组成部分
baselayout.jsp
header.jsp
footer.sjp
body.jsp
navigator.jsp


变化的内容定义为:
<tiles:getAsString name="title"/>
<tiles:insert attribute="header">


baselayout.jsp参考代码:
-------------------------------------------------------------------------------------------------------
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>

<html>
<head>
<title><tiles:getAsString name="title"/></title>
</head>

<body>
<table border="0" width="100%" cellspacing="5">
<tr><td colspan=2 align=center>
<tiles:insert attribute="header"></tiles:insert></td></tr>
<tr><td width="15%" valign="top">
<tiles:insert attribute='navigator'></tiles:insert></td>
<td align="left">
<tiles:insert attribute='body'></tiles:insert></td></tr>

<tr><td colspan="2"><hr></td></tr>
<tr><td colspan=2 align=center>
<tiles:insert attribute="footer"></tiles:insert></td></tr>
</table>
</body>
</html>
-------------------------------------------------------------------------------------------------------


4) 在页面中引用 tiles:
<tiles:insert definition="defall"/>
也可以覆盖定义的属性值
<tiles:insert definition="defall">
<tiles:put name="title" value="my page"/>
</tiles:insert>


3.使用tiles-define.xml定义tiles的好处:
1) tiles可重用(被多个页面)
2) tiles的定义可以被"继承"和"覆盖"
3) 使用已定义的definition
AI工程周刊:面向生产环境的可执行技术决策指南 AI技术资讯泛滥时代,真正驱动开发落地的核心不是信息新鲜度,而是可验证性、可操作性与领域适配性。本文聚焦‘工程师晨会级’信息筛选范式,围绕API变更、开源库breaking change、框架隐性升级等高频实操场景,提炼出时效临界点、行动转化率、领域适配度三大判断标准。结合vLLM Kubernetes Operator、AWS Bedrock权限升级、Transformers FlashAttention-2强制启用等真实案例,详解如何将Newsletter转化为命令可执行、环境可验证、决策可闭环的技术雷 阅读详情

相关推荐

Claude Mythos:首个端到端自动化漏洞利用AI模型解析

AI安全模型正从辅助分析工具演进为具备自主攻防闭环能力的智能体。以Claude Mythos为代表的前沿模型,依托大规模代码演化训练、多阶段强化学习与高预算推理机制,首次实现从CVE识别、PoC生成、沙箱验证到RCE落地的全链路自动化。其核心突破在于将传统需人工协同完成的漏洞挖掘、利用开发与防御绕过等环节,封装为可编程、可复现、零人工干预的端到端工作流。该能力已通过SWE-bench Pro、CyberGym及UK AISI企业级攻击模拟等权威基准验证,在真实内核漏洞(如CVE-2026–4747)利用中展

chunchan1381的博客 377

14. Struts2.x note

Struts 2.x初阶 1.MVC原理 2.Struts框架的介绍 3.Struts2.x快速上手 4.Struts2.x框架的分析 ******************************************************************************* 一、MVC原理 1. Model1---> Model2 ---> MVC ...

十年技术一场空! 175

UsageLog电脑使用记录软件

UsageLog电脑使用记录软件

struts2.0和jstl1.1的奇怪问题

javax.servlet.ServletException: Validation error messages from TagLibraryValidator for fmt in /feekman.jspnull: org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0x0) was found in the ...

cyckjp的专栏 163

最新推荐-2026年固态电池+锂电正极+硅基负极等关键技术实践PPT合集(55份).zip

2026年最新固态电池+锂电正极+硅基负极等关键技术实践PPT合集,共55份。供大家查阅。 一、固态电池 1.全固态电池用硅基负极材料研究进展 2.全固态电池硅基负极的开发思考 3.功能型固态电解质设计及界面调控 4.固态电池及关键材料研发与产业化进展 5.固态电池的产业化应用探索 6.固态锂电池开发现状及未来展望 7.固态锂离子电池正极结构设计与材料选择 8.固态锂金属电池设计与应用 9.硫化物全固态电池石墨和硅负极性能调控技术 10.硫化物固态电解质行业应用 11.聚合物基固态电解质与固态电池的关键技术 12.蜂鸟声共振技术-固态电池产业化的革命性创新 13.长安汽车固态电池应用探索 14.高安全性固态电池技术发展趋势 15.高性能硫化物全固态锂电池解决方案 16.高硅体系的膨胀解决方案 二、硅基负极 1.化学气相沉积碳包覆技术在硅基负极材料中的应用 2.新型粘结剂解决 硅基负极膨胀问题 3.氧化亚硅负极材料化学预锂化与界面设计 4.流化床法生产磷酸铁锂及硅负极材料研究 5.石墨烯包覆硅碳负极 6.硅基材料的发展现状及展望 7.硅基负极与固态电解质 8.硅基负极技术与进展 9.硅基负极材料体积膨胀解决策略 10.硅基负极材料及其结构设计 11.硅基负极材料的冶金法制备 12.硅基负极材料的发展与应用 13.硅基负极材料研究进展 14.硅基负极材料:从基础研究到产业应用 15.硅基负极析锂行为及调制研究 16.硅碳负极低成本制造技术报告 17.硅碳负极制备用多孔碳的开发 18.硅碳负极挑战和进展 19.硅碳负极新路线及关键材料制备 20.硅碳负极锂离子电池应力特性研究 21.锂电石墨负极材料工程化技术进步 22.锂离子电池负极材料 23.高容量石墨烯-硅基复合负极材料的研究进展 三、锂电正极 1.基于AI和图论结构化学的锂电池的材料基因探索 2.废旧磷酸铁锂电池梯次及再生利用进展 3.电动汽车大功率充电标准体系与检测认证实践 4.磷酸铁及磷酸铁锂异物防控管理 5.磷酸铁锂正极材料:液相法合成及产业化应用研究 6.磷酸锰铁锂正极材料的研究现状 7.车用动力电池安全标准化工作进展及未来展望 8.锂电层状氧化物正极材料的原子尺度失效机制 9.锂电正极材料工厂异物防控管理图册 10.锂离子电池高熵正极材料成分设计及储锂机制研究 11.高压实磷酸铁锂正极材料生产工艺配方.docx 12.高安全正极材料添加剂提升三元锂电安全性 13.高比能富锂锰基电池关键技术 14.高能量密度锂离子电池正极材料及应用研究 15.高镍单晶三元正极材料研究 16.三元高电压单晶正极材料

Zotero 是学术管理领域非常优秀的软件 它功能成熟、生态稳定,帮助许多科研人员建立了最初的文献归档体系

Zotero 是学术管理领域非常优秀的软件。它功能成熟、生态稳定,帮助许多科研人员建立了最初的文献归档体系。但在当下日常科研与深度使用各类 Agent 时,传统的文献工具链暴露出一些断点:上下文严重分散:论文存储在 Zotero,笔记记在 Obsidian,与模型的推导和分析留在各个网页对话框中。三者数据彼此隔离,当需要 Agent 结合某篇具体论文与历史笔记进行深入推导时,用户必须反复手动复制粘贴。文献格式对模型不友好:人类习惯阅读排版良好的 PDF 文件;但对于模型而言,直接解析双栏排版、跨页表格、复杂数学公式和交叉引用的成本极高,极易产生识别错误与幻觉。结构化 Markdown 与 LaTeX 才是模型容易准确理解的格式。维护成本较高:AI 伴读、全文翻译、笔记同步等高频需求,往往需要安装和调试多个社区插件,配置门槛高且在版本升级时容易出现兼容性问题。批量自动化能力有限:通过 Deep Research 或自动化检索工具发现的大量文献,目前仍需人工在浏览器中逐篇点击保存,难以顺畅衔接批量研究流。Agentero 并非旨在替代 Zotero,而是探索一种人与 Agent 协同处理科研上下文的新方式:人类负责:提出研究问题、进行学术价值判断、深度研读与核心结论推导;Agent 负责:批量检索筛选、元数据抓取、图表与公式提取、引用关系梳理及基础总结。

AT89C52 电子琴定时器初值计算:从 330Hz 到 1967Hz 的 14 音阶精准生成

本文详细介绍了使用AT89C52单片机通过定时器中断精确生成14个标准音阶(从330Hz到1967Hz)的方法,包括数学计算、代码实现及优化技巧。适用于电子琴设计,结合蜂鸣器和数码管等模块,实现精准音阶生成和自动演奏功能。

weixin_33721427的博客 370

基于 .net 8、blazor 、furion 开发的后台管理系统,功能全(完善的用户权限管理、定时任务、附件管理、日志审计、物联网、企业门户等)、技术新

基于 .net 7开发的后台管理系统,系统前后台分离,api 是基于Furion 框架开发,前端是基于ant-design-blazor开发,系统使用技术或框架较新

拆解Web渗透底层逻辑:从溯源发展史到实战核心全维度指南

Web渗透测试是一套标准化、流程化、逻辑化、合规化的完整技术体系,绝非零散工具的堆砌。1. 信息收集是渗透的基石,决定测试深度与成功率,核心在于精细化、绕过防护挖掘隐性信息;2. 高危漏洞探测与利用是核心突破,需吃透漏洞原理,规避工具误报、WAF拦截等问题;3. 权限提升与内网渗透是进阶核心,是区分入门与资深渗透工程师的关键;4. 日志清理与复盘是职业化核心,适配企业合规测试场景。从发展趋势来看,Web安全攻防对抗会持续升级,自动化渗透、AI漏洞挖掘、云原生安全、API安全将成为未来主流方向。

2501_92125808的博客 599

材料科学基于电致塑性效应的多场耦合精密成形:难变形合金超薄带材低缺陷轧制工艺

内容概要:本文系统阐述了合金在电、热、力多场耦合作用下的电致塑性精密成形工艺(Electrically-Assisted Rolling, EAR),重点介绍其通过瞬时脉冲电流实现材料“成形时软、用时强”的核心技术原理。该工艺利用电子风力、焦耳热微区软化等非热与热效应协同作用,降低难变形合金的流动应力,提升单道次压下率(如SUS304由33.8%提升至41.5%),显著减少中间退火次数,实现数十微米级极薄带材的高效、低残余应力、高平整度轧制。文章详细分析了工艺参数(电流密度、频率、脉宽、温度窗口等)、装备配置(脉冲电源、绝缘辊系、在线检测)及失效模式控制,并强调需以“变形区有效电流密度”和“窄温区闭环控制”为核心进行工艺设计与优化。; 适合人群:从事金属材料加工、精密轧制、先进成形技术研发的科研人员与工程技术人员,具备材料科学与工程、机械制造或相关领域背景的研发工程师及研究生。; 使用场景及目标:①开发高强钛合金、不锈钢、特种合金等难变形金属的超薄精密箔材(如折叠屏基材、光刻机钢带);②优化现有冷轧工艺,降低能耗与退火次数,提升产品尺寸精度与表面质量;③研究电-热-力多场耦合成形机理,指导新型电辅助制造装备开发。; 阅读建议:本文兼具理论深度与工程实践指导意义,建议结合图表与实测数据理解多机制协同效应,重点关注电流回路设计、温度场闭环控制与参数标定方法,避免直接套用文献参数;在应用中应坚持“实验标定+仿真验证”原则,确保工艺安全性与可重复性。

电气工程基于电磁原理的继电器工作机理与应用:工业控制中强弱电隔离开关的设计选型及保护电路分析

内容概要:本文深入浅出地介绍了继电器的工作原理、核心结构、分类、常见应用场景及选型要点。继电器是一种利用小电流控制大电流的“自动开关”,通过线圈通电产生磁场,驱动衔铁吸合或释放,从而控制触点的通断。文章详细解析了其五大组成部分(线圈、铁芯、衔铁、弹簧、触点)和工作三步循环过程,强调了强弱电隔离的优势,并区分了常开、常闭和转换型触点的应用。同时,文章列举了继电器在工业控制、汽车电子、家用电器、新能源和电力系统中的典型应用,重点指出高压直流继电器在新能源汽车中的关键作用。针对选型,强调需根据负载类型(阻性、感性、容性)进行降额使用,并介绍续流二极管、RC吸收电路等保护措施以延长寿命。最后对比了电磁继电器与固态继电器的优缺点,帮助读者合理选择。; 适合人群:具备基础电工知识,从事电子、电气、自动化相关工作的技术人员或爱好者,以及工科类学生。; 使用场景及目标:①理解继电器在电路控制中的隔离与放大作用;②掌握继电器的选型方法与常见故障排查技巧;③应用于实际项目中如电机控制、电源管理、自动化系统设计等; 阅读建议:结合实物或电路图对照学习,重点关注触点保护与负载匹配部分,在实际应用中注意降额设计与环境因素影响。

塔式熔盐光热朗肯循环电站建模!并且搭建了Simulink模型!!

内容概要:本文详细介绍了塔式熔盐光热朗肯循环电站的系统建模过程,并成功构建了相应的Simulink仿真模型。研究不仅涵盖电站热力循环的核心建模,还深入集成电力系统的关键环节,包括一次调频与二次调频控制、风光水火储多能互补的双目标动态调度、化学储能与超级电容混合储能系统的双层容量配置、风电功率波动的RLMD分解与平抑、综合能源系统多目标优化配置等关键技术。同时,文中应用了多种先进优化算法,如多目标粒子群算法(MOPSO)、基于核密度估计(KDE)的CDF置信带鲁棒调度方法等,形成了从系统建模、仿真到优化决策的完整技术链条,为新型电力系统的分析与设计提供了综合性解决方案。; 适合人群:具备电力系统、新能源科学、自动化控制、热能工程等相关专业背景,熟悉MATLAB/Simulink仿真平台,从事能源系统建模、优化调度、储能控制、电力电子与电网稳定性研究的科研人员、研究生及工程师。; 使用场景及目标:① 为塔式光热电站及综合能源系统相关的教学与科研工作提供详尽的Simulink建模范例与Matlab代码参考;② 实现对高比例新能源接入背景下电网的频率响应、动态调度、储能优化配置等问题的仿真分析与控制策略验证;③ 利用所提供的完整代码与模型,复现并深入研究多目标优化、鲁棒调度、信号分解等先进算法在复杂能源系统中的具体应用。; 阅读建议:此资源以实际工程项目为导向,深度融合了系统建模、仿真验证与优化算法三大核心环节。使用者应在深入理解文档中所涉基础理论(如朗肯循环原理、调频控制机制、SVPWM调制技术等)的基础上,结合所提供的Simulink模型与Matlab代码进行动手实践,通过调整系统参数、优化算法配置等方式,探究系统动态特性与优化机制。同时,强烈建议关注文末提供的完整资源下载链接,以获取全部配套的仿真文件、计算书及参考文献,确保学习的完整性与可复现性。

智算中心AI大模型赋能智能体平台及AI场景应用规划方案(决策评审版).pptx

智算中心AI大模型赋能智能体平台及AI场景应用规划方案(决策评审版).pptx

【DBO三维路径规划】基于多策略改进的蜣螂算法MSDBO多无人机协同集群避障路径规划(目标函数:最低成本:路径、高度、威胁、转角)研究(Matlab代码实现)

内容概要:本文研究基于多策略改进的蜣螂算法(MSDBO)在多无人机协同三维避障路径规划中的应用,旨在实现最低成本的路径规划,综合考虑路径长度、飞行高度、环境威胁和飞行转角等多个目标函数。通过Matlab代码实现算法仿真,优化无人机集群在复杂三维空间中的协同飞行路径,有效规避静态与动态障碍物,提升任务执行效率与飞行安全性。该方法融合智能优化算法与路径规划技术,针对城市空中交通、应急救援、军事侦察等实际场景需求,提出了高效的分布式协同求解框架,为多无人机系统在复杂环境下的自主导航与集群控制提供了理论依据和技术支撑。; 适合人群:具备一定编程基础和优化算法知识的科研人员、自动化与人工智能领域研究生、从事无人机路径规划或智能优化算法开发的工程师。; 使用场景及目标:①应用于多无人机协同执行任务时的三维路径规划与动态避障;②解决复杂环境中多目标优化路径问题,提升集群飞行的安全性与经济性;③为智能交通、灾害巡检、城市物流等场景提供可扩展的算法支持;④支持进一步研究算法在异构无人机集群、实时通信受限条件下的适应性改进。; 阅读建议:建议读者结合Matlab代码进行实践操作,深入理解蜣螂算法的改进策略及其在路径规划中的具体实现方式,同时可通过调整环境参数、障碍物分布及目标权重进行扩展性研究,探索算法在不同任务场景下的性能表现与优化潜力。

Everything-v.1.4.1.1032 -X64-号称全世界查找文件最快的工具-便携版 .zip

Everything_v.1.4.1.1032 _X64_号称全世界查找文件最快的工具_便携版 .zip

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)

内容概要:本文系统研究了基于序贯蒙特卡洛模拟法的配电网可靠性评估方法,重点在于通过Matlab编程实现对含分布式电源的配电网在多种运行条件下的可靠性量化分析。文章深入阐述了序贯蒙特卡洛模拟的核心原理,包括系统状态的时序抽样、状态转移机制以及故障与修复过程的随机建模,并构建了完整的仿真流程以计算系统平均停电频率(SAIFI)、系统平均停电持续时间(SAIDI)等关键可靠性指标。研究结合典型配电网络算例,验证了该方法在评估复杂电力系统可靠性方面的有效性与实用性,尤其分析了分布式电源接入对系统可靠性的影响机制,为现代配电网规划与运行提供了科学依据和技术支撑。; 适合人群:具备电力系统基础理论知识和一定Matlab编程能力的高校研究生、科研机构研究人员,以及从事配电网规划、运行与可靠性管理的工程技术人员。; 使用场景及目标:①深入掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的具体实施过程与技术细节;②学习并实践利用Matlab进行电力系统时序仿真与可靠性指标统计分析的方法;③探究分布式电源渗透对配电网整体可靠性水平的影响规律,为提升电网韧性提供决策参考; 阅读建议:读者应结合文中提供的Matlab代码实例进行实操演练,建议在理解算法逻辑的基础上,尝试修改系统参数、网络拓扑结构或调整分布式电源的配置方案,通过对比仿真结果加深对可靠性评估过程和影响因素的理解,该资源亦可直接应用于相关科研课题或工程项目的技术论证。

长沙创沅-硬盘检测-固态硬盘测速工具 .exe

长沙创沅_硬盘检测_固态硬盘测速工具 .exe

【Linux】Petalinux使用QSPI FLASH引导启动

1. 预分配Flash空间使用Flash引导Petalinux做的系统,也有进阶的做法。部分图片和经验来源于网络,若有侵权麻烦联系我删除,主要是做笔记的时候忘记写来源了,做完笔记很久才写博客。1. 预分配Flash空间根据生成的bit文件大小估算BOOT.BIN文件的大小,为Flash大概分配四个分区:boot、bootenv、kernel、bootscr,分别存放BOOT.BIN文件、u-boot的环境变量、内核文件(image.ub/zImage/uImage等)、启动脚本boot.scr。

Tesseract_9527的博客 3376
上一篇: 13. AJAX Note
下一篇: 14. Struts2.x note
dev_J2EE
博客等级 码龄18年 0粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值