项目小结

学完五大框架,上手跟着慕课视频做个项目练手https://coding.imooc.com/class/144.html#Anchor

刚做完1.0,对跟着老师学习到的实用技术做个小结

上传图片的处理(调用Thumbnails生成带有水印的图片)

下载thumbnailator-0.4.8.jar

实体类ImageHolder封装上传文件的名字(后面需要获取格式扩展名时用到)和输入流

public class ImageHolder {

	private String imageName;
	private InputStream image;

	public ImageHolder(String imageName, InputStream image) {
		this.imageName = imageName;
		this.image = image;
	}

	public String getImageName() {
		return imageName;
	}
}
public class ImageUtil {
	private static String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
	private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
	private static final Random r = new Random();

	/**
	 * 处理缩略图,并返回新生成图片的相对值路径
	 * 
	 * @param thumbnail
	 * @param targetAddr
	 * @return
	 */
	public static String generateThumbnail(ImageHolder thumbnail, String targetAddr) {
		// 获取不重复的随机名
		String realFileName = getRandomFileName();
		// 获取文件的扩展名如png,jpg等
		String extension = getFileExtension(thumbnail.getImageName());
		// 如果目标路径不存在,则自动创建
		makeDirPath(targetAddr);
		// 获取文件存储的相对路径(带文件名)
		String relativeAddr = targetAddr + realFileName + extension;
		// 获取文件要保存到的目标路径
		File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
		
		// 调用Thumbnails生成带有水印的图片
		try {
			Thumbnails.of(thumbnail.getImage()).size(200, 200)
					.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath + "/watermark.jpg")), 0.25f)
					.outputQuality(0.8f).toFile(dest);
		} catch (IOException e) {
			logger.error(e.toString());
			throw new RuntimeException("创建缩略图失败:" + e.toString());
		}
		// 返回图片相对路径地址
		return relativeAddr;
	}

	

	/**
	 * 创建目标路径所涉及到的目录,即/home/work/xiangze/xxx.jpg, 那么 home work xiangze
	 * 这三个文件夹都得自动创建
	 * 
	 * @param targetAddr
	 */
	private static void makeDirPath(String targetAddr) {
		String realFileParentPath = PathUtil.getImgBasePath() + targetAddr;
		File dirPath = new File(realFileParentPath);
		if (!dirPath.exists()) {
			dirPath.mkdirs();
		}
	}

	/**
	 * 获取输入文件流的扩展名
	 * 
	 * @param thumbnail
	 * @return
	 */
	private static String getFileExtension(String fileName) {
		return fileName.substring(fileName.lastIndexOf("."));
	}

	/**
	 * 生成随机文件名,当前年月日小时分钟秒钟+五位随机数
	 * 
	 * @return
	 */
	public static String getRandomFileName() {
		// 获取随机的五位数
		int rannum = r.nextInt(89999) + 10000;
		String nowTimeStr = sDateFormat.format(new Date());
		return nowTimeStr + rannum;
	}

	

	/**
	 * storePath是文件的路径还是目录的路径, 如果storePath是文件路径则删除该文件,
	 * 如果storePath是目录路径则删除该目录下的所有文件
	 * 
	 * @param storePath
	 */
	public static void deleteFileOrPath(String storePath) {
		File fileOrPath = new File(PathUtil.getImgBasePath() + storePath);
		if (fileOrPath.exists()) {
			if (fileOrPath.isDirectory()) {
				File files[] = fileOrPath.listFiles();
				for (int i = 0; i < files.length; i++) {
					files[i].delete();
				}
			}
			fileOrPath.delete();
		}
	}
}

水印的透明度可以通过改变最后的参数来调整,0.0F是完全透明的,1.0F是完全不透明的。 

public class PathUtil {
	private static String seperator = System.getProperty("file.separator");

	public static String getImgBasePath() {
		String os = System.getProperty("os.name");
		String basePath = "";
		if (os.toLowerCase().startsWith("win")) {
			basePath = "C:/o2oImg";
		} else {
			basePath = "/user/image";
		}
		basePath = basePath.replace("/", seperator);
		return basePath;
	}

	public static String getShopImagePath(long shopId) {
		String imagePath = "/upload/shop/" + shopId + "/";
		return imagePath.replace("/", seperator);
	}
}

在service层调用的时候

private void addShopImg(Shop shop, ImageHolder thumbnail) {
		// 获取shop图片目录的相对值路径
		String dest = PathUtil.getShopImagePath(shop.getShopId());
		String shopImgAddr = ImageUtil.generateThumbnail(thumbnail, dest);
		shop.setShopImg(shopImgAddr);
	}

往 getShopImagePath(long shopId) 中传入shopid值拼接成/upload/shop/shopid的路径 

 ImageUtil.generateThumbnail(thumbnail, dest)方法 dest+随机名+文件扩展名=相对路径 返回来

PathUtil.getImgBasePath() +相对路径=真实存储路径  方法中判断系统是win或者是其他,统一先把分隔符写成 ‘/’  imagePath.replace("/", seperator)再判断进行替换

 

Ajax发送表单数据

    <!-- json解析 -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.8.7</version>
		</dependency>
	$('#submit').click(function() {
		var shop = {};
		shop.shopName = $('#shop-name').val();
		shop.shopAddr = $('#shop-addr').val();
		shop.phone = $('#shop-phone').val();
		shop.shopDesc = $('#shop-desc').val();

		shop.shopCategory = {
			shopCategoryId : $('#shop-category').find('option').not(function() {
				return !this.selected;
			}).data('id')
		};
		shop.area = {
			areaId : $('#area').find('option').not(function() {
				return !this.selected;
			}).data('id')
		};

		var shopImg = $("#shop-img")[0].files[0];
		var formData = new FormData();
		formData.append('shopImg', shopImg);
		formData.append('shopStr', JSON.stringify(shop));
		var verifyCodeActual = $('#j_captcha').val();
		if (!verifyCodeActual) {
			$.toast('请输入验证码!');
			return;
		}
		formData.append("verifyCodeActual", verifyCodeActual);
		$.ajax({
			url : editShopUrl,
			type : 'POST',
			// contentType: "application/x-www-form-urlencoded; charset=utf-8",
			data : formData,
			contentType : false,
			processData : false,
			cache : false,
			success : function(data) {
				if (data.success) {
					$.toast('提交成功!');
					if (isEdit){
						$('#captcha_img').click();
					} else{
						window.location.href="/myO2O/shopadmin/shoplist";
					}
				} else { 
					$.toast('提交失败!');
					$('#captcha_img').click();
				}
			}
		});
	});

async: 

要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。

这里就会经常发生问题,就是异步了,所以有时候你会不小心,在请求还没成功,你就以为你成功了,然后再干其他事,就容易出问题,所以,一般要在success回调函数里面做一些事。

cache: 
要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。

contentType:

要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为"application/x-www-form-urlencoded"。该默认值适合大多数应用场合。

multipart/form-data:有时候也会这个,上传下载可能会用到。

contentType: "application/json; charset=utf-8",

 success:

要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。
         (1)由服务器返回,并根据dataType参数进行处理后的数据。
         (2)描述状态的字符串。
         function(data, textStatus){
            //data可能是xmlDoc、jsonObj、html、text等等 
            this;  //调用本次ajax请求时传递的options参数
         } 

error:
要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:
       function(XMLHttpRequest, textStatus, errorThrown){
          //通常情况下textStatus和errorThrown只有其中一个包含信息
          this;   //调用本次ajax请求时传递的options参数
       } 

前端把对象转化为json字符串,后台接受可以这样:


String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
ObjectMapper mapper = new ObjectMapper();
Shop shop = mapper.readValue(shopStr, Shop.class);

更粗暴的是传进来的参数加@RequestBody,直接先将字符串转换成对象Shop

 

getJSON获取页面信息

这个项目页面获取从后台传来的信息,全部都是用getJSON啊。。。用getJSON比之前用的JSP搭配jstl,更加前后分离啦

modelMap.put("shopCategoryList", shopCategoryList);
modelMap.put("areaList", areaList);
modelMap.put("success", true);

 

function getCategory() {
		$.getJSON(initUrl, function(data) {
			if (data.success) {
				var tempHtml = '';
				var tempAreaHtml = '';
				data.shopCategoryList.map(function(item, index) {
					tempHtml += '<option data-id="' + item.shopCategoryId
							+ '">' + item.shopCategoryName + '</option>';
				});
				data.areaList.map(function(item, index) {
					tempAreaHtml += '<option data-id="' + item.areaId + '">'
							+ item.areaName + '</option>';
				});
				$('#shop-category').html(tempHtml);
				$('#shop-category').removeAttr('disabled');
				$('#area').html(tempAreaHtml); 
			}
		});
	}

jq数据请求的四种方法get post ajax getJSON和不同于之间的jsonp跨域请求详细总结

 

后台对文件流的处理

CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
if (commonsMultipartResolver.isMultipart(request)) {
		MultipartHttpServletRequest multipartHttpServletRequest =(MultipartHttpServletRequest) request;
			shopImg = (CommonsMultipartFile)=multipartHttpServletRequest.getFile("shopImg");
}
ImageHolder imageHolder = new ImageHolder(shopImg.getOriginalFilename(), shopImg.getInputStream());

 

CommonsMultipartResolver的使用:

  1、得到CommonsMultipartResolver对象:

CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //其中request即为我们请求的HttpServletRequest对象

  2、判断请求是否为MultiPart File文件上传请求:

boolean isFileUpload = multipartResolver.isMultipart(request);

MultipartHttpServletRequest的使用:

  在确定了是多文件上传的请求后,即可以将HttpServletRequest转成MultipartHttpServletRequest对象,MultipartHttpServletRequest对象封装了文件上传的文件对象,可以通过此对象直接得到文件对象。

  1、得到文件名称列表的迭代器:

  Iterator<String> iter = multiRequest.getFileNames();

  2、取得上传的文件:

 MultipartFile file = multiRequest.getFile(iter.next());

跟之前做的直接的文件上传做下对比:

@PostMapping
	public void fileUpload(MultipartFile[] files) throws IllegalStateException, IOException {
		ModelAndView mv=new ModelAndView();
		for(MultipartFile multipartFile:files) {
			String originFileName=multipartFile.getOriginalFilename();
			String newFileName=UUID.randomUUID()+"."+FilenameUtils.getExtension(originFileName);
			String root=request.getServletContext().getRealPath("/upload");
			File uploadRoot=new File(root);
			if(!uploadRoot.exists()) {
				uploadRoot.mkdirs();
			}
			multipartFile.transferTo(new File(uploadRoot,newFileName));
		}
}

服务器部署

阿里云部署Java网站和微信开发调试心得技巧(上)

阿里云部署Java网站和微信开发调试心得技巧(下)阿里云部署Java网站和微信开发调试心得技巧(下)

部署到tomcat的时候出现了很多麻烦的问题,网站还没有备案,80端口不能用估计一直没成功过,这样也导致了后面的微信开发没办法做。。。

最后只能先ip+8080端口访问啦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值