在JeeWeb中自动生成代码模块添加上传功能

来源:互联网 发布:jaba 并发编程 编辑:程序博客网 时间:2024/06/08 00:19

JEEWEB具有代码生成功能,在阅读源码及使用其开发过程中,想将上传功能集成到代码生成模块,现将改动记录如下:

1.修改src/main/resources下的upload.properties和spring-mvc.xml文件:

将upload.properties中的upload.base.dir的值由upload改为../uploads,即将上传的文件所在路径由项目下的upload路径更改为与项目同级的文件uploads,这样项目重新部署的时候就不会影响到上传的文件;

修改spring-mvc.xml,将原先配置的上传文件(如下)

<!-- 支持上传文件 --><!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"p:defaultEncoding="UTF-8" p:maxUploadSize="${upload.max.size}" p:uploadTempDir="${upload.base.dir}/temp"/>
去掉
p:uploadTempDir="${upload.base.dir}/temp"

因为如果不去的话,会在启动时报错:

严重: Servlet [springMvc] in web application [/jeeweb] threw load() exceptionorg.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:PropertyAccessException 1:org.springframework.beans.MethodInvocationException: Property 'uploadTempDir' threw exception; nested exception is java.lang.IllegalArgumentException: Given uploadTempDir [ServletContext resource [/../uploads/temp]] could not be createdat org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1170)at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:922)at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:82)at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:62)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1489)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:624)at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:672)at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:543)at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)at javax.servlet.GenericServlet.init(GenericServlet.java:158)at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266)at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1263)at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1948)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)at java.util.concurrent.FutureTask.run(FutureTask.java:262)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)at java.lang.Thread.run(Thread.java:744)Caused by: java.lang.IllegalArgumentException: Given uploadTempDir [ServletContext resource [/../uploads/temp]] could not be createdat org.springframework.web.multipart.commons.CommonsFileUploadSupport.setUploadTempDir(CommonsFileUploadSupport.java:156)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1157)... 37 more
几经查询,没找到有效解决方法,但发现去掉这项不影响使用,且启动也不报错。。

2.在src/main/webapp/static/common/js路径下添加ajaxfileupload.js文件,通过ajaxfileupload上传,可以从下方链接中下载:ajaxFileUpload 报这错jQuery.handleError is not a function

添加完后,在src/main/resources/mapper/tags/html路径下的vendors-js-html-component.xml中配置,添加:

 <js name="ajaxfileupload">      <![CDATA[        <!-- ajaxfileupload--><script src="${staticPath}/common/js/ajaxfileupload.js"></script>    ]]>       </js>
3.修改src/main/resources/codegen/template/code自动生成代码模板中的list和controller:

对于viewListTemplate.ftl添加:

  <html:js name="ajaxfileupload" />  <script type="text/javascript">function uploads(){$.ajaxFileUpload    (        {            url:"${r'${adminPath}'}/${moduleName}/${entityName?lower_case}/uploads", //用于文件上传的服务器端请求地址            type:"POST",             secureuri: false, //是否需要安全协议,一般设置为false            fileElementId: 'upload1', //文件上传域的ID            dataType: 'json', //返回值类型 一般设置为json,content            success: function (data, status)  //服务器成功响应处理函数            {            if(data.msg!='success'){            alert(data.msg);            }                location.reload(true);            },            error: function (data, status, e)//服务器响应失败处理函数            {                alert("error:"+e);            }        }    );    return false;}  </script> 

<grid:toolbar title="上传" btnclass="btn-warning" icon="fa-database" onclick="$('#upload1').click();"/>
<input type="file" id="upload1" name="upload1" onchange="uploads()" style="display:none" />
既添加了上传按钮,并写好了js,接着修改ControllerTemplate.ftl模板,添加:

import cn.jeeweb.modules.sys.service.IAttachmentService;import org.springframework.web.multipart.commons.CommonsMultipartResolver;import org.springframework.web.multipart.MultipartHttpServletRequest;import java.util.Iterator;import org.springframework.web.multipart.MultipartFile;import cn.jeeweb.modules.sys.entity.Attachment;import cn.jeeweb.core.utils.ExcelReader;import java.util.ArrayList;
导入需要的类,以及注入需要的service,

    @Autowired    protected IAttachmentService attachmentService;    
添加uploads方法:

@RequestMapping(value = "uploads", method = { RequestMethod.GET, RequestMethod.POST })    private @ResponseBody String uploads(HttpServletRequest request, HttpServletResponse response) throws Exception {    JSONObject json = new JSONObject();    String msg = "success";    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());if (multipartResolver.isMultipart(request)) { // 判断request是否有文件上传MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;Iterator<String> ite = multiRequest.getFileNames();while (ite.hasNext()) {MultipartFile file = multiRequest.getFile(ite.next());Attachment attachment = attachmentService.upload(request, file);String proPath=request.getServletContext().getRealPath("/");String filePath = proPath + attachment.getFilepath();String headPath = filePath.substring(0, filePath.indexOf("/uploads"))+"/uploads/template/userUpload.xlsx";//template后面自行替换模板(表头)List<List<String>> dataList = ExcelReader.readXlsx(filePath);List<String> headList = ExcelReader.readHeader(headPath);List<${entityName?cap_first}> list = new ArrayList<${entityName?cap_first}>();//要插入数据库的数据if(dataList.size()>0){for(int i=0;i<dataList.size();i++){List<String> rows = dataList.get(i);if(i==0){if(rows.size()==headList.size()){for(int j=0;j<headList.size();j++){if(headList.get(j).equals(rows.get(j))){continue;}else{msg = "fail:your table's header is mismatch!";json.put("msg", msg);return json.toString();}}}else{msg = "fail:your table header's length is not right";json.put("msg", msg);return json.toString();}}else{${entityName?cap_first} user = new ${entityName?cap_first}();//按顺序取值,放入对象中,添加到list里/**user.setId(rows.get(0).equals("")?null:Integer.parseInt(rows.get(0)));user.setName(rows.get(1));user.setSex(rows.get(2));user.setAge(rows.get(3));user.setHeight(rows.get(4));list.add(user);*/}}}if(list.size()>0){${entityName?uncap_first}Service.insertBatch(list);}continue;}}json.put("msg", msg);return json.toString();    }

对应的tree和onetomany路径下的两个模板修改方式如上一致。

上传的模板放在了uploads/template路径下,当上传文件后,会读取上传文件的第一行与模板的第一行比对,确定文件格式正确,才会继续读取文件内容,插入数据库。
4.上文涉及到的工具类ExcelReader.java见下,需要添加到cn.jeeweb.core.utils包下:

package cn.jeeweb.core.utils;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import net.sf.json.JSONArray;import net.sf.json.JSONObject;import org.apache.poi.hssf.usermodel.HSSFCell;import org.apache.poi.hssf.usermodel.HSSFRow;import org.apache.poi.hssf.usermodel.HSSFSheet;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.xssf.usermodel.XSSFCell;import org.apache.poi.xssf.usermodel.XSSFRow;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;public class ExcelReader {public static List<List<String>> readXlsx(String path) throws Exception{//String pathInputStream is = new FileInputStream(path);XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);List<List<String>> result = new ArrayList<List<String>>();//循环每一页,并处理当前循环页for(int numSheet = 0;numSheet < xssfWorkbook.getNumberOfSheets();numSheet++){XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(numSheet);if(xssfSheet == null){continue;}int lastRow = getEmptrRow(xssfSheet);//hssfSheet.getLastRowNum()XSSFRow row = xssfSheet.getRow(0);int minCol = row.getFirstCellNum();int maxCol = row.getLastCellNum();//处理当前页,循环读取每一行for(int rowNum = 0; rowNum < lastRow;rowNum++){XSSFRow xssfRow = xssfSheet.getRow(rowNum);List<String> rowList = new ArrayList<String>();//遍历该行,获取处理每个cell元素for(int col = minCol;col<maxCol;col++){XSSFCell cell = xssfRow.getCell(col);if(cell == null){rowList.add("");continue;}rowList.add(getStringVal(cell));}result.add(rowList);}}is.close();return result;}/** * 获取最后一行 */public static int getEmptrRow(XSSFSheet sheet) {int rownumber = 0;if (sheet != null) {Iterator<Row> rowiter = sheet.iterator();while (rowiter.hasNext()) {Row row = rowiter.next();if (row != null) {String rowValue = null;Iterator<Cell> iter = row.iterator();while (iter.hasNext()) {Cell cell = iter.next();if (cell.getCellType() == 0) {rowValue += cell.getNumericCellValue();} else {rowValue += cell.getStringCellValue();}}if (rowValue != null && !rowValue.equalsIgnoreCase("null")) {rownumber = row.getRowNum();}}}}return rownumber + 1;}public static List<String> readHeader(String path) throws Exception{InputStream is = new FileInputStream(path);XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);XSSFRow xssfRow = xssfSheet.getRow(0);int minCol = xssfRow.getFirstCellNum();int maxCol = xssfRow.getLastCellNum();List<String> rowList = new ArrayList<String>();//遍历该行,获取处理每个cell元素for(int col = minCol;col<maxCol;col++){XSSFCell cell = xssfRow.getCell(col);if(cell == null){rowList.add("");continue;}rowList.add(getStringVal(cell));}is.close();return rowList;}public static String getStringVal(XSSFCell cell){switch(cell.getCellType()){case Cell.CELL_TYPE_BOOLEAN:return cell.getBooleanCellValue()?"TRUE":"FALSE";case Cell.CELL_TYPE_FORMULA:return cell.getCellFormula();case Cell.CELL_TYPE_NUMERIC:cell.setCellType(Cell.CELL_TYPE_STRING);return cell.getStringCellValue();case Cell.CELL_TYPE_STRING:return cell.getStringCellValue();default:return "";}}}
至此,自动生成代码时,即可在列表页,自带上传功能,可以上传excel文件,插入数据到数据库,只是要自定义模板

的表头。

下方另附一些修改其他小地方的方法:

1.修改列表页默认一页显示的行数,需更改的地方:

(1)cn.jeeweb.core.model.PageJson.java中的:

private long rows = 10;// 每页显示记录数
(2)cn.jeeweb.core.tags.grid.DataGridTag.java中的:

private int rowNum = 10; // 这个参数是要被传递到后台,树结构时候,rowNum无效

2.在自动生成代码功能中,数据库字段与java字段映射部分,java字段类型添加Long类型方法:

(1)cn.jeeweb.modules.codegen.codegenerator.data.AttributeInfo.java中:

private String[] baseTypes = { "String", "Double", "Text", "Date", "Blob", "Short", "Integer", "Boolean","Long" };
添加Long;

(2)cn.jeeweb.modules.codegen.controller.TableController.java中添加Long:

private String[] types = { "String", "Double", "Text", "Date", "Blob", "Short", "Integer", "Boolean", "User","Long","this" };
(3)cn.jeeweb.modules.codegen.entity.Column.java中添加Long:

private String[] baseTypes = { "String", "Double", "Text", "Date", "Blob", "Short", "Integer", "Boolean","Long" };
即可。

参考博客:

1.ajaxFileUpload 报这错jQuery.handleError is not a function

2.jQuery插件之ajaxFileUpload

3.ajaxfileupload 始终不执行success 只执行error方法;SyntaxError: expected expression, got '<

4.点击上传按钮,文件自动上传












阅读全文
0 0
原创粉丝点击