1.客户端传递过来的参数,会寻找action中set方法和参数名一样的,和属性名没有关系
在转发到的结果页面也可以这样获得: ${requestScope.username} ${requestScope.password} 或者 <%request.getParameter("username")%>
2.类型转换 比如我们注册表单的时候,如果不类型转化的话,那么在action中要有对应的属性,进行转化,我们可以在action中有个User类就行了!
"hello".equals(this.getUsername().trim());
类型转换的步骤: 前台输入一个数值,用,隔开,将它转化为point类型的
1.页面
2.类: public class Point{ private int x; private int y; ..... //set和get方法 } 3.public class PointConverter extends DefaultTypeConverter{
//转换有两种: //1.自定义类型到string类型转化 //1.string到自定义类型转化 public Object convertValue(Map context,Object value,Class toType){ //toType是要转换成的类型,客户端String到自定义类型转换 //value是要转换的值 //从客户端到服务器端的转化 if(Point.class==toType){ Point point=new Point(); //页面可能有几个叫做point的input,所以这里要转换成数组 String[] str=(String[])value; String[] paramValues=str[0].split(","); int x=Integer.parseInt(paramValues[0]); int y=Integer.parseInt(paramValues[1]); point.setX(x); point.setY(y);
retunr point; } //如果目标类型是String,就是向页面显示数据,从服务器端到客户端 if(String.class==toType){ Point point=(Point)value;
int x=point.getX(); int y=point.getY(); String result="[x="+x+", y="+y+"]";
return result; } return null; } } 4.public class PointAction extends ActionSupport{ private Point point; private Date date;//struts2自动进行转化2007-12-06 ......
} 4.PointAction-conversion.properties (该文件和PointAction文件在同一个包下面) //对哪个属性进行类型转化 point(属性名字)=com.test.converter.PointConverter
5.页面:
如果在多个action中都有Point,那么是否都的写 **Action-conversion.properties???? ,不需要!上面的是局部类型转换,下面写全局类型转换 对系统里面多有符合类型的action都要转换! 步骤: 在classpath下面建立配置文件: xwork-conversion.properties com.test.bean.Point=com.test.converter.PointConverter
strtus2本身提供了一个类型类型转换: 继承StrutsTypeConverter public class PointConverter extends StrutsTypeConverter{ public Object convertFromString(Map context,String[] values,Class toClass){ Point point=new Point(); String[] paramValues=values[0].split(",");
int x=Integer.parseInt(paramValues[0]); int y=Integer.parseInt(paramValues[1]); point.setX(x); point.setY(y);
retunr point;
} public String convertToString(Map context,Object o){ Point point=(Point)o;
int x=point.getX(); int y=point.getY(); String result="[x="+x+", y="+y+"]";
return result; } }
现在需要集合类型的:
public class PointAction extends ActionSupport{
private List
point; ........... }
public class PointConverter extends StrutsTypeConverter{
public Object convertFromString(Map context,String[] values,Class toClass){
List
list=new ArrayList(); for(String value:values) {String[] paramValues=values[0].split(",");
int x=Integer.parseInt(paramValues[0]); int y=Integer.parseInt(paramValues[1]); point.setX(x); point.setY(y);
list.add(point);
}
return list;
}
public String convertToString(Map context,Object o){
List
list=(List)o; StringBuilder sb=new StringBuilder(); sb.append("["); for(Point point:list){ int x=point.getX(); int y=point.getY(); sb.append("x=").append(x).append(",y=").append(y); } sb.append("]"); return sb.toString(); } }
还支持这样的类型转换 action中: private Point point; 不需要类型转化!显示会调用point的tostring方法; 采用这种方式,point要构造无参数的构造方法
2.验证框架: 输入校验(检验用户输入的信息是否符合要求): 输入检验是在类型转换基础之上的 struts表单标签库已经内置了基本的验证机制,比如:action中是int age;页面中输入字符串,那么框架在转化的是就会出现错误,表单中就会提示输入错误,但是那种提示信息不好看!
一.表单 不用struts2标签 进行输入校验 action继承ActionSupport重写validate 同样如果输入的类型不匹配,struts2先进行类型转化时候就会出错,然后校验 ,仍然会有标签自带的错误信息提示,而且表单中的内容会消失,要不想让他消失: 这种方式比较麻烦:那么我们用struts2表单标签就可以解决这样的问题
如果客户端给age提供abc的值,那么struts2不能进行类型转换,那么框架自动生成一条错误信息,并且将错误信息放在addFieldError里面,且将提交的值为0 那么怎么替换框架原有的提示信息呢? 在struts框架中要使用的常量,在struts.xml中配置: message.properties文件放在classpath下面 #类型转化出问题的话就会是下面的提示信息了 xwork.default.invalid.fieldvalue={0} error 参数0就是表单中name的值
上面是一个全局的验证。 下面是个局部的验证(验证某一个action): PointAction(action名字).properties文件和action在同一个包下面: #类型转换发生错误 int会为0,String会为null invalid.fieldvalue.age(action中的属性)=age conversion error
框架先是进行类型转化(如果类型转化错误,就会把错误信息保存在addFieldError里面,但是错误信息提示不友好,怎样修改 如上面) 然后在进行校验!
要想有中文提示信息: 那么用jdk带的native2ascii工具转化 native2ascii test.txt(含有中文) test.properties 用test.properties这个文件!
那么总结类型转换和输入校验的流程: 1.首先strtus2对客户端传来的数据进行类型转换 2.类型转换完毕后在进行输入校验 3.如果类型转换和输入校验都没有错误发生,那么进入execute方法
注意:如果类型转换不成功也同样进行输入校验
校验错误有2种:addFiekdError(属性级别错误)和addActionError(action级别错误) action级别的错误 在表单上面增加: field级别的错误,struts2表单标签就可以显示错误信息 theme属性定义为simple,就是没有样式的,不会为我们生成表格,这样我们就可以用自己的css来美化了
注意:::如果action中的方法为abc,那么验证方法为:validateAbc() 校验执行顺序: validateAbc validate abc 如果不想validate那么有两种解决办法: 1.不写validate方法 2.不写validate方法,增加validateExecute方法
上面都是写代码来验证的,那么下面讲框架验证,通过xml文件来验证:
步骤:
1.配置文件(针对每一个action)(参数参考xwork-2.0.4.jar下面的com.......validators)
文件名 PointAction-validation.xml
开头的一些信息从struts2下载的包中的例子中拷贝
true username should not be blank! true 6 10 username should be between ${minLength} and ${maxLength} true password should not be blank! true 6 10 password should be between ${minLength} and ${maxLength} true repassword should not be blank! true 6 10 repassword should be between ${minLength} and ${maxLength} true age should not be blank! 1 150 age should be...... true birthday should not be blank! 2001-01-01 2003-12-31 birthday should be between ${min} and ${max} true birthday should not be blank! 2005-01-01 2007-12-31 graduation should be between ${min} and ${max} 客户端校验:
1.form的主题(theme)不能设置为simple
2.form的validate属性设置为true
那么需要上面的xml配置文件!建议不要使用struts2的客户端校验
上面是针对action中的所有属性进行校验
那么针对某个方法进行校验?
PointAction-abc-validattion.xml 不过先校验这个文件,然后在校验
PointAction-validattion.xml 然后在validate方法,
建议对于不同的方法,写不同的检验文件
3.拦截器(Intersptor):
我的博客......
方法拦截器MehtodFilterInterceptor
方法名,方法名 方法名,方法名
4.文件的上传和下载:
实例一: 不用struts2,用apache的fileupload组件上传: jsp页面: servlet类: public class UploadServlet extends HttpServlet{ public void post(....){
DiskFileItemFactory factory=new DiskFileItemFactory(); //获得绝对目录 String path=request.getRealPath("/upload"); //上传文件大的话,就会先存储在临时存储目录,然后在转到上传目录 factory.setRespository(new File(path)); //设定上传文件的大小,如果小于等于这个大小,就保存在内存里面,然后转到上传目录,如果大于这个大小,先存储到临时目录,然后在转到上传目录 factory.setSizeThreshold(1024*1024); //创建实例 ServletFileUpload upload=new ServletFileUpload(factory); try{ //返回客户端上传的文件列表 List list=upload.parseRequest(request); for(FileItem item:list){ if(item.isFormField()){//是一般的类型 //获得表单中定义的name String name=item.getFiledName(); //获得用户输入的内容value String value=item.getString("gbk"); request.setAttribute(name,value); }else{ //获得表单中定义的name String name=item.getFieledName(); //获取上传文件的名字 String value=item.getName(); int start=value.lastIndexOf("\\"); String fileName=vlaue.substring(start+1); request.setAttribute(name,fileName); item.write(new File(path,fileName)); 或者 // OutputStream os=new FileOutputStream(new File(path,fileName)); // InputStream is=item.getInputStream(); // byte[] buffer=new byte[400]; // int length=0; // while((length=is.read(buffer))>0){ // os.write(buffer,0,length); // } // os.close(); // is.close(); } } }catch(Exception e){ .... } request.getRequestDispatcher("upload/reault2.jsp").forward(request,response); } }
实例二: struts2实现文件上传:
上传一个文件: public class UploadAction{ private String username; private String password; private File file; private String fileFileName; private String fileContentType; //属性的get和set方法 ......... public String execute(){ InputStream is=ne FileInputStream(file); String root=ServletActionContext.getRequest.getRealPath(/upload); File destFile=new File(root,this.getFileFileName()); OutputStream os=new FileOutputStream(destFile); byte[] buffer=new byte[400]; int length=0; while((length=is.read(buffer))>0){ os.write(buffer,0,length); } os.close(); is.close(); return "success"; } } 解决中文在struts.xml中加上:
用户上传固定的几个文件: public class UploadAction{ private String username; private String password; private List file; private List fileFileName; private List fileContentType; //属性的get和set方法 ......... public String execute(){ for(int i=0;i InputStream is=ne FileInputStream(file.get(i)); String root=ServletActionContext.getRequest.getRealPath(/upload); File destFile=new File(root,this.getFileFileName().get(i)); OutputStream os=new FileOutputStream(destFile); byte[] buffer=new byte[400]; int length=0; while((length=is.read(buffer))>0){ os.write(buffer,0,length); } os.close(); is.close(); } return "success"; } } 页面中有3个:都是
用户上传任意多个文件 jsp页面
file js代码: function addMore(){ var td=document.getElementById("more"); var br=document.createElement("br"); var input=document.createElement("input"); var button=document.createElement("input"); input.type="file"; input.name="file"; button.type="button"; button.value="Remove"; button.onclick=function(){ td.removeChild(br); td.removeChild(input); td.removeChild(button); }
td.appendChild(br); td.appendChild(input); td.appendChild(button); } Action服务器端代码:不用修改
409600 //每个文件的大小 application/vnd.ms-powerpoint 想改变错误提示信息: message.properties文件放在classpath下面 #类型转化出问题的话就会是下面的提示信息了 struts.messages.error.content.type.not.allowed=the fiel type is error struts.messages.error.file.too.large=the file is too large
用户下载: public class DownloadAction{ //和配置文件的inputName同样 public InputStream getDownloadFile(){ return ServlerActionContext.getServletContext.getResourceAsStream("/upload.struts.ppt"); }
public String execute(){
return success;
}
}
配置文件struts.xml
application/vnd.ms-powerpoint filename="struts2.ppt" downloadFile 对于下载的文件名,下载的文件类型都是在struts.xml文件中配置的,如果有不同的类型的文件要提供给用户下载,那么这种方式显然有失灵活性。
为了动态的设置文件类型和下载的文件名,我们可以编写 一个拦截器,在action执行完毕,result执行之前,动态添加StreamResult参数。
public class FileDownloadInterceptor extends Abstracterceptor{
public String interceptor(ActionInvocation invocation)throws Exception{
incocation.addPreResultListener(new PreResultListener(){
public void beforeResult(ActionInvocation invocation,String resultCode){ Map resultMap=invocation.getProxy().getConfig().getResults(); ResultConfig finalResultConfig=resultMap.get(resultCode); //为了简单起见,我们硬编码了下载文件的类型和下载文件名,实际应用中你可以读取数据库或者配置文件来获取下载文件的信息 finalResultConfig.addParam("contentType",application/zip); fianlResultConfig.addparam("contentDisposition","attachment;filename=\"abc.zip\""); } }); return invocation.invoke(); } }
4.国际化: 有几方面: 页面的国际化 action提示信息的国际化 类型转化提示信息的国际化 输入校验提示信息的国际化
java语言对于国际化的支持 ResouceBundle类 Locale类 如何来获得当前系统jdk里面的国家和语言的支持 public class Main{ public static void mian(Srting args[]){ Local[] locales=Locale.getAvailableLocales(); for(Locale locale:locales){ System.out.println(local.getDisplayCountry()+":"+local.getCountry()); System.out.println(local.getDisplayLanguage()+":"+local.getLanguage()); } } }
国际化文件支持文件(classpath下面) 命名:baseName_language_country 英文文件:hellofile_en_US.properties hello=hello:{0}(动态参数) 中文文件:hellofile_zh_CN.properties hello=\u4f60\u597d 对于中文文件,要转化。 国际化方法: public class Main{ public static void mian(Srting args[]){ //Local locale=Locale.getDefault();//取得中文 Local locale=Locale.US ResourceBundle bundle=ResourceBundle.getBundle("hellofile",locale); String value=bundle.getString("hello"); System.out.println(value); } } 国际化文件中有参数 public class Main{ public static void mian(Srting args[]){ Local locale=Locale.getDefault();//取得中文 ResourceBundle bundle=ResourceBundle.getBundle("hellofile",locale); String value=bundle.getString("hello"); String result=MessgeFormat.format(value,new Object[]{"北京"}); System.out.println(result); } }
在web中国际化
国际化文件: messge_en_US.properties addUser=Add User Infomation message_zh_CN.properties addUser=........
struts.xml
jsp页面
action中的国际化
国际化文件:放在classpath下面 messge_en_US.properties addUser=Add User Infomation username.invalid=...... message_zh_CN.properties addUser=username "{0}" invalid username.invalid=...... struts.xml action的validate方法 public void validate(){ .... this.addActionErroe(this.getText("username.invalid")); .... } 含有参数: public void validate(){ .... List list=new ArrayList(); list.add(username); this.addActionErroe(this.getText("username.invalid"),list); .... }
输入校验国际化:
true true 6 10 username should be between ${minLength} and ${maxLength}
资源文件如果不可能只有一个,有包级别的和类级别的 包级别的资源文件放在包下面: package_en_US.properties package_zh_CN.properties 发生错误会先从包级别找 类级别的资源文件和action RegisterAction_en_US.properties RegisterAction_zh_CN.properties
struts2的深入探索: 模型驱动:将属性封装在一个JavaBean里面为不是在action中 public class User{ private String username; private String password; ..... //属性的get和set方法 ....... } public class RegisterAction extends ActionSupport implements ModelDriven{
private User user=new User();
public User getModel(){ return user; }
public String execute(){ ............. } }
推荐使用属性驱动方式!
Preparable接口,在执行action方法之前先去执行的一些动作 public class MianAction implements Preparable{
public void prepare(){ ....... } ........
}
禁止表单重复提交:
首先:
//增加这个标签就可以了 .........然后:
........ 页面中显示重复提交不成功信息
action中使用Cookie Cookie cookie=new Cookie("username",this.getUsername()); cookie.setMaxAge(1000); response.addCookie(cookie);
只要是重定向,原来保存在request中的数据全部消失
struts2整合JFreeChat 首先下载jar包:选择 jfreechat-1.0.9.jar jcommon.jar 可以查看demo,在下载的包下面的jfreechat-demo.jar 双击 可以执行
体验JFreechat 饼图::::: public class Main{ public staic void main(String args[]){ //定义饼图数据集 DefaultPieDataset dpd=new DefaultPieDataset(); //设置数据 dpd.setValue("管理人员",25); dpd.setValue("市场人员",25); dpd.setValue("开发人员",45); dpd.setValue("其他人员",10); //工厂创建 JFreeChart chart=CharFactory.createPieChart("某公司人员组织结构图",dpd,true,true,true); //JFreeChart chart=CharFactory.createPieChart3D("某公司人员组织结构图",dpd,true,true,true); //用swing显示出来 ChartFrame chartFrame=new ChartFrame("某公司的人员组织图",chart); chartFrame.pack(); chartFrame.setVisable(true); } }
将图表对象转换成图片 public class Main{ public staic void main(String args[]){ //定义饼图数据集 DefaultPieDataset dpd=new DefaultPieDataset(); //设置数据 dpd.setValue("管理人员",25); dpd.setValue("市场人员",25); dpd.setValue("开发人员",45); dpd.setValue("其他人员",10); //工厂创建 JFreeChart chart=CharFactory.createPieChart("某公司人员组织结构图",dpd,true,true,true); //设置标题 chart.setTitle(new TextTitle("hello",new Font("宋体",Font.BLOD,22))); LegendTitle legend=chart.getLengend(0); legend.setItemFont(new Font("宋体",Font.BLOD,22)); PiePlot plot=(PiePlot)chart.getPlot(); plot.setLableFont(new Font("宋体",Font.BLOD,22)); //输出为图片 OutputStream os=new FileOututStream("company.jpeg"); ChartUtilities.vriteChartAsJPEG(os,chart,1000,800); os.close(); } }
如何在jsp里面生成JFreechat图片 首先在web.xml中加入: DisplayChart org.jfree.chart.setvlet.DisplayChart DisplayChart /servlet/DispalyChart jsp页面: <% //定义饼图数据集 DefaultPieDataset dpd=new DefaultPieDataset(); //设置数据 dpd.setValue("管理人员",25); dpd.setValue("市场人员",25); dpd.setValue("开发人员",45); dpd.setValue("其他人员",10); //工厂创建 JFreeChart chart=CharFactory.createPieChart("某公司人员组织结构图",dpd,true,true,true); //输出为图片 String filename=ChartUtilities.vriteChartAsJPEG(chart,1000,800,session); //文件在服务器上的地址 String url=request.getContextPath()+"DisplayChart?filename="+filename;
%>
struts2整合 jsp页面:
Action类: public class Viewresult extends ActionSupport{ private JFreeChart chart;
private List interest;
...get和set
public String execute(){
super.execute(); } //把下面的这方法放在业务逻辑里面,别放在这里 public void increaseResult(List list){ ActionContext context=ActionContext.getContext(); Map map=context.getApplication(); for(String str:list){ if(null==map.get(str)){ map.put(str,1); }else{ map.put(str,(Integer)map.get(str)+1); } } //产生柱状图 private CategoryDataset getDataset(){ DefaultCategoryDataset dataset=new DefaultCategoryDataset(); this.increaseResult(this.getInterest()); ActionContext context=ActionContext.getContext(); Map map=context.getApplication(); dataset.setValue((Integer)map.get("football"),"","足球"); dataset.setValue((Integer)map.get("basketball"),"","篮球"); ..... return dataset; } //生产JFreechat对象 public JFreeChat getChart(){
chart=ChartFactory.createBarChart("兴趣统计结果","项目","结果",this.getDataset(),PlotOrientation.VERTICAL,false,false,false); CategoryPlot plot=(CategoryPlot)chart.getPlot(); CategoryAxis categoryAxis=plot.getDomainAxis(); catoryAxis.setLableFont(new Font("宋体",Font.bold,22)); categoryAxis.setCategoryLablePositions(CategoryLablePosotions.UP_45);
NumberAxis numberAxis=(NumberAxis)plot.getRangeAxis();
numberAxis.setLableFont(new Font("宋体",Font.bold,22))
return chart;
}
}
}
将struts-plugin-freechart.jar放在lib下面
首先解压缩情切修改struts-plugin-freechart.jar下面的struts-plugin.xml文件增加 extends="struts-default"
然后在打包成jar包:
进入struts-plugin-freechart文件下面->jar cvf struts-plugin-freechart.jar -C *
struts.xml中的配置:
600 800
struts2整合JasperReport报表
下载JasperReport和iReport
执行iReport,双击.exe文件 学会怎样使用iReport