miki艾比利个人博客

愿居于一城,与卿所见美好......

推荐文章

测试ckeditor代码高亮显示

    package jiabin.action;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import jiabin.entity.Notice;
    import jiabin.entity.Section;
    import jiabin.entity.Topic;
    import jiabin.entity.Zone;
    import jiabin.service.NoticeService;
    import jiabin.service.SectionService;
    import jiabin.service.TopicService;
    import jiabin.service.ZoneService;
    
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    /**date:2017.04.15
     * 功能:由于页面要通过action方法加载从数据库数据,比如帖子列表页面,Topic_list.action
     * 而进入首页的时候,要自动加载论坛空间,版块列表,以及帖子数据,而并没有指定的action跳转,所以要初始化指定action来实现加载
     * 相应数据
     * @author miik
     *
     */
    
    
    
    @Component
    public class InitAction implements ServletContextListener,ApplicationContextAware{
    
    	private static ApplicationContext applicationContext;
    	
    	@Override
    	public void contextDestroyed(ServletContextEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void contextInitialized(ServletContextEvent servletContextEvent) {
    		ServletContext application=servletContextEvent.getServletContext();
    	}
    	
    	@Override
    	public void setApplicationContext(ApplicationContext applicationContext)
    			throws BeansException {
    		this.applicationContext=applicationContext;
    	}
    
    
    }
    

     

    阅读全文>>

作者:miki分类:【javaEE浏览(392评论(2

2019-10-09 11:35:39

Java 缓存之 Ehcache 详解

    一:EhCache是一个纯Java的进程内缓存框架,具有如下特点:
        1. 快速简单,非常容易和应用集成。
        2.支持多种缓存策略 。
        3. 缓存数据有两级:内存和磁盘,因此无需担心容量问题 。
        4. 缓存数据会在虚拟机重启的过程中写入磁盘 。
        5. 可以通过RMI、可插入API等方式进行分布式缓存。
        6. 具有缓存和缓存管理器的侦听接口 。
        7. 支持多缓存管理器实例,以及一个实例的多个缓存区域 等特点。

     下载地址:
    http://sourceforge.net/projects/ehcache/files/
    在线文档:
    http://tool.oschina.net/apidocs/apidoc?api=ehcache2.5.2

     

    二:cache.xml文件简介


    xml文件配置:     
         

    
                  
                  
                  
               
       
              
       

          ehcache.xml元素的属性:
         name:缓存名称

            maxElementsInMemory:内存中最大缓存对象数

           maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大

           eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false

           overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。

           diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。

           diskPersistent:是否缓存虚拟机重启期数据

           diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒.

           timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才

                                     有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态

           timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有

                                     效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义.

           memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。

     

    三:Cache的数据淘汰策略


    FIFO :first in first out ,这个是大家最熟的,先进先出。
    LFU : Less Frequently Used ,一直以来最少被使用的将被清除,缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存。
    LRU (默认):Least Recently Used ,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,
     而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存.

     

    四:缓存数据存储位置:

     

     内存和磁盘;缓存数据会在虚拟机重启的过程中写入磁盘

    根据需要将缓存刷到磁盘。将缓存条目刷到磁盘的操作可以通过cache.flush()方法来执行.;

    在创建cache的时候,指定了存储在硬盘上也是ok 的,不过没有这个直观。

     

    五:创建Cache的方式以及使用:

     

    A:使用默认配置文件创建:


    java代码:

    CacheManager manager = CacheManager.create(); 

    B:使用指定配置文件创建:


    java代码:

    CacheManager manager = CacheManager.create("src/config/ehcache.xml"); 

    C:从classpath中找寻配置文件并创建:


    java代码:

    URL url = getClass().getResource("/anothername.xml"); 
    CacheManager manager = CacheManager.create(url);

     

    D:通过输入流创建:


    java代码:

    InputStream fis = new FileInputStream(new File("src/config/ehcache.xml").getAbsolutePath()); 
    try { 
    manager = CacheManager.create(fis); 
    } finally { 
    fis.close(); 
    } 

     

    E:卸载CacheManager ,关闭Cache :


    java代码:
    manager.shutdown(); 

    F:使用Caches :


    取得配置文件中预先 定义的sampleCache1设置,通过CacheManager生成一个Cache
    java代码:
    Cache cache = manager.getCache("demoCache");

    G:设置一个名为test 的新cache,test属性为默认:


    java代码:
    CacheManager manager = CacheManager.create(); 
    manager.addCache("test"); 

    H:设置一个名为test 的新cache,并定义其属性:


    java代码:
    //CacheManager manager = CacheManager.create(); 
    Cache cache = new Cache("test", 1, true, false, 5, 2); 
    manager.addCache(cache); 

    I:往cache中加入元素:


    java代码:
    Element element = new Element("key1", "value1");   

    J:从cache中取得元素:


    java代码:
    Element element = cache.get("key1");  

    第一步:生成CacheManager对象
    第二步:生成Cache对象
    第三步:向Cache对象里添加由key,value组成的键值对的Element元素

    --------------------- 本文来自 supingemail 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/supingemail/article/details/45365521?utm_source=copy

    阅读全文>>

作者:miki分类:【javaEE浏览(1277评论(4

2019-10-09 11:34:59

struts2结合common.fileUpload实现文件带进度条上传


    最后,项目还残存的问题就是:明明是每隔500ms向后台请求的进度信息,但是实际上后台并不能够在这段时间内返回对应的信息。亟待优化! 
    效果图如下: 

    获取文件上传信息的基本步骤:经测试有效

    上传文件时如何获取上传进度信息?

    从网上查一下资料就可以知道struts2对文件上传的request请求做了封装,也就是说在调用上传文件的action时就已经上传temp完成了。 
    那么既然这样,我们就可以重写struts2封装request的类:org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest; 
    由于这个类的许多方法都是private的,那么也就是说我们是无法通过extends来重写父类的一些方法的。怎么办呢? 
    暴力一点! 
    直接自定义一个JakartaMultiPartRequest类型的类,把父类的方法全部copy过来,然后在struts.xml中配置:

    
        
        
        
        
        ....
        

    接下来我们实现上述配置文件中的MultiPartRequest类: 
    通过intellij的反编译插件,我们decode JakartaMultiPartRequest这个类:源码如下—-大量代码来袭,直接copy这部分吧 不用细看

    /*
     * $Id: JakartaMultiPartRequest.java 1384107 2012-09-12 20:14:23Z lukaszlenart $
     *
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *  http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    package org.apache.struts2.dispatcher.multipart;
    
    import com.opensymphony.xwork2.LocaleProvider;
    import com.opensymphony.xwork2.inject.Inject;
    import com.opensymphony.xwork2.util.LocalizedTextUtil;
    import com.opensymphony.xwork2.util.logging.Logger;
    import com.opensymphony.xwork2.util.logging.LoggerFactory;
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadBase;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.RequestContext;
    import org.apache.commons.fileupload.disk.DiskFileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.struts2.StrutsConstants;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Multipart form data request adapter for Jakarta Commons Fileupload package.
     */
    public class JakartaMultiPartRequest implements MultiPartRequest {
    
        static final Logger LOG = LoggerFactory.getLogger(JakartaMultiPartRequest.class);
    
        // maps parameter name -> List of FileItem objects
        protected Map> files = new HashMap>();
    
        // maps parameter name -> List of param values
        protected Map> params = new HashMap>();
    
        // any errors while processing this request
        protected List errors = new ArrayList();
    
        protected long maxSize;
        private Locale defaultLocale = Locale.ENGLISH;
    
        @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
        public void setMaxSize(String maxSize) {
            this.maxSize = Long.parseLong(maxSize);
        }
    
        @Inject
        public void setLocaleProvider(LocaleProvider provider) {
            defaultLocale = provider.getLocale();
        }
    
        /**
         * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
         * multipart classes (see class description).
         *
         * @param saveDir the directory to save off the file
         * @param request the request containing the multipart
         * @throws java.io.IOException is thrown if encoding fails.
         */
        public void parse(HttpServletRequest request, String saveDir) throws IOException {
            try {
                setLocale(request);
                processUpload(request, saveDir);
            } catch (FileUploadBase.SizeLimitExceededException e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Request exceeded size limit!", e);
                }
                String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});
                if (!errors.contains(errorMessage)) {
                    errors.add(errorMessage);
                }
            } catch (Exception e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Unable to parse request", e);
                }
                String errorMessage = buildErrorMessage(e, new Object[]{});
                if (!errors.contains(errorMessage)) {
                    errors.add(errorMessage);
                }
            }
        }
    
        protected void setLocale(HttpServletRequest request) {
            if (defaultLocale == null) {
                defaultLocale = request.getLocale();
            }
        }
    
        protected String buildErrorMessage(Throwable e, Object[] args) {
            String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
            if (LOG.isDebugEnabled()) {
                LOG.debug("Preparing error message for key: [#0]", errorKey);
            }
            return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
        }
    
        private void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
            for (FileItem item : parseRequest(request, saveDir)) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Found item " + item.getFieldName());
                }
                if (item.isFormField()) {
                    processNormalFormField(item, request.getCharacterEncoding());
                } else {
                    processFileField(item);
                }
            }
        }
    
        private void processFileField(FileItem item) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Item is a file upload");
            }
    
            // Skip file uploads that don't have a file name - meaning that no file was selected.
            if (item.getName() == null || item.getName().trim().length() < 1) {
                LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
                return;
            }
    
            List values;
            if (files.get(item.getFieldName()) != null) {
                values = files.get(item.getFieldName());
            } else {
                values = new ArrayList();
            }
    
            values.add(item);
            files.put(item.getFieldName(), values);
        }
    
        private void processNormalFormField(FileItem item, String charset) throws UnsupportedEncodingException {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Item is a normal form field");
            }
            List values;
            if (params.get(item.getFieldName()) != null) {
                values = params.get(item.getFieldName());
            } else {
                values = new ArrayList();
            }
    
            // note: see http://jira.opensymphony.com/browse/WW-633
            // basically, in some cases the charset may be null, so
            // we're just going to try to "other" method (no idea if this
            // will work)
            if (charset != null) {
                values.add(item.getString(charset));
            } else {
                values.add(item.getString());
            }
            params.put(item.getFieldName(), values);
            item.delete();
        }
    
        private List parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
            DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
            ServletFileUpload upload = new ServletFileUpload(fac);
            upload.setSizeMax(maxSize);
            return upload.parseRequest(createRequestContext(servletRequest));
        }
    
        private DiskFileItemFactory createDiskFileItemFactory(String saveDir) {
            DiskFileItemFactory fac = new DiskFileItemFactory();
            // Make sure that the data is written to file
            fac.setSizeThreshold(0);
            if (saveDir != null) {
                fac.setRepository(new File(saveDir));
            }
            return fac;
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileParameterNames()
         */
        public Enumeration getFileParameterNames() {
            return Collections.enumeration(files.keySet());
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
         */
        public String[] getContentType(String fieldName) {
            List items = files.get(fieldName);
    
            if (items == null) {
                return null;
            }
    
            List contentTypes = new ArrayList(items.size());
            for (FileItem fileItem : items) {
                contentTypes.add(fileItem.getContentType());
            }
    
            return contentTypes.toArray(new String[contentTypes.size()]);
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
         */
        public File[] getFile(String fieldName) {
            List items = files.get(fieldName);
    
            if (items == null) {
                return null;
            }
    
            List fileList = new ArrayList(items.size());
            for (FileItem fileItem : items) {
                File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
                if (fileItem.isInMemory() &;&; storeLocation != null &;&; !storeLocation.exists()) {
                    try {
                        storeLocation.createNewFile();
                    } catch (IOException e) {
                        if (LOG.isErrorEnabled()) {
                            LOG.error("Cannot write uploaded empty file to disk: " + storeLocation.getAbsolutePath(), e);
                        }
                    }
                }
                fileList.add(storeLocation);
            }
    
            return fileList.toArray(new File[fileList.size()]);
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(java.lang.String)
         */
        public String[] getFileNames(String fieldName) {
            List items = files.get(fieldName);
    
            if (items == null) {
                return null;
            }
    
            List fileNames = new ArrayList(items.size());
            for (FileItem fileItem : items) {
                fileNames.add(getCanonicalName(fileItem.getName()));
            }
    
            return fileNames.toArray(new String[fileNames.size()]);
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
         */
        public String[] getFilesystemName(String fieldName) {
            List items = files.get(fieldName);
    
            if (items == null) {
                return null;
            }
    
            List fileNames = new ArrayList(items.size());
            for (FileItem fileItem : items) {
                fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
            }
    
            return fileNames.toArray(new String[fileNames.size()]);
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
         */
        public String getParameter(String name) {
            List v = params.get(name);
            if (v != null &;&; v.size() > 0) {
                return v.get(0);
            }
    
            return null;
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterNames()
         */
        public Enumeration getParameterNames() {
            return Collections.enumeration(params.keySet());
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterValues(java.lang.String)
         */
        public String[] getParameterValues(String name) {
            List v = params.get(name);
            if (v != null &;&; v.size() > 0) {
                return v.toArray(new String[v.size()]);
            }
    
            return null;
        }
    
        /* (non-Javadoc)
         * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
         */
        public List getErrors() {
            return errors;
        }
    
        /**
         * Returns the canonical name of the given file.
         *
         * @param filename the given file
         * @return the canonical name of the given file
         */
        private String getCanonicalName(String filename) {
            int forwardSlash = filename.lastIndexOf("/");
            int backwardSlash = filename.lastIndexOf("\\");
            if (forwardSlash != -1 &;&; forwardSlash > backwardSlash) {
                filename = filename.substring(forwardSlash + 1, filename.length());
            } else if (backwardSlash != -1 &;&; backwardSlash >= forwardSlash) {
                filename = filename.substring(backwardSlash + 1, filename.length());
            }
    
            return filename;
        }
    
        /**
         * Creates a RequestContext needed by Jakarta Commons Upload.
         *
         * @param req the request.
         * @return a new request context.
         */
        private RequestContext createRequestContext(final HttpServletRequest req) {
            return new RequestContext() {
                public String getCharacterEncoding() {
                    return req.getCharacterEncoding();
                }
    
                public String getContentType() {
                    return req.getContentType();
                }
    
                public int getContentLength() {
                    return req.getContentLength();
                }
    
                public InputStream getInputStream() throws IOException {
                    InputStream in = req.getInputStream();
                    if (in == null) {
                        throw new IOException("Missing content in the request");
                    }
                    return req.getInputStream();
                }
            };
        }
    
        /* (non-Javadoc)
        * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#cleanUp()
        */
        public void cleanUp() {
            Set names = files.keySet();
            for (String name : names) {
                List items = files.get(name);
                for (FileItem item : items) {
                    if (LOG.isDebugEnabled()) {
                        String msg = LocalizedTextUtil.findText(this.getClass(), "struts.messages.removing.file",
                                Locale.ENGLISH, "no.message.found", new Object[]{name, item});
                        LOG.debug(msg);
                    }
                    if (!item.isInMemory()) {
                        item.delete();
                    }
                }
            }
        }
    
    }
    

    好的,我们把上面这部分代码copy到我们自定义的public class MultiPartRequest extends JakartaMultiPartRequest {}中 
    复制粘贴完了之后,我们要ctrl f找到parseRequest方法。在这里,我们要设置文件上传进度监听器

     /**
         * 自定义的parseRequest方法
         * @param servletRequest
         * @param saveDir
         * @return
         * @throws FileUploadException
         */
        private List parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
            System.out.println("调用parseRequest方法");
            UploadProgressListener listener = new UploadProgressListener(servletRequest);
            DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
            ServletFileUpload upload = new ServletFileUpload(fac);
            upload.setSizeMax(maxSize);
            upload.setProgressListener(listener);
            System.out.println("设置监听器成功");
            return upload.parseRequest(createRequestContext(servletRequest));
        }

    在上面这个代码片段中可以看到:我们new了一个监听器UploadProgressListener 的实例,然后调用了ServletFileUpload .setProgressListener(listener)方法。也就是说:这里的监听器与我们以前写过的request,session等等监听器不同,不需要在web.xml中配置。这里只需要一行代码即可解决。

    那么我们就来实现这个监听器吧!

    这个监听器需要实org.apache.commons.fileupload.ProgressListener这个接口:我们直接implement一下。 
    在update方法中我们可以获取到已上传的文件长度,上传的文件的总长度,当前上传第几个文件。(当你上传一个文件的时候,打印日志就会发现这里会输出2。个人猜测是先上传到temp然后再上传到指定路径…) 
    我们在update方法中设置了文件上传状态实体类的实例,并且保存到session。这一步就是能让前端使用ajax访问到文件当前的上传进度信息。

    package listener;
    
    import entity.FileUploadProgress;
    import org.apache.commons.fileupload.ProgressListener;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    /**
     * Created by zipple on 2017/10/13.
     * 监听文件上传情况
     * 实现org.apache.commons.fileupload.ProgressListener接口
     */
    
    
    /**
     * 2018.11.27	miki	监听文件上传进度的监听器
     * 
     */
    
    public class UploadProgress implements ProgressListener {
    	HttpSession session;
    	/*
    	 * 实时更新上传进度
    	 * arg0:当前上传文件的大小
    	 * arg1:总共需要上传的大小
    	 * arg2:剩余上传文件的大小
    	 */
    	public void update(long arg0, long arg1, int arg2) {
    		// TODO Auto-generated method stub
    		if(arg1==0L){
    			return;
    		}
    		
    		//创造json格式参数
    		String value="var info={read:"+arg0+",total:"+arg1+",items:"+1+"}";		//items:"+arg2+"	d多文件上传的时候,使用arg2
    		
    //		System.out.println(value);
    		session.setAttribute("progress", value);	//上传完毕后,记得清除上传过后的进度条session
    	}
    	
    	public UploadProgress(HttpSession session){
    		this.session=session;
    	}
    
    }
    

     

    前端获取后台文件上传的进度信息

    上传文件可大致分为两个阶段:1. 上传到服务器上,在临时目录中 2.从临时目录中把文件移到指定目录(由自己写的action处理),而struts2.的监听器只监听

    public String upload()throws Exception{
    		
    		//2017.11.16 21:58 miki 加载网页静态化缓存路径
    		Properties prop = new Properties();
    		try {
    			prop.load(this.getClass().getClassLoader().getResourceAsStream("resource.properties"));
    		} catch (IOException e1) {
    			throw new RuntimeException(e1);
    		}
    		
    		//2017.11.16 20:37 取静态资源中常量
    //		String HTML_GEN_PATH = prop.getProperty("HTML_GEN_PATH");//静态资源存储路径
    
    		HttpServletResponse response=ServletActionContext.getResponse();
    		HttpSession session=request.getSession();
    			user=(User) session.getAttribute("currentUser");
    			if(user==null){
    				request.getRequestDispatcher("error.jsp").forward(request, response);
    			}
    			System.out.println("上传文件名为:"+uploadFileName);
    			shop=shopService.getShopByuserId(user.getId());
    			// 2017.08.05	miki 文件二次命名,作为下载url链接,采用uuid加密命名,并截取2-18位字符,二次加密,增加安全性
    			String imageName = "file_"+RadomUtil.getUUID().substring(2, 18)+uploadFileName.substring(uploadFileName.lastIndexOf("."));
    			File newfile = new File(ServletActionContext.getServletContext().getRealPath("/image_upload/source_upload/file")+"\\"+imageName);
    						
    			IOUtils.cp(upload, newfile);		//因为要设置表单里没有的属性(setImage(),)所以重新创造了一个photo对象
    			
    			//清除上传过后的进度条session
    			session.setAttribute("progress", null);
    			
    			source.setPath(imageName);
    			source.setUser(user);
    			source.setShop(shop);
    			source.setUpload_time(new Date());
    			sourceService.save(source);
    			user.setScore(user.getScore()+5);
    			shop.setSourceNum(shop.getSourceNum()+1);
    
    			shopService.save(shop);
    			userService.saveUser(user);
    						
    //			/*
    //			 * 2017.11.16	20:31 网页静态化实例
    //			 */
    //			try {
    //				User vistor=(User) session.getAttribute("currentUser");
    //				if (StringUtil.isEmpty(page)) {
    //					page="1";
    //				}
    //				PageBean pageBean=new PageBean(Integer.parseInt(page), 6);
    //				sourceList=sourceService.getSourcesByShopId(shop.getId(), pageBean);
    //				long total=sourceService.getSourceCountByuserId(shop.getUser().getId());
    //				StringBuffer param=new StringBuffer();	
    //				param.append("shopId="+shop.getId());
    //				pageCode=PageUtil.genPagination(request.getContextPath()+"/shop/Shop_view.action", total, Integer.parseInt(page), 6,param.toString());
    //				
    //				
    //				//创建一个数据集,Map将data封装进去
    //				Map data=new HashMap<>();
    //				data.put("vistor", vistor);	
    //				data.put("user", user);	
    //				data.put("shop", shop);
    //				data.put("sourceList", sourceList);
    //				data.put("pageCode", pageCode);
    //				//加载模板对象
    //				Configuration configuration=freeMarkerConfigurer.getConfiguration();
    //				Template template = configuration.getTemplate("shop.ftl");				
    //				//创建一个输出流,指定目录及文件名
    //				Writer out=new FileWriter(HTML_GEN_PATH +shop.getId()+ ".html");				
    //				//生成静态页面
    //				template.process(data, out);				
    //				//关闭流
    //				out.close();
    //				
    //			} catch (Exception e) {
    //				// TODO: handle exception
    //				e.printStackTrace();
    //			}
    								
    		return "su";
    	}

    返回json数据的struts.xml配置如下:

     
            
               shop/Shop_upload.action
            
            

    项目做到这里,后端的事情已经做完了。接下来就是前端显示进度条的事情。需要的同学可以继续往下看咯。

    前端那些事儿——css实现进度条控件

    css:可以直接copy,无需细看(firefox下测试无问题)

     

     

    控制进度条代码:在提交文件时同步调用此计时器即可。

    ...			
    if('${shop.sourceNum}'=='${shop.maxNum}'){
    				$("#error").html("*您已达到资源上传上限,请升级权限再来*");
    				return false;
    			}
    			$("#error").html("");
    			createProgress();
    			//getProgress();	//定时刷新
    			setTimeout("getProgressBar()",1000);
    			return true;
    
    
        /**
          * 展示上传进度条
          */
    
    
    
    
    

     

    阅读全文>>

作者:miki分类:【javaEE浏览(1303评论(3

2019-10-09 11:34:28

# 宇加业务协同平台-Mxgraph常用方法

    # 宇加业务协同平台-Mxgraph常用方法
    ###仅供参考,不对的地方或者有更好的方法可以修正
    ##判断浏览器兼容性
    ```

     if (!mxClient.isBrowserSupported()) {
                // Displays an error message if the browser is not supported.
                mxUtils.error('您当前浏览器不支持此组件!', 200, false);
      }else {
            ....正文
       }


    ```
    ##常用的全局属性配置[graph.setXXXX(bool)]
    ```

    // j禁用浏览器右键菜单
    mxEvent.disableContextMenu(container);
    //添加框选
    new mxRubberband(graph);
    //细胞可以克隆
    graph.setCellsCloneable(true); 
    //是否允许线悬吊着,摆动不定
    graph.setAllowDanglingEdges(false);
    //禁止放大缩小
    graph.setCellsResizable(false);
    //禁用折叠
    graph.foldingEnabled = false;
    // 启用工具提示、新连接和平移
    graph.setPanning(true);
    // 开启鼠标悬停提示
    graph.setTooltips(true);
    //设置可连接性
    graph.setConnectable(true);
    graph.setMultigraph(false);
    //去锯齿效果
    mxRectangleShape.prototype.crisp = true;
    // 是否启用对齐线帮助定位
    mxGraphHandler.prototype.guidesEnabled = true;
    //定义对齐线颜色
    mxConstants.GUIDE_COLOR = "#00A3D9"; 
    // 是否缩放网格
    // mxGraphHandler.prototype.scaleGrid = true;
    // 是否开启旋转
    mxGraphHandler.prototype.rotationEnabled = false;
    
    // 选择基本元素开启
    graph.setEnabled(true);
    // 开启文字编辑功能
    graph.setCellsEditable(true);
    //开启回车退出编辑
    graph.setEnterStopsCellEditing(true);
    // 鼠标悬浮在节点上显示浮动框
    new mxCellTracker(graph, '#8BF19F');


    ```
    ##常用方法
    ```
    //根据ID获取cell
    graph.getModel().getCell(uuid)
    ```
    ##属性重定义方法[graph.isXXX(function(cell){})]
    ```

    //根据ID获取cell
    graph.getModel().getCell(uuid)
    ```
    ##属性重定义方法[graph.isXXX(function(cell){})]
    ```
    // 重定义哪些cell锁定
    graph.isCellLocked = function(cell) { //锁定连线,不可随意拖动
        //                    if (graph.getModel().isEdge(cell)) {
        //                    return true;
        //                }else{
    
        return false;
        //}
    
    };
    //重定义哪些cell可以移动
    graph.isCellMovable = function(cell) {
        if(cell.type && cell.type == "taskType") {
            return false;
        } else {
            return true;
        }
    };
    //获取当前选中的cell
    var cell = graph.getSelectionCell();
    if (cell == null) {
        // Ext.Msg.alert('没有选择图形元素'); //'没有选择图形元素!'
        return;
    }
    var objId = cell.getId();  //元素ID
    var enc = new mxCodec();
    var node = enc.encode(cell); //解析为DOM对象时自定义属性才可以识别
    var nodetype = node.getAttribute('nodetype'); //取节点类型,如果是线则为空
    var source = node.getAttribute('source');  //取线的来源节点ID,如果是节点则值为空
    
    // var config = mxUtils.getXml(node);
    // 新窗口打开
    mxUtils.popup(mxUtils.getXml(node));
    // }
    ```
    ## 添加监听事件的方法
    ```
    graph.addMouseListener(mxEvent.MOUSE_DOWN,function () {
           alert(1111);
    });
    
    //设置节点的鼠标移入手型移出鼠标指示效果
    var track = new mxCellTracker(graph);
    track.mouseMove = function (sender, me) {
        var cell = this.getCell(me);
        if (cell) {
            //设置鼠标为样式为手状
            me.getState().setCursor('pointer');
            // updateStyle(cell, true);
        } else {
            // updateStyle(cell, false);
        }
    };
    //最常用的监听点击事件的
    graph.addListener(mxEvent.CLICK, function (sender, evt) {
        var cell = evt.getProperty('cell');
        if (!cell) return false;
    
        console.log('我点击了节点哦!');
        console.log(cell);
        var enc = new mxCodec();
        var node = enc.encode(cell);
        console.log(node);
    });
    //监听鼠标按下,移动,抬起事件
     graph.addMouseListener({
        mouseDown: function (sender, me) {
            console.log('mouseDown');
        },
        mouseMove: function (sender, me) {
            // console.log('mouseMove');
        },
        mouseUp: function (sender, me) {
            console.log('mouseUp');
        },
        dragEnter: function (evt, state) {
            console.log('dragEnter');
            // if (state != null) {
            //     this.previousStyle = state.style;
            //     state.style = mxUtils.clone(state.style);
            //     updateStyle(state, true);
            //     state.shape.apply(state);
            //     state.shape.redraw();
            //
            //     if (state.text != null) {
            //         state.text.apply(state);
            //         state.text.redraw();
            //     }
            // }
        },
        dragLeave: function (evt, state) {
            console.log('dragLeave');
            // if (state != null) {
            //     state.style = this.previousStyle;
            //     updateStyle(state, false);
            //     state.shape.apply(state);
            //     state.shape.redraw();
            //
            //     if (state.text != null) {
            //         state.text.apply(state);
            //         state.text.redraw();
            //     }
            // }
        },
        dragover: function (evt, state) {
            console.log('dragover');
        },
        drop: function (evt, state) {
            console.log('drop');
        }
    });
    
    graph.addListener({
        dragover: function (evt, state) {
            console.log('dragover');
        },
        drop: function (evt, state) {
            console.log('drop');
        }
    });
    mxEvent.addListener(container, 'dragover', function (evt) {
        if (graph.isEnabled()) {
            evt.stopPropagation();
            evt.preventDefault();
        }
    });
    mxEvent.addListener(container, 'drop', function (evt) {
        if (graph.isEnabled()) {
            evt.stopPropagation();
            evt.preventDefault();
    
            // Gets drop location point for vertex
            var pt = mxUtils.convertPoint(graph.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt));
            var tr = graph.view.translate;
            var scale = graph.view.scale;
            var x = pt.x / scale - tr.x;
            var y = pt.y / scale - tr.y;
    
            console.log(x);
            console.log(y);
            console.log(event);
            // Converts local images to data urls
            var filesArray = event.dataTransfer.files;
            console.log(filesArray);
            // for (var i = 0; i < filesArray.length; i++) {
            //     handleDrop(graph, filesArray[i], x + i * 10, y + i * 10);
            // }
        }
    });


    ```
    ## 定义默认样式以及样式类
    ```
    //默认VertexStyle
    var style = new Object();
    style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
    style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
    style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_LEFT;
    style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
    style[mxConstants.STYLE_FONTCOLOR] = '#000000';
    style[mxConstants.STYLE_FONTSIZE] = '11';
    style[mxConstants.STYLE_FONTSTYLE] = 0;
    graph.getStylesheet().putDefaultVertexStyle(style);

    var style = new Object();
    style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
    style[mxConstants.STYLE_OPACITY] = 50;
    style[mxConstants.STYLE_FONTCOLOR] = '#774400';
    graph.getStylesheet().putCellStyle('ROUNDED', style);

    //标准子过程样式
    style = new Object();
    style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE; //形状
    style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
    style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER; //垂直对齐
    style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP; //水平对齐
    style[mxConstants.STYLE_GRADIENTCOLOR] = '#DEE6E8'; //渐变色
    style[mxConstants.STYLE_FILLCOLOR] = '#FAFAFA'; //填充色
    style[mxConstants.STYLE_SWIMLANE_FILLCOLOR] = '#ffffff'; //swimlane填充色
    style[mxConstants.STYLE_STROKECOLOR] = '#9DA5A7'; //表头边框颜色
    style[mxConstants.STYLE_FONTCOLOR] = '#000000'; //字体颜色    
    style[mxConstants.STYLE_STROKEWIDTH] = '1'; //边框粗细
    style[mxConstants.STYLE_STARTSIZE] = '28'; //表头部高度
    style[mxConstants.STYLE_VERTICAL_ALIGN] = 'middle';
    style[mxConstants.STYLE_FONTSIZE] = '12'; //字体大小
    style[mxConstants.STYLE_FONTSTYLE] = 1;
    graph.getStylesheet().putCellStyle('standrad_tabStyle', style);
    //本节点
    thisPointStyle = mxUtils.clone(style);
    thisPointStyle["image"] = 'resources/images/graph/thisPoint.png';
    thisPointStyle["fontSize"] = '16';
    thisPointStyle["fontColor"] = '#fff';
    thisPointStyle['constituent'] = "1";
    thisPointStyle["verticalLabelPosition"] = "middle";
    thisPointStyle["verticalAlign"] = "middle";
    thisPointStyle["spacingTop"] = "4";

    thisPointStyle["align"] = "center";
    graph.getStylesheet().putCellStyle("thisPointStyle", thisPointStyle);
    //节点状态
    statusPointStyle = mxUtils.clone(style);
    statusPointStyle['constituent'] = "1";
    statusPointStyle["image"] = 'resources/images/graph/status-normal.png';
    graph.getStylesheet().putCellStyle("statusPointStyle", statusPointStyle);
    //添加数据节点
    addDataPointStyle = mxUtils.clone(style);
    addDataPointStyle["image"] = 'resources/images/graph/addDataPoint.png';
    addDataPointStyle["imageWidth"] = '64';
    addDataPointStyle["imageHeight"] = '64';
    addDataPointStyle["fontColor"] = '#00A3D9';
    //默认线条样式
    edgeStyle = graph.getStylesheet().getDefaultEdgeStyle();
    edgeStyle["rounded"] = true;
    edgeStyle["shape"] = "connector";
    edgeStyle["strokeWidth"] = 1;
    edgeStyle["strokeColor"] = "#2C9C39";


    MQEdgeStyle = mxUtils.clone(edgeStyle);
    MQEdgeStyle["edgeStyle"] = 'elbowEdgeStyle';
    MQEdgeStyle["startArrow"] = 'oval';
    //MQEdgeStyle["endArrow"] = 'block';
    MQEdgeStyle["endArrow"] = 'oval';
    MQEdgeStyle["startFill"] = 0;
    MQEdgeStyle["endFill"] = 0;
    MQEdgeStyle["entryX"] = 0;
    MQEdgeStyle["entryY"] = 0.5;
    MQEdgeStyle["exitX"] = 1;
    MQEdgeStyle["exitY"] = 0.5;
    graph.getStylesheet().putCellStyle("MQEdgeStyle", MQEdgeStyle);
    ```
    ## 画图
    ```
     // Gets the default parent for inserting new cells. This
        // is normally the first child of the root (ie. layer 0).
        var parent = graph.getDefaultParent();
        //Adds cells to the model in a single step
        graph.getModel().beginUpdate();
        try {
            var v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);
            var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
            var e1 = graph.insertEdge(parent, null, '', v1, v2);
             //画方块 默认情况下
            graph.insertVertex(parent, null, '矩形', 50, 50, 150, 150);
           // 画方块 圆角矩形
            shape=rounded 定义圆角  arcSize=10 定义圆角弧度
            graph.insertVertex(parent, null, '圆角矩形', 300, 50, 150, 150, "rounded=true;perimeter=ellipsePerimeter;arcSize=20;");
            //画椭圆
            shape=elipse 定义椭圆  perimeter=ellipsePerimeter 让连线的箭头或起点触到边缘
            graph.insertVertex(parent, null, '椭圆', 550, 50, 150, 150, "shape=ellipse;perimeter=ellipsePerimeter;");
            //画三角形
            shape=triangl 定义三角形  perimeter=ellipsePerimeter 让连线的箭头或起点触到边缘 direction=south 让三角形倒立
            graph.insertVertex(parent, null, '三角形', 800, 50, 150, 150, "shape=triangle;perimeter=ellipsePerimeter;direction=south;");
            //画菱形
            shape=rhombus 定义菱形
            graph.insertVertex(parent, null, '三角形', 1050, 50, 150, 150, "shape=rhombus;perimeter=ellipsePerimeter;");
            //画柱形
            shape=cylinder 定义柱形
            graph.insertVertex(parent, null, '柱形', 1300, 50, 150, 150, "shape=cylinder;perimeter=ellipsePerimeter;");
            //画人
            shape=actor 定义演员
            graph.insertVertex(parent, null, '演员', 50, 300, 150, 150, "shape=actor;perimeter=ellipsePerimeter;");
            //画云
            graph.insertVertex(parent, null, '云', 300, 300, 150, 150, "shape=cloud;perimeter=ellipsePerimeter;");
          //  矩形默认情况下
            graph.insertVertex(parent, null, '矩形', 550, 300, 150, 150, "shape=rectangle;perimeter=ellipsePerimeter;");
           // 泳道
            graph.insertVertex(parent, null, '泳道', 800, 300, 150, 150, "shape=swimlane;perimeter=ellipsePerimeter;");
           // 双圆
            graph.insertVertex(parent, null, '双圆', 1050, 300, 150, 150, "shape=doubleEllipse;perimeter=ellipsePerimeter;");
           //  六边形
            graph.insertVertex(parent, null, '六边形', 1300, 300, 150, 150, "shape=hexagon;perimeter=ellipsePerimeter;");
        }finally {
            // Updates the display
            graph.getModel().endUpdate();
        }
    ```
    ## 导出XML
    ```
    //转XML格式输出
    var encoder = new mxCodec();
    var node = encoder.encode(graph.getModel());
    console.log(mxUtils.getXml(node));
    扩充版(解决浏览器兼容问题)
    //获取当前编辑指标的名称、xml
    getGraphXML : function() {
        //生成graph视图的xml格式文件
        var getGraphXml = function(graph) {
            var encoder = new mxCodec();
            var code = encoder.encode(graph);
            return code;
        }
        var model = graph.getModel();
        if (model) {
            var graphXmlObj = getGraphXml(model);
            if (judgeIsIe8()) {
                //console.log("ie8");
                graphXmlForIe = graphXmlObj.xml; //<>转义得用第三变量传递一下,不能用var graphXml
                return graphXmlForIe;
            } else {
                var oSerializer = new XMLSerializer();
                var report_xmlStr = oSerializer.serializeToString(graphXmlObj);
                graphXmlOther = report_xmlStr;
                return graphXmlOther;
            }
        }
    }
    ```
    ## 回显XML
    ```
    // XML回显到编辑区(渲染画布)
    var xmlFile = '<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="2" value="Hello," vertex="1" parent="1"><mxGeometry x="20" y="20" width="80" height="30" as="geometry"/></mxCell><mxCell id="3" value="World!" vertex="1" parent="1"><mxGeometry x="200" y="150" width="80" height="30" as="geometry"/></mxCell><mxCell id="4" value="" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="矩形" vertex="1" parent="1"><mxGeometry x="50" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="6" value="圆角矩形" style="rounded=true;perimeter=ellipsePerimeter;arcSize=20;" vertex="1" parent="1"><mxGeometry x="300" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="7" value="椭圆" style="shape=ellipse;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="550" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="8" value="三角形" style="shape=triangle;perimeter=ellipsePerimeter;direction=south;" vertex="1" parent="1"><mxGeometry x="800" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="9" value="三角形" style="shape=rhombus;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="1050" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="10" value="柱形" style="shape=cylinder;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="1300" y="50" width="150" height="150" as="geometry"/></mxCell><mxCell id="11" value="演员" style="shape=actor;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="50" y="300" width="150" height="150" as="geometry"/></mxCell><mxCell id="12" value="云" style="shape=cloud;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="300" y="300" width="150" height="150" as="geometry"/></mxCell><mxCell id="13" value="矩形" style="shape=rectangle;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="550" y="300" width="150" height="150" as="geometry"/></mxCell><mxCell id="14" value="泳道" style="shape=swimlane;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="800" y="300" width="150" height="150" as="geometry"/></mxCell><mxCell id="15" value="双圆" style="shape=doubleEllipse;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="1050" y="300" width="150" height="150" as="geometry"/></mxCell><mxCell id="16" value="六边形" style="shape=hexagon;perimeter=ellipsePerimeter;" vertex="1" parent="1"><mxGeometry x="1300" y="300" width="150" height="150" as="geometry"/></mxCell></root></mxGraphModel>';
    var doc = mxUtils.parseXml(xmlFile),
    dec = new mxCodec(doc);
    dec.decode(doc.documentElement, graph.getModel());
    扩充版(解决浏览器兼容问题)
    //解析xml字符串并转化成graph视图
    createXmlDom : function(str) {
        if (document.all) { //判断浏览器是否是IE
            var xmlDom = new ActiveXObject("Microsoft.XMLDOM");
            xmlDom.loadXML(str);
            return xmlDom;
        } else {
            return (new DOMParser()).parseFromString(str, "text/xml");
        }
    },
    readGraphXML : function(xmlstr, graph) {
        if (xmlstr) {
            graph.getModel().beginUpdate();
            try {
                var xmlDoc = this.createXmlDom(xmlstr);
                var node = xmlDoc.documentElement;
                var dec = new mxCodec(node.ownerDocument);
                dec.decode(node, graph.getModel());
                console.log(dec);
            } finally {
                graph.getModel().endUpdate();
            }
        }
    }
    ```
    ##右键菜单
    ```
    graph.popupMenuHandler.autoExpand = true;
    graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {
        if(cell != null) {
            menu.addItem('添加节点', null, function() {
                changeTaskType(cell.id, "")
            });
           //二级菜单
            var conn_pos = menu.addItem('连接位置', null, function() {});
            menu.addItem('左右', null, function() {}, conn_pos);
            menu.addItem('三面', null, function() {}, conn_pos);
            menu.addItem('四面', null, function() {}, conn_pos);
            menu.addItem('设置', null, function() {});
            menu.addItem('详细信息', null, function() {});
            menu.addItem('远程更新版本', null, function() {});
            menu.addItem('远程控制(新窗口)', null, function() {
                window.open('index.html?serverUUID=' + cell.id + '&serverName=' + encodeURI(cell.value));
            });
            menu.addItem('查看目录', null, function() {
                viewDataDirectoryWin.show(data.UUID, data.subOrSup);
            });
            menu.addItem('查看话题', null, function() {
                viewTopicWin.show(data.UUID, data.subOrSup);
            });
        }
    }
    ```
    ## 组合型shape配置
    ```
    // Helper method to mark parts with constituent=1 in the style
    //在style里面用constituent=1标记部件
    graph.isPart = function(cell) {
        var state = this.view.getState(cell);
        var style = (state != null) ? state.style : this.getCellStyle(cell);
        return style['constituent'] == '1';
    };
    // 重定义组合型图形的选中事件,不能选中里面的子部件
    graph.selectCellForEvent = function(cell) {
        if(this.isPart(cell)) {
            cell = this.model.getParent(cell);
        }
        mxGraph.prototype.selectCellForEvent.apply(this, arguments);
    };
    ```
    ## 绘制组合图形
    ```$xslt
    var parent = graph.getDefaultParent();
    // Adds cells to the model in a single step
    graph.getModel().beginUpdate();
    try {
        var taskWrap = graph.insertVertex(parent, "Taskid", 'Looped\nSub-Process', 200, 200, 200, 100, 'whiteSpace=wrap;');
        //constituent=1;表示节点作为一个part存在的
        var taskTypeCell = graph.insertVertex(taskWrap, null, 'dfdfgd', 0.5, 1, 30, 30, 'shape=ellipse;fontSize=9;constituent=1;resizable=0;;outlineConnect=0;');
        taskTypeCell.type = "taskType";
        taskTypeCell.expr = "ffffffffffffffffff";
        taskTypeCell.geometry.relative = true;
        taskTypeCell.geometry.offset = new mxPoint(-15, -35);
        taskTypeCell.connectable = false;
        taskTypeCell.value = "jshdjhsdbvf";

    } finally {
        // Updates the display
        graph.getModel().endUpdate();
    }
    ```
    ##边缘事件
    ```
    参考/examples/boundary.html
    ```
    ## 设置style样式[graph.setCellStyles(mxConstant.xxxx,设置的val, [cells])]
    ```
    var changeTaskType = function(cellId, Task) {
        var endFill = "";
        var graph = myGraphInfo.graph;
        switch(examine) {
            case "EXAMINE_ADOPT": //审批通过 
                endFill = 1;
                break;
            case "EXAMINE_REJECT": //审批拒绝 case :
            case "EXAMINE_CONNECT":
            case "EXAMINE_NOT": //未审批 case :
            case "EXAMINING": //待审批 
                endFill = 0;
                break;
        }
        var thisCell = graph.getModel().getCell(uuid);
        var thisEdge = thisCell.edges[0];
        graph.setCellStyles("shape", "", [cell]);
        graph.refresh(thisEdge);//刷新改细胞
    }
    ```
    ##限制最大最小宽度
    ```aidl
    graph.cellResized = function (cell, rect, ignoreRelative, recurse) {
        var flagClass = "mxCol_" + cell.id;
        if (rect.width < 40) {
            rect.width = 40;
            $("." + flagClass).width("0px");
        } else if (rect.width > 800) {
            rect.width = 800;
            $("." + flagClass).width((800 - 43) + "px");
        } else {
            $("." + flagClass).width((rect.width - 43) + "px");
        }
        return mxGraph.prototype.cellResized.apply(this, arguments);

    };
    ```
    ##关于是否可连接设置
    ```aidl
    //目标可连接性设置
    graph.isValidTarget = function (cell) {
        if (cell) {
            if (cell.type) {
                if (cell.type == "table" || cell.type == "gather") {
                  //  designMxgraph.setTabConnectable(true);
                    return true;
                }
            }
        }
    }
    //连线可行性验证
    graph.validateEdge = function (edge, source, target) {
        if (!edge) {
          //  designMxgraph.setTabConnectable(false);
        } else {
            return true;
        }
    }
    ```
    ##Drop拖动目标验证
    ```aidl
    //Drop拖动目标验证
    //cell:target
    //cells:source  一般用于group
    graph.isValidDropTarget = function (cell, cells, evt) {
        if (cell) {
            if (cells.length == 1) {
                source = cells[0];
                if (cell.type == "group" && cells[0].type != "group" && cells[0].type != "gather") {
                    if (source.edges) {
                        for (var i = 0; i < source.edges.length; i++) {
                            if (source.edges[i].id.indexOf("flowline_") != -1) {//针对流向线
                                if (source.edges[i].target.id != source.id) {
                                    return false;//一旦线的目标终点不是source本身,就不可以拖进去
                                } else if (source.edges[i].source.id == cell.id) {
                                    return false;
                                } else {
                                    continue;
                                }
                            }
                        }
                    }
                    return true;
                }
            }
        }
    }
    ```
    ##获取所有画布内得图形对象
    ```aidl
    graph.getChildCells()---包括连线
    graph.getChildVertices()---不包括连线
    ```
    ##设置细胞可连接性
    ```aidl
      cell.setConnectable(bool);
    ```
    ##泳道布局
    ```aidl
    //配置泳道里的细胞自动布局,泳道布局
    editor.layoutSwimlanes = true;
    editor.createSwimlaneLayout = function () {
        var layout = new mxStackLayout(this.graph, false);
        layout.fill = true;
        layout.resizeParent = true;
        // Overrides the function to always return true
        layout.isVertexMovable = function (cell) {
            return true;
        };
        return layout;
    };
    ```
    ##添加A细胞到B细胞的连线
    ```aidl
    var newLine = graph.insertEdge(parent, id, label, startCell, endCell, 'dashed=1;' +
    'startArrow=oval;endArrow=oval;sourcePerimeterSpacing=4;startFill=1;endFill=1;strokeColor=green;' +
    'strokeWidth=1;fontSize=12;edgeStyle=sideToSideEdgeStyle;');
    dashed----
    startArrow----线头起始形状   有oval(圆形),classic(箭头),none(无)
    endArrow-----线头结束形状
    startFill、endFill-----是否填充颜色
    edgeStyle----线条的类型
    entryX,entryY---结尾的落点坐标
    exitX,exitY----开始的坐标
    sourcePerimeterSpacing---留白
    ```

    阅读全文>>

作者:黄小妹22分类:【web浏览(2794评论(2

2018-11-16 11:24:59

clickhouse,mysql,oracle查询表指定记录数量

    1. 那么Oracle中有limit吗,答案是没有。oracle中可以通过 rownumber 
    Oracle使用rownum的关键字来实现这种查询,首先我们假设有一个地域信息表area123,其表结构如下图所示:

    2.mysql的imit方法:

    MYSQL 中 LIMIT 用法

    mapper文件中的sql:

    --------------------------------------------------------------------------------------------

      (在实体类中定义的属性)

      start:从第几条记录开始。

      size:读取几条记录。 

    select id="findAllUsers" parameterType="Map" resultType="entity.IUser">
    
            select * from newusers
            <where>
                user_name like #{user_name,jdbcType=VARCHAR}
            </where>
            limit #{start,jdbcType=INTEGER},#{size,jdbcType=INTEGER}
    </select>

    ------------------------------------------------------------------

    前端将page:第几页

       rows(size):每页多少条

       这两个参数,传到后台。

        通过这两个参数,可以算出start   计算方法 start=size(page-1)

       然后将size和start放入map中

    简单代码示例   

    Map map=new HashMap();
    
       map.put("start",start);
    
       map.put("size",size);
    
       不要忘记将start和size转换成Integer.
    
       然后将map当作参数传入dao的接口。

     

    注:

    limit是mysql的语法
    select * from table limit m,n
    其中m是指记录开始的index,从0开始,表示第一条记录
    n是指从第m+1条开始,取n条。
    select * from tablename limit 2,4
    即取出第3条至第6条,4条记录

    3. clickhouse 使用limit方法

    具体用法如下:

    阅读全文>>

作者:miki分类:【数据库浏览(19365评论(6

2018-11-12 16:49:58

关于社区未来规划及发展

    现在进入整体布局第二期,工程整体布局已经完成大半,现在欠缺的就是两部分,一个是对全部博客做一个归类的首页,

       类似于csdn社区系统,另一个则是对博客系统的后台管理,整体联系有点乱。

    1.关于系统的bug,如果刚导入数据的时候,有些类型为null,则无法查到数据。null和“”

       的区别相信大家都略知其一了。

    2.关于ajax的使用,这个东西可以说是难为了我好久,有句话形容我的心情再好不过了,如同鸡肋 ,食之无味,弃之可惜。

       我不希望每次都刷新全局,异步提交。但是学不会。这个暑假我要认真学习一下

    3.项目无关性虽然不错,客户体验也还说的过去,但是管理员对整体的掌控和把握欠缺太多,这个很致命

    4.留给我的时间不多了,所以我希望可以把它完善的尽善尽美。接下来,我还要再做一个管理系统,

       和一个商城项目。然后学习一下,ajax和数据库管理。

     5.还有maven以及springMVC这两个框架。

     

     

    阅读全文>>

作者:miki分类:【社区浏览(354评论(0

2018-09-27 14:50:09

代码高亮测试第三单

    String from=props.getProperty("from");
            String title=props.getProperty("subject");
            String to = Tuser.getEmail();
            String content = MessageFormat.format(props.getProperty("content"), topic.getId(),topic.getTitle());		//内容
            
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO,to);
            
            //邮件标题
            message.setSubject(title);
            
            //文本部分
            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setContent("<img src='cid:myimg'/><div style='width:1193px; height:100px;border:1px solid red'>"+content+"</div>", "text/html;charset=UTF-8");
            //内嵌图片部分
            MimeBodyPart imagePart = new MimeBodyPart();
            imagePart.setDataHandler(new DataHandler(new FileDataSource("D:/soft/logo.jpg")));//图片路径
            imagePart.setContentID("myimg");
            //图文整合,关联关系
            MimeMultipart mmp1 = new MimeMultipart();
            mmp1.addBodyPart(textPart);
            mmp1.addBodyPart(imagePart);
            mmp1.setSubType("related");
            MimeBodyPart textImagePart = new MimeBodyPart();
            textImagePart.setContent(mmp1);
            //附件部分
            MimeBodyPart attachmentPart = new MimeBodyPart();
            DataHandler dh = new DataHandler(new FileDataSource("D:/soft/freemarker/file/sharehoo社区福利.txt"));//文件路径
            String fileName = dh.getName();
            attachmentPart.setDataHandler(dh);
            attachmentPart.setFileName(fileName);
            //图文和附件整合,复杂关系
            MimeMultipart mmp2 = new MimeMultipart();
            mmp2.addBodyPart(textImagePart);
            mmp2.addBodyPart(attachmentPart);
            mmp2.setSubType("mixed");
            //将以上内容添加到邮件的内容中并确认
            message.setContent(mmp2);
            message.saveChanges();
            //发送邮件
            Transport.send(message);

     

    阅读全文>>

作者:miki分类:【代码高亮浏览(318评论(1

2018-07-19 11:29:55

关于社区论坛版块的置顶,精华,撤销功能说明

    wink1.对于已置顶的帖子设置两个操作:撤销,精华

          之所以这样设置的原因,是撤销功能将帖子的精华和置顶全部设为0,这样的话,帖子就会被降级,降级之后可以执行删除操作或者置顶操作。但是对置顶帖不能执行删除操作。只有将其降级之后,才能实现删除功能

     smiley2.同理,对于普通帖的列表操作选项,有置顶和删除操作,帖子的优先筛选条件是通过访问量多少对其采取置顶操作,访问量,回复量多的可以置顶,置顶之后,如果是优质帖子,可以对其采取精华操作。当然,普通帖才有删除的操作,这就是权限的不同。

    smiley3.附图看一看,啥啊也不说了,一言不合就上图:

     

    阅读全文>>

作者:miki分类:【java浏览(1005评论(3

2017-06-21 08:11:09

a 标签中调用js函数的几种方法介绍及分析

     我们常用的在a标签中有点击事件:
    1. a href="JavaScript:js_method();"

    这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且javascript:协议作为a的href属性的时候不仅会导致不必要的触发window.onbeforeunload事件,在IE里面更会使gif动画图片停止播放。W3C标准不推荐在href里面执行javascript语句

    2. a href="javascript:void(0);" onclick="js_method()"

    这种方法是很多网站最常用的方法,也是最周全的方法,onclick方法负责执行js函数,而void是一个操作符,void(0)返回undefined,地址不发生跳转。而且这种方法不会像第一种方法一样直接将js方法暴露在浏览器的状态栏。

    3.a href="javascript:;" onclick="js_method()"

    这种方法跟跟2种类似,区别只是执行了一条空的js代码。

    4.a href="#" onclick="js_method()"

    这种方法也是网上很常见的代码,#是标签内置的一个方法,代表top的作用。所以用这种方法点击后网页后返回到页面的最顶端。

    5.a href="#" onclick="js_method();return false;"

    这种方法点击执行了js函数后return false,页面不发生跳转,执行后还是在页面的当前位置。

    我看了下taobao的主页,他们采用的是第2种方法,而alibaba的主页是采用的第1种方法,和我们的区别是每个href里的javascript方法都用try、catch包围。

    综合上述,在a中调用js函数最适当的方法推荐使用:
    a href="javascript:void(0);" onclick="js_method()"
    a href="javascript:;" onclick="js_method()"
    a href="#" onclick="js_method();return false;"






    js的方法中 字符串型要加引号

    阅读全文>>

作者:miki分类:【前端浏览(539评论(5

2017-06-20 17:09:17