一、struts类型转换器注册方法
通过插件机制注册,插件只需实现plugIn接口,然后在struts-config.xml中将插件注册一下,这样该转换器就可以在struts中用了!
二、Validator验证框架
首先要加载validator-rules.xml和validator.xml配置文件,然后根据validator-rules.xml中注释填写.properties文件;然后在validator.xml中配置需要验证的actionform以及验证规则;然后将验证框架的配置文件.properties在struts-config.xml中进行注册
注:实用验证框架时Action中配置的validate必须为true,formbean必须继承自validatorform
缺点:要应用在dispatchAction中应用验证框架,必须对验证框架的验证规则进行重写。
三、struts模型驱动及批量封装
FormBean封装时并不是将JavaBean中的各个对象属性封装到其中,而是在其中封装一个JavaBean对象,而在页面利用JavaBean的自省机制以 对象.属性 的方式给各个输入域命名,这样struts会将客户提交的数据封装成JavaBean对象
批量封装
完成类似Ajax的功能,但不同的是每次页面新增行时需要同服务器进行交互,而Ajax只是在页面上进行操作,效率高
原理:批量封装请求发起后,不是直接跳转到新增页面,而是先经过一个预新增(toAdd)方法,在该方法中将以struts 模型驱动产生的ActionForm(该ActionForm中封转了一个List<T>和int index)创建一个空对象放到请求属性域中传到页面,并在页面将该对象取出,这样页面就会显示一个空行;当用户发起一个添加行操作时系统从ActionForm中取出批量对象list并向其中加入一个空实体对象,然后再将该list再返回页面,这样也页面就会添加一个新空行
同样,删除一行也要向服务器发起一个remove请求,并将当前行行号传到服务器,服务器根据行号将list中对应的对象删除!
注:以模型驱动产生的ActionForm中存放了一个list对象,在页面中给各输入域命名时也要按照JavaBean自省机制来命名,所以ForEach的同时给各个输入域的name命名时要将list中的元素以下标来取出以便删除操作时行号的传递,如:
<c:forEach items="${prods}" var="prod" varStatus="vs">
.......
<td><input type="text" name="prods[${vs.index}].title" value="${prod.title}"/></td>
.......
另外,本应用以增删为主,所以为了提高效率实用了linkedlist,因为双向链表记录前后项信息,所以删除行操作后如果刷新页面后台会抛出异常,所以需要重写linkedlist的get方法如下:
public E get(int index) {
// 当从容器中取出超过范围的元素时,本容器会自动先创建一个该类型的对象
while(this.size() <= index){
try {
this.add(clazz.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return super.get(index);
}
四、文件上传
需求:form表单method=post,enctype=multipart/form-data
原理:struts提供了一个FormFile可以解释multipart/form-data类型请求
页面提交请求后,将FormFile对象从ActionForm中取出然后即可以从该对象中获取文件名、文件大小、文件类型以及输入流,可以利用该输入流将文件写入本地磁盘,方法如下:
首先获取本地目录路径 this.getServlet().getServletContext().getRealPath(目录名),
根据该路径创建一个输出流 new BufferedOutputStream(new FileOutputStream(new File(本地磁盘目录名, 文件名(也可对文件重命名))))
将文件写入磁盘 byte[] buff = new byte[8192];for(int count = 0; (count = bis.read(buff))!= -1;){bos.write(buff, 0, count);}
FormFile内部机制:同样利用commons-fileupload包中的ServletFileUpload和FileItem对上传的数据进行解释封装,具体实现类似下列文件域上传图片方法:
HashMap<String ,String> hsmap = new HashMap<String,String>();
if(ServletFileUpload.isMultipartContent(request)){//判断提交数据是否为multipart格式
//创建fileupload对象对上传的文件进行处理
ServletFileUpload sfu = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> itemlist = null;
try {
itemlist = sfu.parseRequest(request);//将提交数据解释到list中
int size = itemlist ==null ? 0 : itemlist.size();
for(int i=0;i<size;i++){
FileItem item = itemlist.get(i);
if(item.isFormField()){//如果是普通表单
hsmap.put(item.getFieldName(), new String(item.getString().getBytes("ISO8859-1"),"UTF-8"));
}else{
if("img_url".equals(item.getFieldName())){//如果是文件域
//获取上传图片的名字(即原文件存放的完整路径相当于file的.getvalue())
String name = item.getName();
//将图片重新命名
String temp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String rename = temp+name.substring(name.lastIndexOf("."));
hsmap.put("img_url", rename);
File file = new File(headpath ,rename);
item.write(file);//将文件写入本地目录(之前可以对图片进行压缩及相应的处理操作)
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}