文档章节

spring mvc 图片上传,图片压缩、跨域解决、 按天生成目录 ,删除,限制为图片代码等相关配置

猪刚烈
 猪刚烈
发布于 2014/08/16 09:35
字数 4814
阅读 101
收藏 0
spring mvc 图片上传,跨域解决 按天生成目录 ,删除,限制为图片代码,等相关配置

fs.root=data/
#fs.root=/home/dev/fs/
#fs.root=D:/fs/
#fs.domains=182=http://172.16.100.182:18080,localhost=http://localhost:8080


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-lazy-init="false" default-autowire="no">

<!-- 图片上传配制 -->
<bean id="fileUpload" class="com.xyt.gsm.utils.FileUpload"> 
 <!-- 是否启用temp文件目录  -->
 <property name="UploadTemp" value="false"/>  
 <!-- 是否相对路径 -->
 <property name="RELATIVE_SAVE" value="true"/>
 <!-- 大小限制 -->
 <property name="photoSize" value="2097152"/>
 <property name="otherSize" value="100000000"/> 
 <!-- 文件真实存放目录  远程服务器存放路径 /gsm/fs/-->
 <!-- <property name="realFilePath" value="smb://gsm:gsm1234@172.16.100.182/home/"/> -->
 <!-- 文件真实存放目录  本地服务器存入-->
 <property name="realFilePath" value="${fs.root}"/> 
 <!-- 文件临时目录 -->
 <!--  <property name="UPLOADDIR" value="fs/temp/"/> -->
</bean>
 
<bean id="fileUploadServiceImp" class="com.xyt.gsm.service.fs.imp.FileUploadServiceImp">
 	<property name="productPhotoService" ref="productPhotoServiceImp"></property>
 	<property name="dictService" ref="dictService"></property>
</bean>
 <!-- 绝对路径要在tomcat 做以下映射 -->
<!--  <Context path="/fs" docBase="d:/fs" /> -->
</beans>

package com.xyt.gsm.utils;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.xyt.gsm.constant.Fs;
import com.xyt.gsm.constant.Fs.UpoladStatus;

/**
 * 图片上传
 * 
 * @author liangrui
 * 
 *         UploadTemp 如果为false 临时所在目录被实际目录替换,如果为true 需要再做一次拷贝
 * 
 */
public class FileUpload
{

	// 文件信息
	/** 是否启用临时文件目录 */
	private static boolean UploadTemp = false;
	/** 文件上传相对 路径 */
	private static String RELATIVEPATH = "relativePath";
	/** 文件上传绝对 路径目录 */
	private static String ABSOLUTEPATH = "absolutePath";
	/** 实际文件所在目录 */
	private static String realFilePath = "fs/";
	/** 文件上传临时所在目录 */
	public static String UPLOADDIR = "fs/temp/";
	/** 图片上传大小限制 */
	public static Integer photoSize = 2097152;//
	/** 末知类型文件上大小限制 */
	private static Integer otherSize = 100000000;
	/** 是否存放相对路径 **/
	private static boolean RELATIVE_SAVE = false;

	// fied
	public void setUploadTemp(boolean uploadTemp)
	{
		UploadTemp = uploadTemp;
	}

	public void setPhotoSize(Integer photoSize)
	{
		FileUpload.photoSize = photoSize;
	}

	public void setOtherSize(Integer otherSize)
	{
		FileUpload.otherSize = otherSize;
	}

	public void setRealFilePath(String realFilePath)
	{
		if (UploadTemp == false)
			UPLOADDIR = realFilePath;
		FileUpload.realFilePath = realFilePath;
	}

	public void setUPLOADDIR(String uPLOADDIR)
	{
		if (UploadTemp == false)
			UPLOADDIR = realFilePath;
		else
			UPLOADDIR = uPLOADDIR;

	}

	public static void setRELATIVE_SAVE(boolean rELATIVE_SAVE)
	{
		RELATIVE_SAVE = rELATIVE_SAVE;
	}

	

	public static String getRealFilePath() {
		return realFilePath;
	}

	/**
	 * 
	 * @param request
	 *            上传文件的请求
	 * @param suffuxDir
	 *            目录分配
	 * @param type
	 *            上传文件的类型
	 * @param cutPhoto
	 *            是否切图
	 * @return 上传后的文件路径
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	// ===============================================================================================
	// -----解析request 上传 返回上传后的文件把在路径
	// ================================================================================================

	public static List<String> fileUpload(HttpServletRequest request, String suffuxDir, String type) throws IllegalStateException, IOException
	{

		return fileUpload(request, suffuxDir, type, false);
	}

	public static List<String> fileUpload(HttpServletRequest request, String suffuxDir, String type, Boolean cutPhoto) throws IllegalStateException, IOException
	{
		// 上传文件的解析器
		CommonsMultipartResolver mutiparRe = new CommonsMultipartResolver();
		if (mutiparRe.isMultipart(request))
		{// 如果是文件类型的请求

			List<String> fileInfo = new ArrayList<String>();
			MultipartHttpServletRequest mhr = (MultipartHttpServletRequest) request;

			// 按月分目录
			DateFormat df = new SimpleDateFormat("yyyyMM");
			String month = df.format(new Date());

			// 获取路径
			String uploadDir = "";
			if (RELATIVE_SAVE)
			{
				uploadDir += (request.getSession().getServletContext().getRealPath("/")+FileUpload.realFilePath);
			}else
			{
				uploadDir += FileUpload.UPLOADDIR ;
			}

			uploadDir+=(suffuxDir + month + "/");
			
			// 如果目录不存在,创建一个目录
			if (!new File(uploadDir).exists())
			{
				File dir = new File(uploadDir);
				dir.mkdirs();
			}

			// 跌带文件名称
			Iterator<String> it = mhr.getFileNames();
			while (it.hasNext())
			{
				final MultipartFile mf = mhr.getFile(it.next()); // 获取一个文件
				if (mf != null)
				{
					// 如果是图片类型文件上传 限制大小和类型
					if (type.equals(Fs.FileUpLoadType.PHOTO))
					{
						if (!checkingPhoto(mf))
						{
							fileInfo.add(UpoladStatus.类型无效或图片过大.toString());
							continue;
						}
					} else
					{
						if (mf.getSize() > otherSize)
						{
							fileInfo.add(UpoladStatus.类型无效或图片过大.toString());
							continue;
						}
					}
					// 其它上传类型 另外做限制判断

					String resFileName = mf.getOriginalFilename();// 获取原文件名
					// 取得文件名和后辍
					String suffix = "";
					if (resFileName.indexOf(".") != -1)
					{
						suffix = resFileName.substring(resFileName.lastIndexOf(".") + 1);
					}

					String dian = ".";
					if ("".equals(suffix))
						dian = "";

					// 保存的文件名
					String uuid = rename();
					String fileName = uuid + dian + suffix;
					File outFile = new File(uploadDir + fileName); // 路径加文件名 +"/"
					mf.transferTo(outFile); // 保存到

					if (cutPhoto)
					{
						final String dirAndUuid = uploadDir + uuid;
						final String dians = dian;
						final String suffixs = suffix;

						new Thread(new Runnable()
						{
							public void run()
							{
								try
								{
									copyImgSpecification(mf.getInputStream(), dirAndUuid, dians, suffixs);
								} catch (IOException e)
								{
									e.printStackTrace();
								}
							}
						}).start();
					}

					if (RELATIVE_SAVE)
					{// 相对路径目录
						fileInfo.add("/" + FileUpload.realFilePath + suffuxDir + month + "/" + fileName);// 文件路径
					} else
					{// 绝对路径目录
						fileInfo.add("/" + suffuxDir + month + "/" + fileName);// 文件路径
					}
				}
			}
			return fileInfo;
		}
		return null;
	}

	// ------------------------------------------------------------------------------------------------------------
	// 复制图片 改变不同大小的规格
	// ------------------------------------------------------------------------------------------------------------
	public static void copyImgSpecification(InputStream is, String DirAnduuid, String dian, String suffix) throws IOException
	{

		Image img = ImageIO.read(is);
		FileOutputStream fos = null;
		for (int i = 0; i < Fs.FileUpLoadType.changePhotoSize.length; i++)
		{
			int w = Fs.FileUpLoadType.changePhotoSize[i];
			// int h=imgSize[i];
			String allPath = DirAnduuid + "_" + w + "x" + w + dian + suffix;
			if ("".equals(suffix))
			{
				suffix = "jpg";
			}

			fos = new FileOutputStream(allPath); // 输出到文件流
			chagePhotoSize(allPath, img, fos, suffix, w, w);
		}

		img.flush();
		// if(fos!=null){fos.close();}
	}

	// ----------------------------------------------------------------
	// 检查图片类型上传和图片大小
	// ----------------------------------------------------------------
	public static boolean checkingPhoto(MultipartFile mf) throws IOException
	{
		if (!isImage(mf.getInputStream()))
		{ // 判断是否为图片
			// fileInfo.add("请上传有效图片文件");//提示信息
			return false;
		}
		if (mf.getSize() > photoSize)
		{
			// fileInfo.add("图片大于"+(new
			// DecimalFormat("####.##").format(((double)photoSize)/1024/1024))+"MB上传失败");//提示信息
			return false;
		}
		return true;
	}

	// 只生成uuid 和后辍分开,切图时需要
	public static String rename(/* String name */)
	{
		// 时分秒
		/*
		 * Long now = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()));
		 * Long random = (long) (Math.random() * now); String fileName = now + "" + random;
		 */
		// 不能设置种子值,应采用默认的方式(系统时间戳 )
		final Random rd = new Random();
		final Long random = rd.nextLong();
		String num = String.valueOf(random);
		// 限制5个字符
		int limit = 5;
		if (num.length() > limit)
		{
			num = num.substring(0, limit);
		}
		// uuid生成文件名
		UUID uuid = UUID.randomUUID();
		// 加上 5位随机数
		String uustr = uuid.toString().replace("-", "") + num;

		/*
		 * if (name.indexOf(".") != -1) { uustr += name.substring(name.lastIndexOf(".")); } else {
		 * return uustr; }
		 */

		return uustr;
	}

	// 更改文件名称
	public static String rename(String name)
	{
		// 时分秒
		/*
		 * Long now = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()));
		 * Long random = (long) (Math.random() * now); String fileName = now + "" + random;
		 */
		// 不能设置种子值,应采用默认的方式(系统时间戳 )
		final Random rd = new Random();
		final Long random = rd.nextLong();
		String num = String.valueOf(random);
		// 限制5个字符
		int limit = 5;
		if (num.length() > limit)
		{
			num = num.substring(0, limit);
		}
		// uuid生成文件名
		UUID uuid = UUID.randomUUID();
		// 加上 5位随机数
		String uustr = uuid.toString().replace("-", "") + num;

		if (name.indexOf(".") != -1)
		{
			uustr += name.substring(name.lastIndexOf("."));
		} else
		{
			return uustr;
		}

		return uustr;
	}

	// ===============================================================================================
	// -----判断是否为图片
	// ================================================================================================
	public static boolean isImage(File imageFile)
	{
		if (!imageFile.exists())
		{
			return false;
		}
		Image img = null;
		try
		{
			img = ImageIO.read(imageFile);
			if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0)
			{
				return false;
			}
			return true;
		} catch (Exception e)
		{
			return false;
		} finally
		{
			img = null;
		}
	}

	public static boolean isImage(InputStream imageFile)
	{
		Image img = null;
		try
		{
			img = ImageIO.read(imageFile);
			if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0)
			{
				return false;
			}
			return true;
		} catch (Exception e)
		{
			return false;
		} finally
		{
			img = null;
		}
	}

	// ===============================================================================================
	// -----删除
	// ================================================================================================
	public static int deleteFile(HttpServletRequest request, boolean cutPhoto, String... path) throws MalformedURLException, SmbException
	{
		// List<String> delList=new ArrayList<String>();//记录成功删除的文件名
		int delcount = 0;
		// 远程删除
		if (realFilePath.length() > 3 && realFilePath.substring(0, 3).equals("smb"))
		{
			for (String pa : path)
			{
				SmbFile remoteFile = new SmbFile(pa);
				if (remoteFile.exists())
				{
					remoteFile.delete();
					delcount++;
					// 获取文件名
					// delList.add(p.substring(p.lastIndexOf("/")+1));
				}
			}
		} else
		{

			// 获取当前根目录 本地删除
			String proPath = "";
			if (RELATIVE_SAVE)
			{
				proPath += request.getSession().getServletContext().getRealPath("/");
			} else
			{
				proPath += FileUpload.UPLOADDIR;
			}

			for (String p : path)
			{
				File file = new File(proPath + p);
				if (file.exists())
				{
					file.delete();
					delcount++;
					// 获取文件名
					// delList.add(p.substring(p.lastIndexOf("/")+1));
				
				// 删除小图
				if (cutPhoto)
				{
					Integer[] xPhotoArr = Fs.FileUpLoadType.changePhotoSize;
					for (Integer imgSize : xPhotoArr)
					{
						String suffixs ="";
						String prefix=p;
						
						if(p.indexOf(".")!=-1){
						 suffixs = p.substring(p.lastIndexOf("."));
						 prefix = p.substring(0, p.lastIndexOf("."));
						}
						String newP = prefix + "_" + imgSize + "x" + imgSize + suffixs;
						File filex = new File(proPath + newP);
						if (filex.exists())
						{
							filex.delete();
							delcount++;
						}

					}
				}
				}
			}
		}
		return delcount;
	}

	/**
	 * 
	 * @param request
	 * @param path
	 *            临时图片目录
	 * @param prefixDir
	 *            前辍目录 比如 "商品ID目录,商品图片目录"
	 * @return
	 * @throws IOException
	 */
	// -------------------------------------------------------------------------------------------
	// 把temp的图片文件拷贝到 真实存放文件目录/日期文件夹中
	// -----------------------------------------------------------------------------------------------
	public static String tempToupdateImgPath(HttpServletRequest request, String path, String... prefixDir) throws IOException
	{
		// 主目录
		String rootDir = request.getSession().getServletContext().getRealPath("/");
		File file = new File(rootDir + path);// 需要移动的图片

		String realPath = "";// 实际图片地址
		String dbPath = "";// 保存数据库
		String fileName = path.substring(path.lastIndexOf("/") + 1);// 文件名
		// 加上前辍目录
		StringBuffer appendDir = new StringBuffer();
		for (String zdir : prefixDir)
		{
			appendDir.append(zdir + "/");
		}

		// smb://username:password@192.168.0.77
		// 如果是smb远程 上传远程服务器
		if (realFilePath.length() > 3 && realFilePath.substring(0, 3).equals("smb"))
		{
			dbPath = fileToRemoto(file, fileName, appendDir.toString());
		} else
		{
			// 上传到本地服务器
			dbPath = realFilePath + appendDir.toString() + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/";

			realPath = rootDir + dbPath;
			if (!new File(realPath).exists())
			{
				File dir = new File(realPath);
				dir.mkdirs();
			}

			file.renameTo(new File(realPath + fileName));
		}

		return "/" + dbPath + fileName;
	}

	// -------------------------------------------------------------------------------------------
	// 通用smb 传送文件到远程 配制路径 前三个字符为 smb开头
	// -----------------------------------------------------------------------------------------------
	private static String fileToRemoto(File file, String fileName, String prefixDir)
	{
		InputStream in = null;
		OutputStream out = null;
		String returnPath = null;
		try
		{
			// 获取流
			in = new BufferedInputStream(new FileInputStream(file));
			String dateDir = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/";
			SmbFile remoteFile = new SmbFile(realFilePath + dateDir);
			// ip+...
			String fixed = realFilePath.substring(realFilePath.indexOf('@') + 1);
			returnPath = fixed + prefixDir + dateDir + fileName;

			if (!remoteFile.exists())
			{
				remoteFile.mkdirs();

			}

			// 将远程的文件路径传入SmbFileOutputStream中 并用 缓冲流套接
			String inputFilePath = remoteFile + "/" + fileName;

			// System.out.println("remoteFile:  "+remoteFile);
			out = new BufferedOutputStream(new SmbFileOutputStream(inputFilePath));
			byte[] buffer = new byte[1024];
			while (in.read(buffer) != -1)
			{
				out.write(buffer);
				buffer = new byte[1024];
			}

		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		} finally
		{
			try
			{
				if (in != null)
				{
					in.close();
				}
				if (out != null)
				{
					out.close();
				}
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}

		return returnPath;
	}

	// ----------------------------------------------------------------------------------------
	// 改变图片大小
	// --------------------------------------------------------------------------------------
	private static void chagePhotoSize(final String path, Image src/* FileInputStream is */, FileOutputStream fos, final String format, int w, int h) throws IOException
	{

		try
		{
			int old_w = src.getWidth(null); // 得到源图宽
			int old_h = src.getHeight(null);
			int new_w = 0;
			int new_h = 0; // 得到源图长
			double w2 = (old_w * 1.00) / (w * 1.00);
			double h2 = (old_h * 1.00) / (h * 1.00);
			/**
			 * BufferedImage(,,) width - 所创建图像的宽度 height - 所创建图像的高度 imageType - 所创建图像的类型
			 */
			// 图片跟据长宽留白,成一个正方形图。
			BufferedImage oldpic;
			if (old_w > old_h)
			{
				// BufferedImage.TYPE_INT_RGB; //0-13
				oldpic = new BufferedImage(old_w, old_w, 1);
			} else
			{
				if (old_w < old_h)
				{
					oldpic = new BufferedImage(old_h, old_h, 1);
				} else
				{
					oldpic = new BufferedImage(old_w, old_h, 1);
				}
			}
			// 改变图片大小
			Graphics2D g = oldpic.createGraphics();
			g.setColor(Color.white);
			if (old_w > old_h)
			{
				/**
				 * x - 要填充矩形的 x 坐标。 y - 要填充矩形的 y 坐标。 width - 要填充矩形的宽度。 height - 要填充矩形的高度。
				 */
				g.fillRect(0, 0, old_w, old_w);

				/**
				 * img - 要绘制的指定图像。如果 img 为 null,则此方法不执行任何操作。 x - x 坐标。 y - y 坐标。 width - 矩形的宽度。
				 * height - 矩形的高度。 bgcolor - 在图像非透明部分下绘制的背景色。 observer - 当转换了更多图像时要通知的对象。
				 */
				g.drawImage(src, 0, (old_w - old_h) / 2, old_w, old_h, Color.white, null);
			} else
			{
				if (old_w < old_h)
				{
					g.fillRect(0, 0, old_h, old_h);
					g.drawImage(src, (old_h - old_w) / 2, 0, old_w, old_h, Color.white, null);

				} else
				{
					// g.fillRect(0,0,old_h,old_h);
					/**
					 * getScaledInstance() width - 将图像缩放到的宽度。 height - 将图像缩放到的高度。 hints -
					 * 指示用于图像重新取样的算法类型的标志。
					 */

					g.drawImage(src.getScaledInstance(old_w, old_h, Image.SCALE_SMOOTH), 0, 0, null);
				}
			}

			g.dispose();
			src = oldpic;

			// 原宽大于指定宽
			if (old_w > w)
				new_w = (int) Math.round(old_w / w2);
			else
				new_w = old_w;
			// 原高大于指定高
			if (old_h > h)
				new_h = (int) Math.round(old_h / h2);
			else
				new_h = old_h;

			BufferedImage tag = new BufferedImage(new_w, new_h, 4);
			tag.getGraphics().drawImage(src.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0, 0, null);

			ImageIO.write(tag, format, fos);
			tag.flush();

		} catch (IOException ex)
		{
			ex.printStackTrace();
		} finally
		{
			if (fos != null)
			{
				fos.close();
			}
		}

	}

	
	
	// ==========在服务端为用户保存图片上传信息================================================
	// private static final ThreadLocal<> threadLocal =new ThreadLocal<>();

}

package com.xyt.gsm.service.fs;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.xyt.gsm.bean.common.ResultBean;
import com.xyt.gsm.entity.mgr.User;

public interface FileUploadService
{

	String singleUpload(HttpServletRequest request, User user, String suffixDir, String type, Boolean cutPhoto) throws Exception;//

	List<?> MonyUpload(HttpServletRequest request, User user, String suffixDir);//

	int deleteFile(HttpServletRequest request, boolean cutPhoto, String... path);

	ResultBean deleteFileAnDb(HttpServletRequest request, String type, String id, boolean cutPhoto, String... path) throws Exception;

	String singleUpload(HttpServletRequest request, User user, String suffixDir, String type, Boolean cutPhoto, String merchantId) throws Exception;//

	List<String> singleUpload(HttpServletRequest request, String suffixDir, String type, Boolean cutPhoto, String merchantId) throws Exception;//

	void download();

}

package com.xyt.gsm.service.fs.imp;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xyt.gsm.bean.common.ResultBean;
import com.xyt.gsm.constant.CommonConstants;
import com.xyt.gsm.constant.DictConstants;
import com.xyt.gsm.constant.Fs;
import com.xyt.gsm.constant.Fs.UpoladStatus;
import com.xyt.gsm.entity.mgr.User;
import com.xyt.gsm.service.fs.FileUploadService;
import com.xyt.gsm.service.mgr.DictService;
import com.xyt.gsm.service.mgr.ProductPhotoService;
import com.xyt.gsm.utils.FileUpload;

public class FileUploadServiceImp implements FileUploadService
{
	protected Log log = LogFactory.getLog(this.getClass().getName());

	private ProductPhotoService productPhotoService;
	private DictService dictService;

	public void setProductPhotoService(ProductPhotoService productPhotoService)
	{
		this.productPhotoService = productPhotoService;
	}

	public void setDictService(DictService dictService)
	{
		this.dictService = dictService;
	}

	@Override
	public String singleUpload(HttpServletRequest request, User user, String suffixDir, String type, Boolean cutPhoto, String merchantId) throws Exception
	{

		String path = "";
		// 图片上传类型
		if (type.equals(Fs.FileUpLoadType.PHOTO))
		{

			if (user == null)
				return UpoladStatus.上传失败末知错误.toString();

			if ("".equals(merchantId) || merchantId == null)
			{
				// 运营人员操作 为 另一目录下
				if (CommonConstants.RoleType.OPERATER.equals(user.getUserType()))
				{
					//merchantId = Fs.FileDir.OPERATION_DIR;
					merchantId = "";
				} else
				{
					//获取供应商id
					merchantId = user.getMerchantId();
				}
			}

			// 判断数据字典里是否有该目录
			Map<String, String> photos = (Map<String, String>) dictService.getDictMap(DictConstants.ClsCode.FS);
			if (!matchDir(photos, suffixDir))
			{
				// suffixDir=FileDir.NOT_DIR;
				path=com.xyt.gsm.constant.Fs.UpoladStatus.文件目录未分配.name();

			} else
			{

				// 商家id /处理
				merchantId = manageSeparator(merchantId);
				// suffixdri
				suffixDir = manageSeparator(suffixDir);

				path = FileUpload.fileUpload(request, merchantId + suffixDir, Fs.FileUpLoadType.PHOTO, cutPhoto).get(0);

			}
		}

		return path;
	}

	@Override
	public String singleUpload(HttpServletRequest request, User user, String suffixDir, String type, Boolean cutPhoto) throws Exception
	{

		return singleUpload(request, user, suffixDir, type, cutPhoto, "");
	}

	@Override
	public List<?> MonyUpload(HttpServletRequest request, User user, String suffixDir)
	{
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int deleteFile(HttpServletRequest request, boolean cutPhoto, String... path)
	{

		return 0;
	}

	@Override
	public void download()
	{
		// TODO Auto-generated method stub

	}

	// 处理 / 前后有无/都可以
	public String manageSeparator(String str)
	{
		if (str == null)
			str = "";
		if (!"".equals(str))
		{// --05/01/
			// 不需要/
			if (str.startsWith("/"))
				str = str.substring(1);
			// 要加上/
			if (!str.endsWith("/"))
				str = str + "/";
		}

		return str;
	}

	// -------------------------------------------
	// 匹配前端的目录和数据库的目录是否一至,以防前后有无/问题
	// -------------------------------------------
	public boolean matchDir(Map<String, String> photos, String webDir)
	{
		if (photos == null)
			return false;
		if (webDir == null)
			webDir = "";

		boolean isMatch = false;

		if (photos.containsKey(webDir))
			return true;
		String temp = "";
		// 不匹配的情况下!再进行前后/处理匹配
		if (webDir.startsWith("/"))
		{
			// 前面 不要/
			temp = webDir.substring(1);
			if (photos.containsKey(temp))
				return true;

		}

		if (webDir.endsWith("/"))
		{
			// 后面 不要/
			temp = webDir.substring(0, webDir.length() - 1);
			if (photos.containsKey(temp))
				return true;
		}

		if (!webDir.endsWith("/"))
		{
			// 后面 要/
			temp = webDir + "/";
			if (photos.containsKey(temp))
				return true;
		}

		if (!webDir.startsWith("/"))
		{
			// 前面 要/
			temp = "/" + webDir;
			if (photos.containsKey(temp))
				return true;
		}

		// 前面 后面要/
		if (!webDir.startsWith("/") && !webDir.endsWith("/"))
		{
			temp = "/" + webDir + "/";
			if (photos.containsKey(temp))
				return true;
		}

		// 前面 后面 不要/
		if (webDir.startsWith("/") && webDir.endsWith("/"))
		{
			temp = webDir.substring(1, webDir.length() - 1);
			if (photos.containsKey(temp))
				return true;
		}

		return isMatch;
	}

	@Override
	public ResultBean deleteFileAnDb(HttpServletRequest request, String type, String id, boolean cutPhoto, String... path) throws Exception
	{

		ResultBean rb = new ResultBean();

		if (type.equals(Fs.FileUpLoadType.PHOTO))
		{
			// 删除数据
			int count = productPhotoService.deleteByProductId(id);
			if (count > 0)
			{
				// 删除图片
				int cou = FileUpload.deleteFile(request, cutPhoto, path);
				if (0 >= cou)
				{
					log.warn("id:" + id + ": 数据删除成功!图片删除失败");
				}

			} else
			{
				rb.setSuccess(false);
			}
		}
		return rb;

	}

	@Override
	public List<String> singleUpload(HttpServletRequest request,
			String suffixDir, String type, Boolean cutPhoto, String merchantId)
			throws Exception {

		List<String> paths = null;
		// 图片上传类型
		if (type.equals(Fs.FileUpLoadType.PHOTO))
		{

			// 判断数据字典里是否有该目录
			Map<String, String> photos = (Map<String, String>) dictService.getDictMap(DictConstants.ClsCode.FS);
			if (!matchDir(photos, suffixDir))
			{
				// suffixDir=FileDir.NOT_DIR;
				
//				path=com.xyt.gsm.constant.Fs.UpoladStatus.文件目录未分配.name();

			} else
			{

				// 商家id /处理
				merchantId = manageSeparator(merchantId);
				// suffixdri
				suffixDir = manageSeparator(suffixDir);

				paths = FileUpload.fileUpload(request, merchantId + suffixDir, Fs.FileUpLoadType.PHOTO, cutPhoto);

			}
		}

		return paths;
	}

}

package com.xyt.gsm.mvc.controller.fs;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.JsonObject;
import com.xyt.gsm.bean.common.ResultBean;
import com.xyt.gsm.bean.mgr.FileUploadVo;
import com.xyt.gsm.bean.mgr.LoginUser;
import com.xyt.gsm.constant.CommonConstants;
import com.xyt.gsm.constant.Fs;
import com.xyt.gsm.constant.Fs.UpoladStatus;
import com.xyt.gsm.entity.mgr.ProductPhoto;
import com.xyt.gsm.entity.mgr.User;
import com.xyt.gsm.mvc.controller.BaseController;
import com.xyt.gsm.service.fs.FileUploadService;
import com.xyt.gsm.service.ice.MerchantService;
import com.xyt.gsm.utils.FileUpload;
import com.xyt.gsm.utils.StringUtil;

/**
 * 图片上传接口 controller
 * 
 * @author liangrui
 * 
 */

@Controller
@RequestMapping(CommonConstants.UriPrefix.PC + CommonConstants.Menu.SYS + "/photoupload")
public class PhotoUploadController extends BaseController
{

	protected Log log = LogFactory.getLog(this.getClass().getName());

	@Resource
	FileUploadService fileUploadService;
	@Resource
	MerchantService merchantService;

	// 多张上传
	@ResponseBody
	@RequestMapping(value = "/manyup")
	public List<String> ManyUp(HttpServletRequest request, HttpServletResponse response, String suffixDir) throws IllegalStateException, IOException
	{
		List<String> fileInfo = null;

		return fileInfo;
	}

	// -----------------------------------------------------------------------------------
	// 单张图片上传,返回路径
	//@currentDomain:解决跨域,传值为==》主域服务器下的子页面   在子页面 周转, 回调父页面的JS函数
	// ----------------------------------------------------------------------------------
	@RequestMapping(value = "/singleup", method = RequestMethod.POST)
	public void SingleUp(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "suffixDir", required = true) String suffixDir,
			@RequestParam(required = false, value = "cutPhoto") boolean cutPhoto, @RequestParam(required = false, value = "merchantId") String merchantId) throws Exception
	{
		StringBuffer basePath=new StringBuffer(request.getScheme());
		basePath.append("://");
		basePath.append(request.getServerName());
		basePath.append(":");
		basePath.append(request.getServerPort());
		basePath.append(request.getContextPath());
		basePath.append("/");
		//basePath.append(FileUpload.getRealFilePath()/*.substring(0,FileUpload.getRealFilePath().length()-1)*/);
		
		User user = super.getLoginUser(request).getUser();
		if (user != null)
		{
			
			String filePath = fileUploadService.singleUpload(request, user, suffixDir, Fs.FileUpLoadType.PHOTO, cutPhoto, merchantId);

			// 处理返回状态
			UpoladStatus result = getStatus(filePath);
			String PromptSize = "";
			if (UpoladStatus.类型无效或图片过大.toString().equals(result.toString()))
			{
				// 2^10=1024
				PromptSize = "(最大限制:" + (FileUpload.photoSize >> 20) + "MB)";
			}

			PrintWriter out = response.getWriter();
			response.setHeader("Cache-Control", "none-cache");
			String idnum = request.getParameter("idnum");
			String reutrnDate = "{'id':'" + idnum + "','filePath':'" + basePath.append(filePath).toString() + "','dbFilePath':'" + filePath + "','status':{'code':'" + result.ordinal() + "','message':'" + result.name()
					+ PromptSize + "'}}";
			String currentDomain = request.getParameter("currentDomain");
			//<script>parent.parent.callback(" + reutrnDate + ");</script>
			String ret="<iframe id=\"ifr\" src=\""+currentDomain+"#"+reutrnDate+"\"></iframe>";
			out.print(ret);
		
		}

	}

	@RequestMapping(value = "/saveImage", method = RequestMethod.POST)
	public void saveImage(HttpServletRequest request, HttpServletResponse response, FileUploadVo vo) throws Exception
	{
		// 删除旧的无用的图片
		if (!StringUtil.isEmpty(vo.getOldImagePath()) && vo.getOldImagePath().startsWith("/"))
		{
			FileUpload.deleteFile(request, vo.getCutPhoto(), vo.getOldImagePath());
		}
		User user = super.getLoginUser(request).getUser();
		String filePath = fileUploadService.singleUpload(request, user, vo.getSuffixDir(), Fs.FileUpLoadType.PHOTO, vo.getCutPhoto(), vo.getMerchantId());
		JsonObject json = new JsonObject();
		json.addProperty("filePath", filePath);
		json.addProperty("success", false);
		if (!StringUtil.isEmpty(filePath) && filePath.startsWith("/"))
		{
			json.addProperty("success", true);
		}
		String result="<iframe id=\"ifr01001\" src='"+vo.getCallbackPath()+"#"+json.toString()+"'></iframe>";
		responseText(response, result);

	}

	/**
	 * 响应请求
	 * 
	 * @param response
	 * @param result
	 * @throws IOException
	 */
	private void responseText(HttpServletResponse response, String result) throws IOException
	{
		response.setHeader("pragma", "no-cache");
		response.setHeader("cache-control", "no-no-cache");
		response.setHeader("expires", "0");
		response.setContentType("text/html;charset=UTF-8");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = null;
		try
		{
			out = response.getWriter();
			out.print(result);
			out.flush();
		} finally
		{
			if (out != null)
			{
				out.close();
			}
		}
	}

	// -----------------------------------------------------------------------------------
	// 商品 图片数据和存储图片 删除 根据id
	// ----------------------------------------------------------------------------------
	@ResponseBody
	@RequestMapping(value = "/delimgandb")
	public ResultBean delImgAnDB(HttpServletRequest request, HttpServletResponse response, ProductPhoto photo, @RequestParam(required = true, value = "id") String id,
			@RequestParam(value = "cutPhoto", required = false) boolean cutPhoto, @RequestParam(value = "path") String path) throws Exception
	{
		return fileUploadService.deleteFileAnDb(request, Fs.FileUpLoadType.PHOTO, id, cutPhoto, path);

	}

	// -----------------------------------------------------------------------------------
	// 只 删除存储图片
	// ----------------------------------------------------------------------------------
	// @ResponseBody
	@RequestMapping(value = "/delimg")
	public void delImg(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "path", required = true) String[] path,
			@RequestParam(value = "cutPhoto", required = false) boolean cutPhoto) throws Exception
	{

		if (path.length > 0)
		{
			FileUpload.deleteFile(request, cutPhoto, path);
		}

	}

	// 获得图片返回状态
	public UpoladStatus getStatus(String filePath)
	{
		UpoladStatus result = UpoladStatus.上传失败末知错误;
		boolean isUp = true;
		for (UpoladStatus u : UpoladStatus.values())
		{
			if (filePath.equals(u.toString()))
			{
				result = u;
				isUp = false;
				break;
			}
		}
		if (isUp)
		{
			result = UpoladStatus.SEUCCESS;
		}
		return result;
	}

	// -----------------------------------------------------------------------------------
	// 获取上传服务器的域名
	// 根据用户类型获取,
	// 如果是商家,code 为null 默认取商家商品域名, 传参数 "1" 取商家域名
	// ----------------------------------------------------------------------------------
	@RequestMapping(value = "/getdomain", method = RequestMethod.POST)
	@ResponseBody
	public String getUpPhotoDomain(HttpServletRequest request, HttpServletResponse response, String code)
	{

		String domain = "";
		LoginUser user = super.getLoginUser(request);
		if (user != null)
		{
			// 运营
			if (CommonConstants.RoleType.OPERATER.equals(user.getUser().getUserType()))
			{
				domain = user.getPublicUploadDomain();
			} else if (CommonConstants.RoleType.MERCHANT.equals(user.getUser().getUserType()))
			{
				if (null == code || "".equals(code))
				{
					domain = user.getMerchantProductDomain();
					// 如果没有取到
					if (null == domain || "".equals(domain))
					{
						{
							// 获取域名
							domain = merchantService.getMerchantDomain(user.getUser().getMerchantId()).getProductDomain();
						}
					} else if ("1".equals(code))
					{
						domain = user.getMerchantDomain();
						// 如果没有取到
						if (null == domain || "".equals(domain))
						{
							{
								// 获取域名
								domain = merchantService.getMerchantDomain(user.getUser().getMerchantId()).getProductDomain();
							}
						}
					}
				}
			}
		}

	     //协议://域名/项目/X文件夹  ====(去掉文件夹) 
		 Matcher slashMatcher = Pattern.compile("/").matcher(domain);
		    int mIdx = 0;
		    while(slashMatcher.find()) 
		    {
		       mIdx++; if(mIdx == 4)break;
		    }
		 domain=domain.substring(0,slashMatcher.start());
		/*if ("/fs".equals(domain.substring(domain.lastIndexOf("/"))))
			{
				domain = domain.substring(0, domain.lastIndexOf("/"));
			}*/

	return domain;
	}
	// -----------------------------------------------------------------------------------
	// 下载
	// ----------------------------------------------------------------------------------

}

前端
部分相关代码
商品主图:  
<div class="upload" id="mainPicButton">
 <form method="post" enctype="multipart/form-data" target="hidden_frame" id="formImg0">
									<!-- <input type="file" name="file0" id="file0" onchange="submitUpload('0')" style="width:68px;height:22px;"> -->
									<input type="file" name="file0" id="file0" onchange="addOnePic('#mainPicButton')" style="width:68px;height:22px;">
									<input type="hidden" name="idnum" value="0">
									<input type="hidden" name="suffixDir" value="05/01"/>
									<input type="hidden" name="cutPhoto" value="true">
									<iframe name='hidden_frame' id="hidden_frame" style='display:none'></iframe>
								</form>
		                    </div>

<th><span>商品更多图片:</span></th>
             
						<td>
						           
							<div  id="morePicButton">
								<form method="post" enctype="multipart/form-data" target="hidden_frame" id="formImg1">
									<input type="file" name="file0" id="file0" onchange="addMorePic();" style="width:68px;height:22px;">
									<input type="hidden" name="idnum" value="0">
									<input type="hidden" name="suffixDir" value="05/01"/>
									<input type="hidden" name="cutPhoto" value="true">
									<iframe name='hidden_frame' id="hidden_frame" style='display:none'></iframe>
								</form>
		                    </div>

js:
//全局常量
var maxNoOfPics = 5;
var picPrefix = "/fs"; //图片路径前缀

//全局变量
var imgNum = 0;      //图片数量
var imgNo=0;		//图片ID
var hasMainPic = false;
var origPics = new Array(); //当更新某商品时,保存原来图片的路径,用于在删除时判断是否需要延迟删除

//var domainStr=window.top.getLoginUser().merchantProductDomain;

function getDomain(){
	var domainSt="";
	var userObj=window.top.getLoginUser();
	if(userObj.user.userType=="0")
	{
		domainSt=userObj.publicUploadDomain;
	}else if(userObj.user.userType=="2"){
		domainSt=userObj.merchantProductDomain;
	}
//	alert (domainSt);
	return domainSt;
}

function submitUpload(id){
	$("#imgSrc" + id +"").attr("alt", "图片上传中……");
	var imgID = id;
	if(id>0){
		imgID = 1;
	}
	
	var form=document.getElementById("formImg" + imgID +"");	
	form.method = "post";		
	form.idnum.value = id;
	
	var uriUp= getDomain()+"/pc/sys/photoupload/singleup?"+window.top.getLoginUser().token;
	form.action = uriUp;
	//form.action = getContextPath()+"/pc/sys/photoupload/singleup"; //必须先包含sys.js文件
	
	//用于返回
	var currentHref=window.location.href;
	var subHref=currentHref.substring(0, currentHref.lastIndexOf("/"));
	var input_domain = document.createElement("input");
	input_domain.setAttribute("name", "currentDomain");
	input_domain.setAttribute("value", subHref+"/callback-up.html");
	input_domain.setAttribute("type", "hidden");
	form.appendChild(input_domain);
	
	form.submit();
	//如果已经存在的图不是原图,则把服务器中的图片删除
	var currentPicPath =  $("#imgUrl" + id +"").val();
	if(!contains(origPics, currentPicPath) && currentPicPath!=""){
		delImg(currentPicPath, true);//true 删除图片 
	}
};


// step2: 上传图片,后台回调 
function callback(message) {
	var id=message.id;
	if(message.status.code=="0"){
		var filePath=message.filePath;
		var dbFilePath=message.dbFilePath;
		//$("#imgUrl" + id +"").attr("value", dbFilePath);
		$("#imgUrl" + id +"").val(dbFilePath);
		$("#imgSrc" + id +"").attr("src", filePath);
	}else{
		if(id!=0){
			$("#imgSrc" + id).parent().remove();
		}
		_message(message.status.message); //上传错误提示
	}
};

function deleteOrigPics(photoList){ //判断是否需要删除原图,如果原图不在photoList中,则删除
	for(var i=1; i<origPics.length; i++){
		var found=false;
		var j=0;
		while(!found && j<photoList.length){
			if(photoList[j].url==origPics[i]){
				found=true;
			}
			j++;
		}
	
		if(!found){
			delImg(origPics[i], true);
		}
	} 
}

/**
* Author: 许继俊, 2014-04
* 为“更多图片”增加一个图片,加在morePicButtonId前面
* morePicButtonId: “添加图片”按钮的ID,调用此方法就在它前面添加一个图片
* imgNo:图片序号
* picPrefix: 图片路径前缀
* filePath:图片(相对)路径
*/


//dbFilePath 用于存放数据库, fullFilePath用于显示图片
function addOnePic(picButtonId, dbFilePath, fullFilePath){
	if(picButtonId == "#mainPicButton"){ //如果是主图
		imgId = 0;
	}else{	//如果是“更多图片”
		imgNo++;
		imgNum++;
		imgId = imgNo;
	}
	if(picButtonId == "#mainPicButton" ){
		if(hasMainPic == false){
			var html = '<span class="pict">\
				<img id="imgSrc' + imgId + '" width="120px" height="120px"/>\
				<a class="close" onclick="removeImg(\'' + imgId + '\')"></a>\
				<input type="hidden" id="imgUrl' + imgId + '"/></span>';
			$(picButtonId).after(html);
			hasMainPic = true;
		}
	}else{
		var html = '<span class="pict">\
			<img id="imgSrc' + imgId + '" width="120px" height="120px"/>\
			<a class="close" onclick="removeImg(\'' + imgId + '\')"></a>\
			<input type="hidden" class="imgUrl" id="imgUrl' + imgId + '"/></span>';
		$(picButtonId).after(html);
	}
	if(fullFilePath != undefined){
		$("#imgUrl" + imgId +"").val(dbFilePath);
		$("#imgSrc" + imgId +"").attr("src", fullFilePath);
	}else{
		submitUpload(imgId); //如果只有一个参数,则是提交
	}	
}

//添加更多图片:
function addMorePic(){
	if(imgNum>=maxNoOfPics){
		_message("对不起,最多只能上传" + maxNoOfPics + "张图片!");
		return false;
	}
	addOnePic("#morePicButton");
}	

	
//删除图片(imgNo=0时为主图)
function removeImg(imgNo){
	var picPath="";
	
	if($("#imgUrl"+ imgNo).val()!=undefined){
		picPath=$("#imgUrl"+ imgNo).val();
		$("#imgSrc" + imgNo).parent().remove();
	}
	
	if(imgNo==0){ //删除主图
		hasMainPic = false;
		//$("#imgSrc0").removeAttr("src");
		//$("#imgSrc0").attr("alt","点击添加图片");
		//$("#imgUrl0").removeAttr("value");
	}else{		//删除其他图
		imgNum--;
	}
	
	//如果是原图,则延迟服务器的删除(在提交时再删除)
	if(picPath != origPics[imgNo]){
		delImg(picPath,true);//true 删除小图 
	}
	
}


//删除图片 
function delImg(path, cutPhoto){
	var reqStr=null;
	
	if(cutPhoto==true){
		reqStr="path="+path+"&cutPhoto=true";
	}else{
		reqStr="path="+path+"&cutPhoto=false";
	}
	
	$.post(
		getContextPath()+"/pc/sys/photoupload/delimg",
		reqStr,
		function(data){	},
		'json'
	);
}

	
/**判断在数组中是否含有给定的一个变量值/对象
 * array: 数组
 * obj: 值/对象
 */
function contains(array, obj) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] === obj) {
            return true;
        }
    }
    return false;
}

callback-up.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
<script type="text/javascript">

//alert(document.domain);
var returndata=self.location.hash.substring(1);
if(parent.parent&&parent.parent.callback){
	var message = eval('(' + returndata + ')'); 
	parent.parent.callback(message);
}else if(window.top.success){
	window.top.success(returndata);
}else if(parent.parent&&parent.parent.success){
	parent.parent.success(returndata);
}
	

</script>
</body>
</html>



本文转载自:http://blog.csdn.net/liangrui1988/article/details/30237699

猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
Spring Boot项目每次请求Session都不一样的记录

背景 网站注册模块有个带图片验证码验证的环节,实现思路为:前端请求获取图片验证码的接口,接口里生成图片验证码,并保存在session;验证图片验证码时,从session中获取图片验证码与当前请...

豫华商
06/25
416
0
Spring Boot Banner自定义,让你的应用与众不同

点击上方 IT牧场 ,选择 置顶或者星标技术干货每日送达! TIPS 本文基于Spring Boot 2.1.4,理论支持Spring Boot所有版本。 相信玩过Spring Boot的童鞋一定在启动日志中见过类似如下的内容。...

IT牧场
05/08
0
0
Spring 跨域支持(CROS)注解:@CrossOrigin

Spring MVC 4.2 增加 CORS 支持 跨站 HTTP 请求(Cross-site HTTP request)是指发起请求的资源所在域不同于该请求所指向资源所在的域的 HTTP 请求。比如说,域名A(http://domaina.example)的某...

孟飞阳
2017/11/08
297
0
vue使用html2canvas踩坑总结

需求场景 运营后台上传一张图,同时页面生成小程序二维码,与运营上传的图合成一张大图,用于该页面在朋友圈的分享传播。 实现思路 1. 背景图上传 背景图上传,调用接口实现文件上传到oss平台...

邹R-ainna
08/24
0
0
.net mvc + layui做图片上传(一)

  图片上传和展示是互联网应用中比较常见的一个功能,最近做的一个门户网站项目就有多个需要上传图片的功能模块。关于这部分内容,本来功能不复杂,但后面做起来却还是出现了一些波折。因为...

CherishTheYouth
01/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

uni app 零基础小白到项目实战

$emit 子组件传给父组件$ref 父组件操作子组件 公用模板 uni-app全局变量的几种实现方法 const websiteUrl = 'http'const now = Date.now || function() { return new Date().getTime......

达达前端小酒馆
30分钟前
7
0
Tomcat是如何实现异步Servlet的

前言 通过我之前的Tomcat系列文章,相信看我博客的同学对Tomcat应该有一个比较清晰的了解了,在前几篇博客我们讨论了Tomcat在SpringBoot框架中是如何启动的,讨论了Tomcat的内部组件是如何设...

木木匠
54分钟前
29
0
mysql中间件分享(Mysql-prxoy,Atlas,DBProxy,Amoeba,cobar,TDDL)

hello 各位小伙伴大家好,我是小栈君,这期我们分享关于mysql中间件的研究,也就是数据层的读写分离和负载均衡,希望能够在实际的应用中能够帮助到各位小伙伴。 下期我们将继续分享go语言的系...

IT干货栈
今天
10
0
OSChina 周一乱弹 —— 人生,还真是到处是意外

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐# 分享lil peep的单曲《High School》 《High School》- lil peep 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
943
13
Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部