Struts2项目开发总结
(注:Struts2版本:Struts2.1.6,数据库:Oracle9i)
所须架包:
commons-logging-1.0.4.jar、commons-fileupload-1.2.1.jar 、freemarker-2.3.13.jar
ognl-2.6.11.jar、struts2-core-2.1.6.jar 、xwork-2.1.2.jar
1、若在前台页面使用orgl表达式:
必须定义:<%@ page isELIgnored = "false" %>
使用:${requestScope.count}来获取session中的值
2、在jsp页面中显示action中的数据,不需要点击链接到action再返回页面中显示数据
第一步,写一个action类
第二步:配置struts.xml文件,如:
class="com.txxw.cms.news.action.NewsSortListAction" method="sort5list">
第三步:在sort1.jsp中遍历action方法为sort5list的结果集:
第四步:在index.jsp中调用action为sort5list的方法
executeResult="true"> id="ctype">
3、Struts2超链接传参方式:
第一种:
第二种:
第三种:
注意:Struts2超链接标签
4、使用Struts2标签
其中内嵌html语言,
status="status",value属性是必选的
5、格式化日期显示方法
或者,只需要改变即可
必须定义:<%@ page import="java.text.SimpleDateFormat;"%>
Body体中引用:<%SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
Date ntime = new Date();
%><%=s.format(ntime)%>
6、Struts2下拉菜单的使用
listValue="ct_name" theme="simple" headerKey="0" headerValue="一级栏目">
listKey="key" listValue="value" headerKey="0">
属性注解:name是给Struts2
7、Struts2.1.6使用日期控件:
需要导入包:struts2-dojo-plugin-2.1.6.jar
<%@ taglib uri="/struts-dojo-tags" prefix="sx"%>
在head体中加入:
在body体中引用:
displayFormat="yyyy/MM/dd" value="%{'today'}">
属性注解:name是给
8、Struts2中form提交表单格式
在form中加入theme="simple"属性,就不会受Struts2
9、使用属性驱动取值
在action中将要输出的属性生成get和set方法,并将返回值定义为返回对象,如:
private String ntitle;//标题
private String ncontent;//内容
private String ntime;//时间
private String username;//发布人
News news=ns.queryNnewsdetailsql2(nid);//返回一个对象
public String getNtitle() {
return ntitle;
}
public void setNtitle(String ntitle) {
this.ntitle = ntitle;
}
public String getNcontent() {
return ncontent;
}
public void setNcontent(String ncontent) {
this.ncontent = ncontent;
}
public String getNtime() {
return ntime;
}
public void setNtime(String ntime) {
this.ntime = ntime;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
https://www.doczj.com/doc/ab16284674.html,ername = username;
}
由action直接跳转到要显示这些属性详细内容的页面
在jsp中直接使用标签
使用模型驱动:查改
新建action查询文章类型:
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.txxw.cms.news.model.Ctype;
import com.txxw.cms.news.model.CtypeService;
/**
*@author fejd E-mail:lzd_niit_java@https://www.doczj.com/doc/ab16284674.html,
*@version创建时间:May22,20091:43:21PM
*功能实现:文章类型修改内容查询
*/
public class CtypeeditAction extends ActionSupport implements ModelDriven {
private Ctype ctype=new Ctype();//将封装数据的ctype实现get和set方法@Override
public String execute() throws Exception {
// TODO Auto-generated method stub]
HttpServletRequest request=ServletActionContext.getRequest();
int
ct_id=Integer.parseInt(request.getParameter("ct_id").replace(",", ""));//通过选择复选框来实现单个文章类型修改
CtypeService cs=new CtypeService();
Ctype ctype=cs.editctypesql(ct_id);
this.setCtype(ctype);
return"success";
}
public Object getModel() {
// TODO Auto-generated method stub
return null;
}
public Ctype getCtype() {
return ctype;
}
public void setCtype(Ctype ctype) {
this.ctype = ctype;
}
}
Editctypesql()方法如下:
public Ctype editctypesql(int ct_id) throws IOException{
dbcon=new DBConnection();
con=dbcon.getCon();
Ctype cty=null;
List ctylist=new ArrayList();
try {
psta=con.prepareStatement(this.getEditCtypesql(ct_id));
psta.setInt(1, ct_id);
rs=psta.executeQuery();
while(rs.next())
{
cty=new Ctype();
cty.setCt_id(rs.getInt("ct_id"));
cty.setCt_name(rs.getString("ct_name"));
cty.setCt_sid(rs.getString("ct_sid"));
//数据类型Clob转换String类型START//
try
{
oracle.sql.CLOB
clob=(oracle.sql.CLOB)rs.getClob("ct_introduction");//数据库中存文本的CLOB型字段名
String
ct_introduction=clob.getSubString((long)1,(int)clob.length());//subSt ring是截取字符串(从1截到length)
if(clob==null||ct_introduction==null||ct_introduction==""){
return null;
}
cty.setCt_introduction(ct_introduction);
System.out.println(ct_introduction);
}//try
catch(Exception e){
logger.debug("数据类型Clob转换String类型出现异常");
https://www.doczj.com/doc/ab16284674.html,("数据类型Clob转换String类型出现异常");
e.printStackTrace();
}
//数据类型Clob转换String类型END//
cty.setCt_image(rs.getString("ct_image"));
ctylist.add(cty);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cty;
}
public String getEditCtypesql(int ct_id) {
this.editCtypesql="select *from system.ctype where ct_id=?";
return editCtypesql;
}
public void setEditCtypesql(String editCtypesql) {
this.editCtypesql = editCtypesql;
}
注明:上述方法中涉及到Oracle数据类型Clob转换成String类型问题
在jsp中使用
即可取出ctype中的数据。
10、Struts2+ajax实现批量删除,批量更新操作
全选: checkAll()
不选: checkAllNo()
反选: swichAll()
批量删除: deletenews()
批量更新:display1news()
function checkAll(){
var obj=document.getElementsByName("nid");
for(i=0;i obj[i].checked=true; } } function checkAllNo(){ var obj=document.getElementsByName("nid"); for(i=0;i obj[i].checked=false; } } function switchAll(){ var obj=document.getElementsByName("nid"); for(i=0;i obj[i].checked =! obj[i].checked; } } function vals(input1,input2) { var temp=""; var objForm = document.forms[input1]; var objLen = objForm.length; for (var iCount = 0; iCount < objLen; iCount++) { if (objForm.elements[iCount].type == "checkbox") { if(objForm.elements[iCount].checked==true&&objForm.elements[iCount].n id!="allSelected"&&objForm.elements[iCount].nid!="allConcled") { temp=temp+objForm.elements[iCount].value+","; } // objForm.elements[iCount].checked = true; } } return temp; } function deletenews(){ var nid=vals('form1','this') if(nid==""){ alert('你没有选中内容'); return false; } else{ if(confirm('你确定要删除选中的内容吗'+'?'+nid)){ var url="delete.action?nid="+nid; window.location.href=url; } } } function display1news(){ var nid=vals('form1','this') if(nid==""){ alert('你没有选中内容'); return false; }else{ if(confirm('你确定要显示选中的内容吗'+'?'+nid)){ var url="display1news.action?nid="+nid; window.location.href=url; } } } 11、控制Struts2 function sub() document.form.submit(); } 12、ajax前台验证(一部分) function check() { if(document.getElementById("ct_name").value==""){ alert("请输入栏目名称!"); return false; } document.form.submit(); } function check() { if(document.getElementById("ntitle").value==""){ alert("请输入文章标题!"); return false; } if(document.getElementById("nprovider").value==""){ alert("请输入供稿人!"); return false; } if(document.getElementById("ntelephone").value==""){ alert("请输入联系电话!"); return false; } var partten1 = /^1[3,5]\d{9}$/; var partten2 = /^0(([1,2]\d)|([3-9]\d{2}))\d{8}$/; if(partten1.test(document.getElementById("ntelephone").value)==false& &partten2.test(document.getElementById("ntelephone").value)==false) { alert("请检查您输入的联系电话格式"); return false; } if(document.getElementById("email").value==""){ alert("请输入Email!"); return false; } var zz=/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z 0-9]+$/; if(zz.test(document.getElementById("email").value)==false) { alert("请输入正确格式的Email."); return false; } document.form.submit(); } function check() { if(document.getElementById("nt").value=="") { alert("请输入查询关键字"); return false; } document.getElementById("form2").submit(); } 13、Struts2+Oracle9i数据库分页 第一步:新建分页的公共接口: public interface FenYeDao { public int count(int ct_id);//带有参数 } 第二步:实现接口方法(从数据库中获取数据的总行数): int ct_id) { int intRowCount = 0;//总行数 String sql= null ; ResultSet rs = null ; dbcon=new DBConnection(); con=dbcon.getCon(); sql = "select nid,ntitle,ntime, ntype from system.news a where a.ntype =(select ct_id from system.ctype c where c.ct_id=?)order by nid asc";//Sql语句可自定义 try { psta=con.prepareStatement(sql); psta.setInt(1, ct_id); rs =psta.executeQuery(); while( rs.next()){ //游标指向第一行 intRowCount+=1;//取得总行数 } } catch(Exception e) { System.out.println(e) ; } return intRowCount; } 第三步:新建action类: SortNewsListAction import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import com.txxw.cms.news.model.News; import com.txxw.cms.news.model.NewsService; public class SortNewsListAction extends ActionSupport implements ModelDriven { private int ct_id;//分页需要的参数 private String ntype;//文章类型 private List sortclist;//文章类型列表 private List sortnlist;//文章所有列表 private News news;//文章对象 private int pageNow = 1 ; //初始化为1,默认从第一页开始显示 private int pageSize = 8 ; //每页显示8条记录 private int k;//储存最大页面数 private int i;//从第i条查询数据 private int intRowCount;//总行数 private int intPageCount;//总页数 private NewsService ns=new NewsService(); @Override public String execute() throws Exception { // TODO Auto-generated method stub HttpServletRequest request=ServletActionContext.getRequest(); if(request.getParameter("pageNow")!=null){ try{ pageNow=Integer.parseInt(request.getParameter("pageNow")); }catch (Exception ex) { pageNow=1; } if(request.getParameter("ct_id")!=null) ct_id=Integer.parseInt(request.getParameter("ct_id")); } sortclist=ns.sortclist(ct_id); //文章类型列表 intRowCount=ns.count(ct_id); //获取匹配条件文章的总条数 k = (intRowCount+pageSize-1) / pageSize;//计算出总页数 //-------------翻页控制START--------------// if(pageNow < 1) { pageNow=1; } if(pageNow >= k){ pageNow = k; } if(pageNow==0) { pageNow=1; } //-------------翻页控制END--------------// i=pageNow*pageSize-pageSize;//每页要显示文章的条数 sortnlist=ns.sortnlist(i, pageSize,ct_id);//获取文章列表return"success"; } public Object getModel() { // TODO Auto-generated method stub return null; } public List getSortnlist() { return sortnlist; } public void setSortnlist(List sortnlist) { this.sortnlist = sortnlist; } public int getCt_id() { return ct_id; } public void setCt_id(int ct_id) { this.ct_id = ct_id; } public String getNtype() { return ntype; } public void setNtype(String ntype) { this.ntype = ntype; } public News getNews() { return news; } public void setNews(News news) { this.news = news; } public List getSortclist() { return sortclist; } public void setSortclist(List sortclist) { this.sortclist = sortclist; } public int getPageNow() { return pageNow; } public void setPageNow(int pageNow) { this.pageNow = pageNow; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getK() { return k; } public void setK(int k) { this.k = k; } public int getI() { return i; } public void setI(int i) { this.i = i; } public int getIntRowCount() { return intRowCount; } public void setIntRowCount(int intRowCount) { this.intRowCount = intRowCount; } public int getIntPageCount() { return intPageCount; } public void setIntPageCount(int intPageCount) { this.intPageCount = intPageCount; } } 第四步:在model层中实现方法 NewsService 获取文章类型列表方法Sortclist() public List sortclist(int ct_id){ dbcon=new DBConnection(); con=dbcon.getCon(); List sortclist=new ArrayList(); try { psta=con.prepareStatement(this.getSortclistSql()); psta.setInt(1, ct_id); rs=psta.executeQuery(); while(rs.next()){ Ctype ctype=new Ctype(); ctype.setCt_id(rs.getInt("ct_id")); ctype.setCt_name(rs.getString("ct_name")); ctype.setCt_image(rs.getString("ct_image")); sortclist.add(ctype); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return sortclist; } 分类文章列表显示方法Sortnlist() public List sortnlist(int i, int pageSize,int ct_id){ dbcon=new DBConnection(); con=dbcon.getCon(); List sortnlist=new ArrayList(); try { pstac=con.prepareStatement(this.getQueryCctypesql()); rsc=pstac.executeQuery(); String ntype[]=new String[1000]; while(rsc.next()){ ntype[(int)rsc.getInt("ct_id")]=rsc.getString("ct_name"); } rsc.close(); pstac.close(); psta=con.prepareStatement(this.getSortnlistSql()); psta.setInt(1, ct_id); rs=psta.executeQuery(); int a=0; while(rs.next()){ a++; if((a>i)&&(a<=i+pageSize)){ news=new News(); news.setNid(rs.getInt("nid")); news.setNtitle(rs.getString("ntitle")); String ct_name=ntype[(int)rs.getInt("ntype")]; news.setNtype(ct_name); news.setNcontent(rs.getString("ncontent")); news.setNtime(rs.getString("ntime")); news.setUsername(rs.getString("username")); news.setAuditing(rs.getInt("auditing")); news.setDisplay(rs.getInt("display")); news.setCommend(rs.getInt("commend")); news.setNsubhead(rs.getString("nsubhead")); news.setNsource(rs.getString("nsource")); news.setNinvalidate(rs.getString("ninvalidate")); news.setNinvalidate_time(rs.getString("ninvalidate_time")); news.setNprovider(rs.getString("nprovider")); news.setNtelephone(rs.getString("ntelephone")); news.setEmail(rs.getString("email")); sortnlist.add(news); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return sortnlist; } 第五步:jsp视图层:在“上一页”和“下一页”中加入判断,当pageNow<1时,“上一页”不可点击;当“pageNow>k总页数”时,“下一页”不可点击 共 共 第 value="sortnlist.action?pageNow=%{pageNow-1}&ct_id=%{ct_id}"> value="sortnlist.action?pageNow=%{pageNow+1}&ct_id=%{ct_id}"> 跳转到第 注:这种分页方式比较啰嗦,完全可以实现纯Struts2+数据库分页,建议小的项目可使用,不建议大项目使用,可以考虑利用数据库中来实现分页. 2012年第11卷第6期 产业与科技论坛2012.(11).6 Industrial &Science Tribune Struts2框架工作原理及应用体会 □宋 君 张家爱 【摘要】通过针对特定用户的分析,搭建以Struts2为技术核心的旅行社管理系统。本文简单的介绍了MVC 、 Struts2的工作原理,同时总结了在项目制作过程中所得到的心得。 【关键词】 Struts2;MVC ;FilterDispatcher ;Action 【基金项目】本文为大学生科技创新院级基金项目(编号:2011070)成果 【作者单位】宋君,吉林农业科技学院信息工程学院;张家爱,吉林农业科技学院信息工程学院教师 本着锻炼自我与积极参与到实用性技术的目标,以发掘自身创新意识为前提。利用空闲时间,在老师的指导下,进行了一次大学生创新项目的实践性活动。本着实用原则,以某中小旅行社为客户(根据用户需求,匿名),以Struts2框架为基点,进行了一次旅行社管理系统的开发。在项目结束之余, 特将在项目过程中经历的种种认识进行了简单的总结,希望让阅读本文的朋友们,更多的参与到此类活动中。 一、基础思想— ——MVC 简述作为时下经典框架之一, MVC 具有其独特的价值。MVC 框架简单的说,就是将数据模型与用户视图进行分离。通过控制器进行协调处理的一种结构是框架。同时,也是本文中要讨论的Sturts2框架的基础思想。 M 是指模型层(Model ),V 是指用户视图(View ),C 则是指控制器 (Controller )。这种划分方式是以将模型层与视图层进行代码分离,从而降低两者之间的耦合性,使同一程序可以使用不同形式进行表现。不同层之间的修改不会或尽量少的印象到其他层功能的史前为前提。有效的提高的代码的维护性和设计难度。 图1 二、 Struts2工作原理(一)Struts2框架组成。Struts2框架由三个主要部分组成:核心控制器、业务控制器,以及由用户实现的业务逻辑组件。这里我们将侧重于核心控制器与业务控制器的理解与说明。 (二)核心控制器:FilterDispatcher 。FilterDispatcher 是Struts2框架的核心控制器,在此,我们可以将FilterDispatcher 看作一个类似于过滤网的过滤器。当用户发出请求,并到达Web 硬哟那种时,该过滤器会过滤用户请求。如果用户请求的结尾为action ,则将该请求转入Struts2框架进行处理。当Struts2框架获得了*.actio 请求后,会根据请求前面“*”的那部分内容,决定调用哪个业务逻辑组件作为响应单位。这里需要说明的是Struts2用来处理用户请求的Action 实例并不是业务控制器,而是作为Action 的代理———正因为Struts2的一大特点,与Servlet API 的非耦合性,使得用户实现的业务控制器无法直接处理用户请求。有效的提高了后期调试维护的效率。而Struts2框架再次提供了了一系列的拦截器。这些拦截器负责将HttpServletRequest 请求的参数解析出来,传入Action 中,并毁掉Action 的Execute 方法来处理用户请求。用户实现的Action 类仅作为Struts2的Action 代理的代理目标。用户实现的业务控制器则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest 对象中,而用户的Action 类无需访问HttpServletRequest 对象。拦截器负责将HttpServletRequest 里的请求数据解析出来,并传给业务逻辑组件Action 实例。 (三)业务控制器。业务控制器就是前文提到的用来实现用户Action 的实力,这里的每个Action 类通常包含有一个execute 方法,当业务控制器处理完用户的请求后,该方法将会针对此次处理返回一个字符串— ——该字符串就是一个逻辑树图名。当程序开发人员开发出系统所需要的业务控制器后,还需要针对性的配置Struts2的Action ,即需要配置Ac- tion 的以下三个部分:(1)Action 所处理的URl 。(2)Action 组件所对应的实现类。(3)Action 里包含的逻辑试图和物理资源之间的对应关系。每个Action 都要处理一个用户请求,而用户请求则总是包含有指定的URL 。当核心控制器过滤用户请求,并调用后,根据请求的URL 和Action 处理URL 之间的对应关系来处理转发。 · 342· 阐述struts2的执行流程。 Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action 和用户实现的企业业务逻辑组件。 核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理 机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。Struts 2的工作流程相对于Struts 1要简单,与WebWork框架基本相同,所以说Struts 2 是WebWork的升级版本。 基本简要流程如下: 1、客户端浏览器发出HTTP请求。 2、根据web.xml配置,该请求被FilterDispatcher接收。 3、根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Aciton。 4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。 5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到 相应页面。 6、返回HTTP响应到客户端浏览器。 工作原理 在Struts2框架中的处理大概分为以下几个步骤 1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否 需要调用某个Action 4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action 类 6 ActionProxy创建一个ActionInvocation的实例。 7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP 一、 1、struts2 struts2是mvc设计思想的一个实现,可以将项目低耦合,提高扩展性 2、struts2和struts1的区别 struts2不是struts1的升级,而是继承的下xwork的血统,它吸收了struts1和webwork 的优势。 struts2的action是原型,安全的,struts2的action是单例,非安全 3、步骤: 1、导入包 2、在web.xml文件中,加入struts2的核心拦截器 3、在src下放入struts2的xml struts.xml 4、url http://localhost:8080/Struts2_01_HelloWorld/demo/hello.action 二、 1、默认值 2、转发和重定向的区别 转发:url显示的依然是上一个的url,共享上一次的请求 重定向:url显示的是下一个的url,不共享 3、url http://localhost:8080/Struts2_02_Default/demo/hello.action 4、路径 http://localhost:8080/Struts2_02_Default/demo/a/b/c/hello.action 1、原路径找不到,http://localhost:8080/Struts2_02_Default/demo/a/b/hello.action 2、如果1找不到,http://localhost:8080/Struts2_02_Default/demo/a/hello.action 3、如果2找不到,http://localhost:8080/Struts2_02_Default/demo/hello.action 3、如果3找不到,http://localhost:8080/Struts2_02_Default/hello.action 三、 11、自定义action 1.系统分析与设计 1.1 系统功能描述 本系统是个非常简单的注册、登录系统。本系统的实现是基于Struts2、Spring、Hibernate 三个框架,系统功能单一,业务逻辑简单。 当用户注册信用户时,就是向系统中增加一个新用户,对应的数据库增加一条记录。 当用户输入注册信息时,系统提供了基本的输入验证判断用户输入是否合法,只有当用户输入满足基本输入要求时,才会被提交到实际的登录系统,进行实际的登录处理。 系统还使用了随机产生的图形验证码来防止刷新,防止用户通过单击浏览器的书安心按钮来重复注册多个用户。 系统还提供了一种Ajax方式来验证用户输入的注册名是否有效,系统要求所有的用户名不能重复。故当用户输完用户名后,系统立即在页面上方提示用户该用户名是否可用,如果系统中没有该用户名,则系统提示该用户名可用;否则提示用户该用户名重复,用户必须重新选择用户名注册。 当用户注册一个新用户名之后,就可以使用系统的登录功能来登录系统了,用户输入登录用的用户名、密码后,系统一样提供了基本的输入校验。 除此之外,系统还采用了随机产生图形验证码来防止恶意用户的暴力破解,系统随机生成一个图形验证码,而用户登录必须输入图形验证码中显示的字符串,只有用户输入的字符串和系统随机生成的验证码字符相同时,系统才允许用户登录。 1.2 系统功能流程 1.3 数据库设计 相关的映射文件: Struts2在WebWork基础上发展起来的,可扩展的JAVA EE web框架。框架设计的目标贯穿整个开发周期,从开发到发布,包括维护的整个过程。 Action类:Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO 对象都可以用作Struts2的Action对象。 线程模式:Struts2Action对象为每一个请求产生一个实例,因此没有线程安全问题。 Servlet依赖:Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。 可测试性:Struts2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。 捕获输入:Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。Action属性能够通过web页面上的taglibs访问。 表达式语言:Struts 2 使用"ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。Struts2不仅支持JSTL, Struts2 还可使用OGNL进行类型转换。提供基本和常用对象的转换器。 校验:Struts2支持通过validate方法和XWork校验框架来进行校验。XWork 校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性。 在用到spring框架中时,场景如下 post 请求过去,对象接收不到参数的值(解决办法:考虑到在参数上加个@RequestBody 注解即可,有些没加的是框架帮忙处理了后默认接收的是json串) http://localhost:8080/xxxxxxxxxxx-xxxxxxx-api/xxxxxx/xxxxx/xxxxxxxxx/sugges t/add.sgt ================================================== ==================================== mapper.xml->@Repository{存储数据层}->@Service{业务层}->@Controller{展示层} (spring注解可以理解为这样的线性,任其项目结构怎么变这样的线性结构是不会变的,万变不 离其宗) @Repository @Service @Controller均是注册在spring上下文中 @Autowired 在spring上下文中找bean @Qualifier 配合@Autowired使用当找到多个同一类型的bean,则会抛异常,此时可以使用@Qualifier("beanName"),明确指定bean的名称进行注入 @RequestMapping 配置连接 @Required 注册在sett方法上,检查有没有被调用 @RequestParam 绑定参数 @RequestBody读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 Struts2基础知识 Struts2概述 1.Struts2框架应用javaee三层结构中的web层框架。 2.Struts2框架在struts1和webwork基础之上发展的全新框架。 3.Struts2所解决的问题: 在以往实现一个功能时,都需要写很多的servlet,从而造成后期维护上的不方便。 图解: 4.现在比较稳定的Struts2版本 struts-2.3.24-all.zip 5.web层常见框架 1.struts 2.springMVC Struts2框架入门 1.导入jar包 1.在lib里面有jar包,但不能全部导入,因为里面含有一些spring 包,是不能使用的,导入会导致程序不能运行。 2.到app目录里面复制案例的jar包是最好的方法。 2.创建action 3.配置action类的访问路径 1.创建struts2核心配置文件,该核心配置文件位置和名称是固定的, 位置必须在src下面,名称为struts.xml 。 2.引入dtd约束,可以在案例文件中找到,复制在struts.xml文件中即 可。 3.action的配置 *注意访问路径: http://域名/端口号/项目名/action名.action 注意:.action可以省略,但建议不要省略,为了兼容一些老版本的浏览器。 4.配置Struts2的过滤器,可以在案例中的web.xml文件中找到,复制粘贴 即可。 Struts2执行过程 图解: Struts2配置 1.是一种常量标签 2.修改Struts2的默认常量值 1.常用方式 在struts.xml中进行配置。 2.其它两种方式 1.在src下面创建struts.properties文件并修改。 2.在web.xml文件中进行修改。 3.Struts2最常用的常量 struts.il8n.encoding=UTF-8,解决表单在通过post方式提交中文时,中文乱码的问题。 Struts2面试题 1、struts2工作流程 Struts 2框架本身大致可以分为3个部分: 核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。核心控制器FilterDispatcher是Struts 2框架的基础, 包含了框架内部的控制流程和处理机制。 业务控制器Action和业务逻辑组件是需要用户来自己实现的。 用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件, 供核心控制器FilterDispatcher来使用。 Struts 2的工作流程相对于Struts 1要简单,与WebWork框架基本相同, 所以说Struts 2是WebWork的升级版本。基本简要流程如下: 1 、客户端初始化一个指向Servlet容器的请求; 2、这个请求经过一系列的过滤器(Filter) (这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器, 这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 、接着FilterDispatcher被调用, FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action 4、如果ActionMapper决定需要调用某个Action, FilterDispatcher把请求的处理交给ActionProxy 5、ActionProxy通过Configuration Manager询问框架的配置文件, 找到需要调用的Action类 6、ActionProxy创建一个ActionInvocation的实例。 7、ActionInvocation实例使用命名模式来调用, 在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP 或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper 9、响应的返回是通过我们在web.xml中配置的过滤器 10、如果ActionContextCleanUp是当前使用的,则FilterDispatecher将不会清理sreadlocal ActionContext;如果ActionContextCleanUp不使用,则将会去清理sreadlocals。 2、说下Struts的设计模式 MVC模式: web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生 成动态的网页,返回给客户。 Struts1 (1) Struts1和Servlet的关系 (1) 创建第一个Struts1项目 (1) 例子1: (3) 总结重点:struts1的工作流程(基于MVC模式的) (7) 一.普通的Servlet的工作流程 (7) 二.Structs1的工作流程(和上面的对比记忆) (8) Struts标签 (9) Bean标签 (9) html标签 (10) logic标签(逻辑标记) (12) i18n(国际化) (13) Struts1 Struts1和Servlet的关系 Jsp+Servlet+Javabean ActionForm和VO的区别: 一样的内容,不一样的作用 ActionForm只接收前台表单传来的数据 VO是conga后台提取的数据向前台传递 创建第一个Struts1项目 新建一个web项目,选择1.4即可 右键----MyEclipse----Add Struts Capacity ---------------Struts控制文件的路径 TLD(标签) 1) 2) Struts2 中的拦截器和servelt 中的过滤器是非常的相似的。如果学过过滤器的话,肯定能够感觉的到,尽管有些微的不同。可是struts2的拦截器到底如何使用呢,为什么会有这些配置呢?接下来一一来看。 过滤器和拦截器是非常相似的,过滤器public interface Filter 接口里面有三个方法: ?init(FilterConfig filterConfig), ?destroy(), ?doFilter(ServletRequest request, ServletResponse response, FilterChain chain), 这里面的doFilter() 方法是最重要的,在struts2 中String intercept(ActionInvocation invocation)就相当于此方法。 如何完成一个拦截器呢?在struts2 中要实现一个接口这个接口是什么呢?在哪呢?,是否在哪听说过?是webwork 是我们以前听的最多的关于拦截器的框架,struts2 用了其中一个核心的东西,这个东西在是什么呢?是xwork 。恩,有了它才可以拦截,好了我们在哪找呢?在com.opensymphony.xwork2.interceptor 中找,里面有个Interceptor 这是个接口,里面也有三个方法,有init,destroy 和intercept 三个方法,而在struts2 里面的所有的拦截器都继承这个接口! 为了看这些是怎么实现的,加入了一些打印! 将上面的配置整合起来就是: 这样就可以让Aciton 被拦截了,到此,好了,可以运行程序了: 输出结果是:启动服务器init 被打出 运行后提交action 输出intercept 这个就是初步的一个拦截器。 ======= 在此可能出现一个问题,是什么呢?如果就我们做的注册程序而言,可以想一下,有数据转换,有数据校验,以前当转换和校验不符合的时候,点击提交,会提示相关错误信息,然而,此时当转换和校验依然不符合要求时,点击提交,却不会提示错误信息,为什么呢? ==== 当然你答对了,这些功能都包含在struts2的默认拦截器中,这里没执行是被添加的拦截器myinterceptor取代了。 为了查明原因可以查看一下struts2-core-2.xx.jar中的struts-default.xml 这个文件 这里定义的很多的东西,和我们的程序相关的非常紧密 首先这里有个 1. 系统分析与设计 1.1 系统功能描述 本系统是个非常简单的注册、登录系统。本系统的实现是基于struts2、spring、 hibernate三个框架,系统功能单一,业务逻辑简单。 当用户注册信用户时,就是向系统中增加一个新用户,对应的数据库增加一条记录。 当用户输入注册信息时,系统提供了基本的输入验证判断用户输入是否合法,只有当用 户输入满足基本输入要求时,才会被提交到实际的登录系统,进行实际的登录处理。 系统还使用了随机产生的图形验证码来防止刷新,防止用户通过单击浏览器的书安心按 钮来重复注册多个用户。 系统还提供了一种ajax方式来验证用户输入的注册名是否有效,系统要求所有的用户名 不能重复。故当用户输完用户名后,系统立即在页面上方提示用户该用户名是否可用,如果 系统中没有该用户名,则系统提示该用户名可用;否则提示用户该用户名重复,用户必须重 新选择用户名注册。 当用户注册一个新用户名之后,就可以使用系统的登录功能来登录系统了,用户输入登 录用的用户名、密码后,系统一样提供了基本的输入校验。 除此之外,系统还采用了随机产生图形验证码来防止恶意用户的暴力破解,系统随机生 成一个图形验证码,而用户登录必须输入图形验证码中显示的字符串,只有用户输入的字符 串和系统随机生成的验证码字符相同时,系统才允许用户登录。 1.2 系统功能流程 1.3 数据库设计 相关的映射文件: <hibernate-mappingpackage= <classname=user table=user_table> <id name=idcolumn=user_id> <generatorclass=identity</id> nique=true/> <propertyname==user_passnot-null=true length=50/> <propertyname=emaillength=100/> </class> <propertyname=usercolumn=</hibernate-mapping> 一旦提供了上面的映射文件,hibernate就可以理解user和user_table之间的对应关 系。 2.系统实现与测试 2.1 系统采用的关键技术 mvc框架采用了struts2框架,struts2框架的易用性,极好的简化了系统的mvc层的实 现;本系统使用了struts2的json插件来完成ajax功能,除此之外本系统为了避免进行底 层的ajax交互,还是用了一个简单prototype.js函数库,用以简化ajax编程。struts2框 架的稳定性,为系统的稳定运行提供了保证。 spring容器作为系统的ioc容器,将系统中所有组件都放在spring容器中进行管理, 并且充分利用了spring ioc容器的功能,采用依赖注入来管理系统中各组件的依赖关系,避 免了各组件之间的硬编码耦合,提高了系统的可扩展性。 借助hibernate orm框架实现系统的持久化,通过hibernate的框架帮助,允许上层程 序采用面向对象的方式编程,二hibernate负责把面向对象的持久化操作转换成jdbc操作, 但hibernate的底层操作对开发者完全透明,从而让用户从具体的jdbc访问中释放出来,无 需理会底层的jdbc数据库访问,而是以面向对象的方式进行持久化操作。 2.2 关键程序流程 一. 配置问题: 最新的struts2为GA版2.2.1 其中必须类库为https://www.doczj.com/doc/ab16284674.html,mons-fileupload-1.2.1.jar 2. commons-io-1. 3.2.jar 3. freemarker-2.3.16.jar 4. javassist-3.7.ga.jar 5. ognl-3.0.jar 6. struts2-core-2.2.1.jar 7. xwork-core-2.2.1.jar 之前的版本使用ognl时不需要javassist这个类库现在这个版本则需要。。 二. EL表达式(JSP EL) 目的是为了使JSP写起来更加简单。 A、语法结构 ${expression} B、[ ]与.运算符 EL 提供“.“和“[ ]“两种运算符来存取数据。 当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用“[ ]“。例如: ${user.My-Name}应当改为${user["My-Name"] } 如果要动态取值时,就可以用“[ ]“来做,而“.“无法做到动态取值。例如:${https://www.doczj.com/doc/ab16284674.html,er[data]}中data 是一个变量 C、变量 EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为username的变量。 因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、Application范围查找。 假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,就回传null。 属性范围在EL中的名称 Page PageScope Request RequestScope Session SessionScope Application ApplicationScope D、特别强调: 1、注意当表达式根据名称引用这些对象之一时,返回的是相应的对象而不是相应的属性。例如:即使现有的pageContext 属性包含某些其他值,${pageContext} 也返回PageContext 对象。 2、注意<%@ page isELIgnored="true" %> 表示是否禁用EL语言,TRUE表示禁止.FALSE 表示不禁止.JSP2.0中默认的启用EL语言。 3、在web中用EL表达式时${name}其意思是调用其getName方法,而不是name这个属性 例如: 第一章MiniStruts 的制作 不使用Servlet,也不使用request.getParameter()获取参数;是用户能够直接访问Dao中的查询方法? 1、可以使用filter过滤器,用来拦截用户的表单提交(请求的路径、请求的参数)。 2、根据路径分析出,应该调用哪个类的哪个方法。 3、根据请求的参数,动态的将参数的值,设置到类的属性中去。 4、执行完成之后,需要跳转的页面(创建xml配置文件,配置用户跳转的路径信息)。 一、s truts的实现步骤 手动导入: 1.创建Web项目。 2.导入Strutrs的几个必须包(7个jar)。 3.在src目录下,创建struts.xml配置文件(名字和路径都不能改)。 4.在web.xml配置文件中,添加Struts的支持(配置一个filter过滤器)。 自动导入(Myeclipse8.0以上的版本): 第二章深入Struts Struts2运行原理: 请求--- >自定义过滤器----> filterdispatcher ------> ActionProxy(代理,读取struts.xml的配置文件)---->ActionInvocation(action的调用者,调用具体的Action;在调用之前经过一系列的拦截器)——>执行完Action之后,跳转到对应的页面。 注意:struts中的所有编码处理都是i18n拦截器处理,所有的表单数据处理都是在系统默认拦截器中获取。 Struts.xml配置文件详解: 动态方法调用: 注意:1. 在配置 Struts2 复习题 1.以下属于 struts2 的控制器组件是: 2.以下属于 struts2 的体系结构的是: ( 多选 ) 控制器组件配置文件 3.以下属于 struts2 配置文件中的配置元素是: ( 多选 ) A. struts2课程知识点总结 by wanggc 1.action a) struts2环境配置 包括5个基本jar包,web.xml中配置过滤器、struts.xml文件配置、 编写action b) 得到表单数据(接受参数) 两种方法:1、get set 方法2、对象 c) 动态方法配置 action中定义方法名称,strust.xml文件action中配置如: method=”add” Struts2项目开发总结 (注:Struts2版本:Struts2.1.6,数据库:Oracle9i) 所须架包: commons-logging-1.0.4.jar、commons-fileupload-1.2.1.jar 、freemarker-2.3.13.jar ognl-2.6.11.jar、struts2-core-2.1.6.jar 、xwork-2.1.2.jar 1、若在前台页面使用orgl表达式: 必须定义:<%@ page isELIgnored = "false" %> 使用:${requestScope.count}来获取session中的值 2、在jsp页面中显示action中的数据,不需要点击链接到action再返回页面中显示数据 第一步,写一个action类 第二步:配置struts.xml文件,如: Struts2框架工作原理及应用体会
Strurts2
strusts2课堂总结
struts2 实验报告
Struts2的介绍及总结
java 问题汇总(总结,重点)
Struts2知识点总结
struts2面试题(自己总结)
Struts1学习笔记总结
Struts2的拦截器总结
STRUTS2实验报告
struts2学习心得
Struts2总结
struts2复习总结计划题.docx
struts2课程知识点总结-01
Struts2开发总结