黑马商城06

黑马商城06

今日任务:
1.商品展示
2.添加商品(上传文件)

1.商品展示

	前端:
	 	携带当前页面页码请求后端
	 	后端数据拿来后拼串
    后端:
         把数据该查的查,该算的算,以Json格式返回

2.文件上传

文件上传?
	从客户端的计算机 传输 文件到服务器的计算机

	本质流传输的过程
///
	满足以下条件(java代码版)

	1.页面给一个form表单
	2.在表单有一个input type=file
	3.表单的提交方式 得是post 不能用get是因为数据拼在请求行里,对数据有大小限制
	4.修改表单的一个属性  enctype="application/x-www-form-urlencode"  修改为enctype="multipart/form-data"
	5.满足了以上四个条件 提交到后端服务器上 接收的时候  reqeust.getParameter|getParameterValues|getParameterMap 都将失效

	发现 虽然不能使用request.getParameter系列方法 但是发现数据是有规律的
	可以工具类 也是apache提供
		common-fileupload
		
    1.maven 添加依赖
	2.使用它的api 让它来帮助解析
		使用步骤(不需要记忆)-----框架里封装了 (以后开发 也不会写文件上传的服务器代码 为啥 最后解释)

		1.创建 文件磁盘工厂对象 
		2.创建一个上传解析对象 负责帮助我们解析 request中inputstream
		3.它解析完成 返回list集合  放着一个个的表单项
		4.使用了   遍历集合 取出一个个项


	小问题:
		文件名重复 覆盖问题  收到文件 文件名字自己取 保证唯一
		某个目录下 小文件太过问题 导致操作系统检索变慢
		分散目录
			随机分散目录

		删除临时文件
		item.delete()

代码实现

demo.html

    <!--enctype="multipart/form-data"-->
    <form action="/upload" method="post"  enctype="multipart/form-data" >
        用户名:<input type="text" name="username"><br>
        备注:<input type="text" name="desc"><br>
        头像:<input type="file" name="avatar"><br>
        身份证:<input type="file" name="IDCard"><br>
        <input type="submit" value="点我提交">
    </form>

UploadServlet

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //不考虑文件框
        /*String username = request.getParameter("username");
        String desc = request.getParameter("desc");
        String avatar = request.getParameter("avatar");
        System.out.println("名字:"+username+"-描述:"+desc+"-头像:"+avatar);*/

        //获取请求 头 自己解析 太麻烦 我们使用 apache提供工具类
/*        String contentType = request.getHeader("Content-Type");
        String boundary=contentType.split("; ")[1].split("=")[1];
        System.out.println("该次请去分隔符是:"+boundary);

        ServletInputStream inputStream = request.getInputStream();
        //自己取数据
        BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
        String s1 = bf.readLine();
        System.out.println(s1);
        String s2 = bf.readLine();
        System.out.println(s2);*/

        //使用工具类
        //获取ip
        String remoteAddr = request.getRemoteAddr();
        System.out.println("欢迎我的朋友:"+remoteAddr+"来访问服务器");

        //目录将下面 封装了 放在一个方法里 返回一个返回值  返回map集合
        Map<String, String[]> map = parseRequest(request);

        Set<Map.Entry<String, String[]>> entries = map.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            System.out.println(entry.getKey()+"::::::::"+ Arrays.toString(entry.getValue()));
        }


        response.getWriter().print("ok");


    }
    public Map<String,String[]> parseRequest(HttpServletRequest request){
        //返回一个map集合
        Map<String,String[]> result = new HashMap<>();

        try {
            //1.创建 文件磁盘工厂对象
            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            //2.创建一个上传解析对象 负责帮助我们解析 request中inputstream
            ServletFileUpload parser = new ServletFileUpload(diskFileItemFactory);
            //3.它解析完成 返回list集合  放着一个个的表单项
            List<FileItem> items = parser.parseRequest(request);
            //4.使用了   遍历集合 取出一个个项
            for (FileItem item : items) {
                //获取表单项的名字
                String parameterName = item.getFieldName();

                //判断表单是否是普通文本字段
                if(item.isFormField()){
                    //是普通项  关心她的值
                    String paramValue = item.getString("utf-8");

                    /*if(result.containsKey(parameterName)){

                    }*/
                    //这里注意有坑,当一个表单项有多个值的时候,这样写不行
                    result.put(parameterName,new String[]{paramValue});
                }else{
                    //文件项 关心就是 文件对应 的流
                    //文件的名字
                    String fileName = item.getName();

                    //以流的形式返回上传文件的数据内容
                    InputStream in = item.getInputStream();
                    //创建  分散二级目录
                    String secondDir = UploadUtil.randDir();
                    //电脑文件路径+随机目录
                    String storePath=UploadUtil.BaseDir()+secondDir;
                    //检查是否存在 有 直接用 没有创建
                    UploadUtil.mustExist(storePath);
                    //获取随机文件名
                    String uuidName = UploadUtil.getUUIDName(fileName);
                    //创建输出流
                    FileOutputStream out = new FileOutputStream(storePath + uuidName);

                    byte[] bf=new byte[1024];

                    int len=0;
                    while((len=in.read(bf))!=-1){
                        //写到输出流
                        out.write(bf,0,len);
                    }
                    //关流
                    out.close();
                    in.close();
                    System.out.println("该文件被保存了:"+fileName);
                    //删除temp文件夹里的文件
                    item.delete();
                    //表单项名字,和目录+随机名字,放到put里面
                    result.put(parameterName,new String[]{secondDir+uuidName});
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

UploadUtil

	/**
	 * 获取文件真实名称
	 * 由于浏览器的不同获取的名称可能为:c:/upload/1.jpg或者1.jpg 
	 * 最终获取的为  1.jpg
	 * @param name 上传上来的文件名称
	 * @return	真实名称
	 */
	public static String getRealName(String name){
		//获取最后一个"/"
		int index = name.lastIndexOf("\\");
		return name.substring(index+1);
	}
	
	
	/**
	 * 获取随机名称
	 * @param realName 真实名称
	 * @return uuid 随机名称
	 */
	public static String getUUIDName(String realName){
		//realname  可能是  1.jpg   也可能是  1
		//获取后缀名
		int index = realName.lastIndexOf(".");
		if(index==-1){
			return UUID.randomUUID().toString().replace("-", "").toUpperCase();
		}else{
			return UUID.randomUUID().toString().replace("-", "").toUpperCase()+realName.substring(index);
		}
	}
	
	public static String BaseDir(){

		ResourceBundle upload = ResourceBundle.getBundle("upload");
		return upload.getString("base");
	}



	/**
	 * 获取文件目录,可以获取256个随机目录
	 * @return 随机目录 /a/4  /b/c
	 */
	public static String randDir(){
		String s="0123456789ABCDEF";
		Random r = new Random();
		return "/"+s.charAt(r.nextInt(16))+"/"+s.charAt(r.nextInt(16))+"/";
	}

	public static void mustExist(String path){
		File file = new File(path);
		if (!file.exists()){
			file.mkdirs();
		}

	}

upload.properties

base=C:\\Users\\Admin\\Desktop\\upload1

3.Ajax上传文件的封装

代码实现

<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript" src="resources/js/jquery-1.11.3.min.js" ></script>
		<script type="text/javascript" src="resources/js/jquery-heima-0.0.1.js" ></script>
		<script>
			$(function(){
				
				$("#upload").click(function(){
					/*var params=$("form").serialize();
					alert(params)*/
					//js 专门提供一个对象 对付 ajax上传文件
					//这个对象构建的需要给传入参数
					//对应的form表单对象
					var fd=new FormData(document.getElementById("f01"));
					
					/*$.ajax({
						url:"http://api.itheima349.com/upload",
						data:fd,
						type:"post",
						contentType:false,//不要动手脚 对请求头 不要覆盖
						processData:false,
						success:function(data){
							alert(data);
						},
						error:function(){
							//...
						}
						
					})*/
					
					//封装好的方法直接用
					HM.ajaxFile("/upload","f01",function(vo){
						alert(vo)
						
					})
					
				})
			})
		</script>
	</head>
	<body>
		<form id="f01"   enctype="multipart/form-data" >
	        用户名:<input type="text" name="username"><br>
	        备注:<input type="text" name="desc"><br>
	        头像:<input type="file" name="avatar"><br>
	        身份证:<input type="file" name="IDCard"><br>
        	<input type="button" value="点我提交" id="upload">
    	</form>
	</body>
</html>

这两个参数一定要改为false,要不传不了值
在这里插入图片描述
在这里插入图片描述

4.完成上传文件操作

	  前端:
	        携带整个表单提交servlet
	        成功后跳转
	  后端:
	       把照片放到对应的目录,开始封装product数据,插入数据库,返回
1.2. 结构化一下 1.3. 图形化一下 1.3.1. 运营商后台 1.3.2. 商家后台 1.3.3. 网页前台 参考京东 2. 技术选型 前端:angularJS + Bootstrap 后台:SSM( springmvc+spring+mybatis) 数据库:mysql,使用mycat读写分离 开发模式:SOA 服务中间件:dubbox,需要和zookeeper配合使用 注册中心:zookeeper 消息中间件:Activemq,使用spring-jms 负载均衡:nginx 搜索:solr集群(solrCloud),配合zookeeper搭建, 使用spring-data-solor 缓存:redis集群,使用spring-data-redis 图片存储:fastDFS集群 网页静态化:freemarker 单点登录:cas 权限管理:SpringSecurity, 跨域:cros 支付:微信扫描 短信验证:阿里大于 密码加密:BCrypt 富文本:KindEditor 事务:声明式事务 任务调度:spring task 所有的技术,都可能涉及到为什么用?怎么用?用的过程中有什么问题? 3. 框架搭建 3.1. 前端 理解baseControler.js、base.js、base_pagination.js,以及每一个xxxController.js里面都公共的做了些什么。 baseControler.js 分页配置 列表刷新 处理checkBox勾选 xxxControler.js 自动生成增删改查 base_pagination.js 带分页 base.js 不带分页 3.2. dao 使用了mybatis逆向工程 4. 模块开发 逐个模块开发就好 4.1. 学会评估模块难不难 一个模块难不难从几方面考虑。 涉及几张表? 1,2张表的操作还是没有什么难度的。 涉及哪些功能? 增删改查,批量删除。 前端展示? 分页列表、树形、面包屑、三级联动、内容格式化。 4.2. 举几个简单模块的例子 4.2.1. 品牌管理 单表 分页、新增、删除、修改 4.2.2. 规格管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.3. 模板管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.4. 分类管理 单表 4.2.5. 商家审核 单表 4.3. 举一个复杂模块 4.3.1. 商品新增 需要插入3张表,tb_goods、tb_goods_desc、tb_item 前端:三级联动、富文本、图片上传、动态生成内容 4.3.2. 商品修改 需要从3张表获取数据,然后进行回显。 4.4. 典型模块设计 4.4.1. 管理后台 商品新增、商品修改 4.4.2. 前台页面 搜索模块实现 购物车模块实现 支付模块实现 秒杀模块实现 5. 开发过程中问题&优化 1.1. 登录 单点登录怎么实现 session怎么共享 1.2. 缓存 哪些场景需要用到redis redis存储格式的选择 怎么提高redis缓存利用率 缓存如何同步 1.3. 图片上传 图片怎么存储 图片怎么上传 1.4. 搜索 ​ 怎么实现 数据量大、 并发量高的搜索 怎么分词 1.5. 消息通知 ​ 哪些情况用到activeMq 1.6. 优化 seo怎么优化 怎么加快访问速度 1.7. 秒杀 ​ 怎么处理高并发 ​ 秒杀过程中怎么控制库存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值