第50天了,一半了,正好是考研,教室那边的路都被封锁了,没有办法打水了……田老师也没有来,不会真的是因为昨天的事情吧?
昨天的事情田老师确实是很在乎,以后无论是什么样的纠纷,是公司和学生之间的,还是学生自己之间的,有冲突到外面去解决,否则课程立刻停止
,绝对没有商量……
===============================================
昨天给的struts-1.2.8-bin解压后的lib文件夹中的jar包,还有webapp里面有一些war包,可以放到Tomcat的webapps中去,启动服务器
之后,会自动将war包解开(可以在server.xml中去设置)
org.apache.struts.action中定义了一个最核心的组件controller,也就是ActionServlet
实际上Struts中核心去掌握控制器就可以了。
Struts中是如何实现MVC的?
新键立一个文件夹,里面再建一个WEB-INF,里面再弄个web.xml,还有刚才lib文件夹里面的那些jar包全部拷贝到WEB-INF中的lib文件夹
里面去。然后那些tld文件和dtd文件放到WEB-INF里面
里面有个web-app_2_3.dtd,其中有下面一段话:
<!--
This is the XML DTD for the Servlet 2.3 deployment descriptor.
All Servlet 2.3 deployment descriptors must include a DOCTYPE
of the following form:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
-->
说明web.xml中得这么写:
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/*.do</url-pattern> //所有以.do结尾的请求都会被ActionServlet接收 */
</servlet-mapping>
</web-app>
ActionServlet被称为总控制器!
表单的action中如果是/……………….do的话就是让总控制器去处理了。
总控制器接收请求后,然后将请求分发给其他的类去处理,总控制器本身不去处理逻辑,而是由
org.apache.struts.action中的Action去帮助处理,Action是介于请求和业务逻辑之间的适配器。
严格来说Action是控制器,由Action来决定调用哪一个逻辑Service服务。
Actions必须考虑线程安全问题,因为每个Actions的实例仅有一个,多个同时的请求可能会共享它,这也就是说,Actions里面
绝对不可以存储和特定用户有关的信息。
ActionServlet将请求分发到特定的Actions后,Actions调用execute方法(返回ActionForward),
接着ActionServlet根据返回的ActionForward决定转到哪个页面。
所有的.do地址都会转到ActionServlet中去,ActionServlet依据什么分发呢?就是依靠具体的地址:比如register.do
,login.do等
Struts是地址驱动的:.do的地址决定了要被送到总控制器中去,.do前面的地址决定了要被送到哪个Actions中去,Actions生成的
ActionForward转向提示会告诉Actions跳到哪个页面去。
ActionServlet在Struts中是唯一的,但是Actions有多个……
======================================
一个典型的例子就是登陆:
package first ;
import org.apache.struts.action.* ;
import javax.servlet.http.* ;
public class LoginAction extends Action
{
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) //继承的时候方法的访问权限可以放大,但是不可以缩小!
//比如父类里面有个方法是protected,子类里面这个方法可以是public;但是异常是相反的,父类方法抛出的异常必须比子类对应方法
//抛出的异常范围要大!父类的execute方法抛出了所有的异常,所以子类的这个方法就可以不必抛出异常了……也就是异常可以缩小,但是
//绝对不可以放大……因为可以用父类操纵一个子类,如果用父类new出一个子类,并且调用子类中的方法,如果子类中的方法抛出的异常不是父类
//方法异常的子集的话,就没有办法捕捉了;关于权限,这样的例子就更多了,比如Servlet中的7个do方法都是protected级别,但是我们写
//的子类全是public级别的。
{
String username = request.getParameter("username");
String password = request.getParameter("password");
if("jsp".equals(username)&&"jsp".equals(password))
{
return new ActionForward("/welcome.jsp");
}
else
{
return new ActionForward("/index.jsp");
}
}
}
--------------------------------------------------------
index.jsp:
<form action="loginUrl.do" method="post">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
<input type="submit">
</form>
welcome.jsp
<body>Welcome</body>
------------------------------------------------
在WEB-INF中建立struts-config.xml:
<?xml version="1.0"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<action-mappings>
<action path="/loginUrl" type="first.LoginAction" /> //完成了一个地址和action的映射,把一个页面和一个具体的Action连起来
//这里其实是绝对于模块路径
</action-mappings>
</struts-config>
---------------------------
别忘了还有web.xml:
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern> //所有以.do结尾的请求都会被ActionServlet接收,注意*的前面不可以加/!!!!
</servlet-mapping>
</web-app>
-------------------------------------
命令行:
javac -classpath "/lib/servlet-api.jar;/lib/struts.jar" -d ../classes LoginAction.java
==================================================
<url-pattern>/</url-pattern> 是Tomcat的默认路径,比如请求html地址,是默认的,一般自己不要去写!
conf里面的web.xml中:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
三种路径形式:
/
/* */
*.………………
==================================================
上午课程暂时告一段落,张老师要了解一下我们现在培训的具体学习情况,因为就业承诺的关系,所以张老师比较担心
我们目前的状况,现在老师认为有经验的东西学生未必认为那东西值得学,比如张老师讲Struts就只会花半天的时间,
但是这样一来恐怕大家都不愿意吧……田老师讲Struts需要10天的时间,真有点奇怪,怎么这么大的差别呢?上海、达内
都发生过集体退钱或是老师集体跳槽的事情,但是奇怪的是网上没有什么声音,而张老师这边好像有点风吹草动的就
有不少人颇有微辞似的。
现在后面的教学安排还是相对透明,张老师目前也不清楚……后面最后三天要讲一下面试中的题目,现在希望有人能够
提一下有关课程方面的意见,但是好像没人开口……
中午张老师从我这里拷走了尚学堂马士兵的视频教程,这真是意料之外的事情……大概他认为里面有什么很好的东西值得借鉴把……
==================================================
下午课程开始:
流程:地址驱动,先根据.do地址到ActionServlet里面,然后根据配置文件取.前面的地址,根据这个地址去找Action,然后调用
execute方法,该方法返回ActionForward给ActionServlet,由ActionServlet再转到相应的页面。
上午写的LoginAction中:
if("jsp".equals(username)&&"jsp".equals(password))
{
return new ActionForward("/welcome.jsp");
}
else
{
return new ActionForward("/index.jsp");
}
其实是不合适的,应该根据名字进行转向,而不是具体的路径
<struts-config>
<action-mappings>
<action path="/loginUrl" type="first.LoginAction" > //完成了一个地址和action的映射,把一个页面和一个具体的Action连起来
//这里其实是绝对于模块路径
<forward name = "success" path="/welcome.jsp" />
<forward name="failure" path="/index.jsp">
</action>
</action-mappings>
</struts-config>
-------------------------------------------------------------------
在eclipse里面:建立一个Web Project
使用MyEclipse里面的增添struts功能
web.xml:<load-on-startup>0</load-on-startup>:表示启动的时候就加载进来。
0表示最先被加载进俩,这个数字越大表明加载的顺序越靠后 。
index.jsp:
<%@ tablib uri="/WEB-INF/struts-html.tld" prefix="html"%>
//下面是Struts的自定义标签
<html:form action="/loginUrl"> //必须以斜杠开头!!!!!而且不加.do!这个斜杠代表的是模块路径,不是上下文路径!!
//标签会自动把它处理成是/loginUrl.do!不用我去标识它是.do文件
用户名:<html:text property="username"/><br>
密 码:<html:password property="password"/><br>
<html:submit />
</html:form>
如果在页面上使用了html:form的话,必须得有一个javaBean,属性和上面表单标签里面的对应。
package cn.itcast.struts.form;
public class LoginForm extends ActionForm
{
private String username ;
private String password ;
//要加上getter方法和setter方法。
//重载reset方法,这个方法会被Struts自动调用
public void reset(ActionMapping arg0,HttpServletRequest arg1)
{
username = null ;
password = null ;
System.out.println("该方法被调用了!!!");
//提交的时候,从请求中取出值后,先reset,然后再用那些值来设置你的formbean属性值!
//看似先reset没有必要,因为赋值本身是对原来的属性值的一种覆盖,为什么一定要先reset呢?
//现在的问题是提交过来的参数个数未必和formbean属性的个数一致!如果formbean属性里面有7个值,
//而提交过来的参数只有一个的话,如果没有调用reset就直接赋值的话,剩下的6个值仍然还会保持上一次
//的结果……还有,如果两个form表单对应一个ActionForm的话,它们必须得有两个不同的attribute值,
//否则会有冲突发生的!
}
}
表单提交的时候Struts会将这些参数设置到上面的javaBean中的同名属性中,这个javaBean的实例将会
作为一个参数传入execute方法里面去。
还要注册:
//注意:多个页面的表单可以共享一个表单的javaBean。
<struts-config>
<form-beans>
<form-bean name="loginForm" type="cn.itcast.struts.form.LoginForm" /> //声明出一个formbean
</form-beans>//作用一:将loginForm和一个路径关联起来,实际上就是和一个html表单关联起来
//作用二:会在生成的html页面中把表单的名字设为name中的属性
//作用三:默认情况下会把这个name属性存储在session中,名字为"loginForm",也就是存储那个表单的javabean。
//下面的scope就是设置表单bean的存储作用域,默认情况下存储在session里面!
//注意一个formbean是可以对应多个action-mapping的,每个表单只要name属性和form-bean的name一致的话,就是使用那个
//formbean,就会实例出那个formbean以供使用。
<action-mappings>
<action path="/loginUrl" type="cn.itcast,struts.action.LoginAction" name="loginForm" scope="request">
//name是你自己做的formbean!上面那句话实例出一个formbean
<forward name="success" path="/welcome.jsp" /> //用来指明ActionForward指明页面转移方向!
<forward name="failure" path="/index.jsp" redirect="true"/>
</action>
</action-mappings>
<message-resources parameter="cn.itcast.struts.ApplicationResources">
</struts-config>
//这里需要注意一个问题!如果多个action-mapping共享一个formbean的话,如果action元素中的scope中不设置属性的话,默认就是session,
//都往session里面存储同name的formbean对象必然会发生冲突,这就要用到Struts中的另外一个属性:attribute
<action path="/loginUrl" attribute="aa" type="cn.itcast,struts.action.LoginAction" name="loginForm" scope="request">
//这样一来,在作用域里面存储的属性名就不再是loginForm了,而是aa!这样有两个地址同时管理一个ActionForm的时候,由于它们设置好
//不同的attribute值,就不会发生冲突了。
然后再写Action
package cn.itcast.struts.action;
import …………………………………………………………………………………………
public class LoginAction extends Aciton
{
public ActionForward execute(ActionMapping mapping,ActionForm arg1,
HttpServletRequest request,HttpServletResponse response) throws Exception
{
String target = "failure";
LoginForm form (LoginForm)arg1 ;//强制类型转换
if("jsp".equals(form.getUsername())&&"jsp".equals(form.getPassword()))
{
target = "success";
}
else
{
form.reset(mapping,request); //失败的话就手工调用reset方法。
}
return mapping.findForward(target); //调用mapping的findForward方法。查找配置文件中的forward
//元素的name为target的所对应的路径。
}
}
之所以把表单做成一个对象,是为了更加的面向对象化,传递的时候操作了对象,就改变了表单的显示……
而且以javaBean的形式传递的话很方便和Hibernate之间的整合。
Struts中心就是ActionServlet总控制器。
============================================================
先请求地址,地址分为.前面和.后面,后面的决定这个表单是不是要进入总控制器,前面的决定是进入哪一个Action,
递交到ActionServlet后,ActionForm的这些属性值要在调用execute方法前就已经被设置好了
===============================================================
这样有了ActionForm的帮助,修改功能就比较好做了。
因为修改的时候一定会要求你要把默认值显示在表单里面的。
其实就是保证进入修改页面之前,一定要在配置文件中指定作用域里面存储好一个和attribute值同名的属性,这个属性值就是
formbean那个对象,对象里面已经事先被赋值了。
<a href="modifyInput.do?userId=1">修改个人信息??</a>
注意:在<html:form action="/modifyInput">中,由于是自定义标签,是不用加上.do的!
这样再新建另外一个页面:
<@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<html:form action="/modifySubmit">
<html:text proerty="username" /><br>
<html:password property="password" /><br>
</html:form>
现在有两个.do地址,一个来自超级链接,一个来自自定义标签表单
在action-mapping中加上:
<action path="/modifyInput" type="cn.itcast.struts.action.ModifyInputAction" >
<forward name="success" path="/modify.jsp" />
</action>
<action path="/modifySubmit" type="cn.itcast.struts.action.ModifySubmitAction" name="loginForm" attribute="modifyForm">
//因为这是个form提交过来的,所以必然要有个name关联ActionForm!!
//这里可以添加转向代码,就像上面的配置一样
</action>
建立一个ModifyInputAction:
public class ModifyInputAction extends Action
{
public ActionForward execute(…………………………)
{
//这里面是读取数据库的代码
LoginForm form = new LoginForm() ; //这是你单独创建的formbean,其实应该先在作用域里取,如果为null的话再new
form.setUsername("");
form.setPassword("");
request.getSession.setAttribute("modifyForm",form);//将ActionForm的实例对象存储入配置文件中制定的属性名中,作用域默认是session。
return actionMapping.findForward("success");//按照配置文件中的所指转发到指定的页面里面去……
}
}
public class ModifySubmitAction extends Action
{
//这里面是把修改后的信息去写数据库!!!!
//改了ActionForm就是改了页面表单里面的值,同样,改了页面表单里面的值同时也就改了ActionForm!两者是同步进行的!
}
======================================================================
这部分有点乱,需要好好清理一下。
Struts页面与我们以前写的jsp页面最大的不同之处是什么呢?需要用到Struts的一些自定义标签,自定义标签需要从几方面来说,
一种比较典型的是form表单相关标签,Struts提供的这个表单标签可以做到把打回的页面上显示一些原来没有的错误信息,比如
”用户名或密码不正确“。而且还提供国际化标签,来进行国际化的显示。
显示表单、显示表单验证的错误信息、文本国际化显示等等……
下载下来的Struts包的结构:
其中bin的zip里面有一些war包,这些war包里面的struts-documentation.war里面是
文档,struts-mailreader.war里面则是登录注册的编写示例
其实自定义的form标签会生成类似下面的:
<form action="">
<input type="hidden" tokeid="kdsajkfsxlxxxxdkfsdfkjxkxxk" />//隐藏表单域的id号可以防止表单的重复提交
</form>
表单提交后根据action去找ActionForm对象和对应的Action类:
其实ActionServlet根据路径调用Action之前已经把ActionForm做好了,这样才能传过去……
在Struts配置文件中已经根据Action映射好了对应的Action了,而且还对应好了相应的ActionForm实例,这都在配置文件中指明了!
面试题目:
int和Integer的区别:前者是基本数据类型,初始化的默认值是0;后者是包装类,初始化默认值是null;
一般都用Integer,因为如果没有给赋值的话就是空,它可以明确的表示到底是有值还是没值。
在第一次访问自定义标签的表单页面时,只要一执行到这个自定义标签,它就会自动根据配置文件去找对应的作用域中到底有没有ActionForm,
没有的话它会自己创建一个……传给ActionServlet里面后,ActionServlet会把表单里面的数据利用同名的setter方法弄进ActionForm里面去,
然后再给Action类……
现在说说修改信息,首先点击超级链接,到达表单页面,要求表单页面中必须填好原始信息,方便我们进行修改……