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文件,如:
<action name="sort5"
class="com.txxw.cms.news.action.NewsSortListAction"
method="sort5list">
<result name="success">/sort1.jsp</result> <result name="error">/error.jsp</result> </action>
第三步:在sort1.jsp中遍历action方法为sort5list的结果集:
<s:iterator value="sort5list" id="ctype" status="status">
<a href="sortnlist.action?ct_id=<s:property value="ct_id"/>"><FONT COLOR="#FFFFFF"><s:property value="ct_name"/></FONT></a>
</s:iterator>
第四步:在index.jsp中调用action为sort5list的方法
<s:action name="sort5"
executeResult="true"><s:iterator value="sort5list"
id="ctype"></s:iterator></s:action>
3、 Struts2超链接传参方式:
第一种:
<a href="newdetail2.action?nid=<s:property value="nid" />"><s:property value="ntitle"/></a>
第二种:
<s:url id="Newsquerynew" action="querynew.action">
<s:param name="request_locale">Newsquerynew</s:param>
</s:url>
<s:a href="%{Newsquerynew}">最新文章</s:a>
第三种:
<s:a href="newsAction.action ">直接使用即可 </s:a>
注意:Struts2超链接标签<s:a href=””>中的href属性是必选参数,否则在项目整合中可能会出现不明的标签异常。
4、 使用Struts2标签<s:iterator>循环遍历结果集:
<s:iterator value="sort5newslist">
<a href="newdetail2.action?nid=<s:property value="nid" />"><s:property value="ntitle"/></a>
<s:property value="ntime"/>
</s:iterator>
其中内嵌html语言,<s:iterator>除了value属性外,还有可选属性id=" "
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下拉菜单的使用
<s:select name="ct_sid" list="ctypesonlist" listKey="ct_id"
listValue="ct_name" theme="simple" headerKey="0"
headerValue="一级栏目">
</s:select>
<s:select name="ninvalidate" list="#{1:'是',2:'否'}"
listKey="key" listValue="value" headerKey="0"></s:select>
属性注解:name是给Struts2<s:select>标签取名字,这个也是提交到action并保存到对应的数据库中的字段名所必须得参数;list是下拉选项数值;listKey是选项列表所对应的id,listValue是选项列表每个字段的名称;theme是自定义下拉框格式,headerkey是首选项的主键id,headerValue是首选项的字段名
7、 Struts2.1.6使用日期控件:
需要导入包:struts2-dojo-plugin-2.1.6.jar
<%@ taglib uri="/struts-dojo-tags" prefix="sx"%>
在head体中加入:<sx:head />
在body体中引用:
<sx:datetimepicker name="ninvalidate_time" type="date"
displayFormat="yyyy/MM/dd" value="%{'today'}"></sx:datetimepicker> 属性注解:name是给<sx:detetimepicker>标签取名,type为date日期类型,displayFormat格式化显示日期,value是获取时间值,value="%{'today'}"是获取当前系统时间
8、Struts2中form提交表单格式
<s:form action="login" method="post" theme="simple" validate="true"> </s:form>
在form中加入theme="simple"属性,就不会受Struts2<s:form>定义格式的影响
9、使用属性驱动取值
在action中将要输出的属性生成get和set方法,并将返回值定义为返回对象,如: private String ntitle;//标题
private String ncontent;//内容
private String ntime;//时间
private String username;//发布人
News news=ns.queryNnewsdetailsql2(nid);//返回一个对象
public String getNtitle() {
} public void setNtitle(String ntitle) { } public String getNcontent() { } public void setNcontent(String ncontent) { } public String getNtime() { } public void setNtime(String ntime) { } public String getUsername() { } public void setUsername(String username) { } this.username = username; return username; this.ntime = ntime; return ntime; this.ncontent = ncontent; return ncontent; this.ntitle = ntitle; return ntitle;
由action直接跳转到要显示这些属性详细内容的页面
在jsp中直接使用标签<s:property value="ncontent"/>取出即可
使用模型驱动:查改
新建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@163.com
* @version 创建时间:May 22, 2009 1:43:21 PM
* 功能实现:文章类型修改内容查询
*/
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();
} 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")); } public Object getModel() { } public Ctype getCtype() { } public void setCtype(Ctype ctype) { } this.ctype = ctype; return ctype; // TODO Auto-generated method stub return null; Ctype ctype=cs.editctypesql(ct_id); this.setCtype(ctype); return "success";
//数据类型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());//subString是截取字符串(从1截到length)
if(clob==null||ct_introduction==null||ct_introduction==""){ } cty.setCt_introduction(ct_introduction); System.out.println(ct_introduction); }//try catch(Exception e){ } logger.debug("数据类型Clob转换String类型出现异常"); logger.info("数据类型Clob转换String类型出现异常"); e.printStackTrace(); return null;
//数据类型Clob转换String类型END//
cty.setCt_image(rs.getString("ct_image"));
} } public void setEditCtypesql(String editCtypesql) { } this.editCtypesql = editCtypesql; this.editCtypesql="select *from system.ctype where ct_id=?"; return editCtypesql; } return cty; } // TODO Auto-generated catch block e.printStackTrace(); ctylist.add(cty); } catch (SQLException e) { public String getEditCtypesql(int ct_id) {
注明:上述方法中涉及到Oracle数据类型Clob转换成String类型问题
在jsp中使用
<s:property value="ctype.ct_id"/>
即可取出ctype中的数据。
10、Struts2+ajax实现批量删除,批量更新操作
全选: checkAll()
不选: checkAllNo()
反选: swichAll()
批量删除: deletenews()
批量更新:display1news()
<script type="text/javascript">
function checkAll(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;i++){
obj[i].checked=true;
}
}
function checkAllNo(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;i++){
obj[i].checked=false;
}
}
function switchAll(){
var obj=document.getElementsByName("nid");
for(i=0;i<obj.length;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].nid!="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;
}
}
}
</script>
11、控制Struts2 <s:form>提交表单样式
<!-- form提交表单样式设置Start -->
<style type="text/css">
<!--
form { margin:0px;display:inline; }
-->
</style>
<!-- 控制form表单样式 -->
<script language="javascript">
function sub()
{
document.form.submit();
}
</script>
<!-- form提交表单样式设置End -->
12、ajax前台验证(一部分)
<script language="javascript">
function check()
{
if(document.getElementById("ct_name").value==""){
alert("请输入栏目名称!");
return false;
}
document.form.submit();
}
</script>
<script language="javascript">
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-z0-9]+$/;
if(zz.test(document.getElementById("email").value)==false) {
alert("请输入正确格式的Email.");
return false;
}
document.form.submit();
}
</script>
<s:form action="updatectype" name="form" method="post" theme="simple"> <s:textfield
</s:form>
<script language="javascript">
function check()
{
if(document.getElementById("nt").value=="")
{
alert("请输入查询关键字");
return false;
}
document.getElementById("form2").submit();
}
</script>
<form action="searchsortnews.action" name="form2" id="form2"
method="post">
按标题:
<input type="text" name="ntitle" id="nt" size="20" />
<s:hidden name="ct_id"></s:hidden>
<input type="image" src="images/tj.jpg" align="bottom"
onClick="return check();" />
<s:a style="cursor:pointer" onClick="return check();">查询</s:a> </form> name="ctype.ct_name" id="ct_name" size="30"></s:textfield>
<s:a style="cursor:pointer" onclick="return deletenews()">删除</s:a>
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){ } sortclist=ns.sortclist(ct_id); //文章类型列表 intRowCount=ns.count(ct_id); //获取匹配条件文章的总条数 k = (intRowCount+pageSize-1) / pageSize;//计算出总页数 //-------------翻页控制START--------------// if(pageNow < 1) }catch (Exception ex) { } if(request.getParameter("ct_id")!=null) ct_id=Integer.parseInt(request.getParameter("ct_id")); pageNow=1; try{ pageNow=Integer.parseInt(request.getParameter("pageNow"));
} { } if(pageNow >= k){ } if(pageNow==0) { } //-------------翻页控制END--------------// i=pageNow*pageSize-pageSize;//每页要显示文章的条数 sortnlist=ns.sortnlist(i, pageSize,ct_id);//获取文章列表 return "success"; pageNow=1; pageNow = k; pageNow=1; public Object getModel() { } public List getSortnlist() { } public void setSortnlist(List sortnlist) { } public int getCt_id() { } public void setCt_id(int ct_id) { } public String getNtype() { } public void setNtype(String ntype) { } public News getNews() { } public void setNews(News news) { return news; this.ntype = ntype; return ntype; this.ct_id = ct_id; return ct_id; this.sortnlist = sortnlist; return sortnlist; // TODO Auto-generated method stub return null;
} this.news = news; public List getSortclist() { } public void setSortclist(List sortclist) { } public int getPageNow() { } public void setPageNow(int pageNow) { } public int getPageSize() { } public void setPageSize(int pageSize) { } public int getK() { } public void setK(int k) { } public int getI() { } public void setI(int i) { } public int getIntRowCount() { } public void setIntRowCount(int intRowCount) { } public int getIntPageCount() { } public void setIntPageCount(int intPageCount) { } this.intPageCount = intPageCount; return intPageCount; this.intRowCount = intRowCount; return intRowCount; this.i = i; return i; this.k = k; return k; this.pageSize = pageSize; return pageSize; this.pageNow = pageNow; return pageNow; this.sortclist = sortclist; return sortclist;
}
第四步:在model层中实现方法
NewsService 获取文章类型列表方法Sortclist()
public List sortclist(int ct_id){
分类文章列表显示方法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); } dbcon=new DBConnection(); con=dbcon.getCon(); List sortclist=new ArrayList(); try { } return sortclist; psta=con.prepareStatement(this.getSortclistSql()); psta.setInt(1, ct_id); rs=psta.executeQuery(); while(rs.next()){ } // TODO Auto-generated catch block e.printStackTrace(); 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) {
} } 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")); } // TODO Auto-generated catch block e.printStackTrace(); news.setNprovider(rs.getString("nprovider")); news.setNtelephone(rs.getString("ntelephone")); news.setEmail(rs.getString("email")); sortnlist.add(news); } } catch (SQLException e) { return sortnlist;
第五步:jsp视图层:在“上一页”和“下一页”中加入判断,当pageNow<1时,“上一页”不可点击;当“pageNow>k总页数”时,“下一页”不可点击
共 <s:property value="intRowCount"/> 条 |
共 <s:property value="k"/> 页 |
第 <s:property value="pageNow"/> 页 |
<s:a href="sortnlist.action?pageNow=1&ct_id=%{ct_id}">首页</s:a> |
<s:url id="url_pre"
value="sortnlist.action?pageNow=%{pageNow-1}&ct_id=%{ct_id}"> <s:param name="pageNow" value="pageNow-1"></s:param>
</s:url>
<s:if test="pageNow>1"><s:a href="%{url_pre}">上一页</s:a></s:if> <s:else>上一页</s:else> |
<s:url id="url_next"
value="sortnlist.action?pageNow=%{pageNow+1}&ct_id=%{ct_id}"> <s:param name="pageNow" value="pageNow+1"></s:param>
</s:url>
<s:if test="pageNow<k"><s:a href="%{url_next}">下一页</s:a></s:if> <s:else>下一页</s:else> |
<s:a
</s:a>
<s:form action="newsAction.action" method="post" theme="simple"> 跳转到第<s:textfield name="pageNow" size="3"></s:textfield>页
<s:submit value="Go"></s:submit>
注:这种分页方式比较啰嗦,完全可以实现纯Struts2+数据库分页,建议小的项目可使用,不建议大项目使用,可以考虑利用数据库中来实现分页. href="sortnlist.action?pageNow=%{k}&ct_id=%{ct_id}">尾页