通用mapper、图片上传、nginx
1 通用Mapper介绍
1.1 通用Mapper入门案例
1.1.1 通用的findCount()
- 编辑接口
/** * 需求:自己实现一个通用Mapper的方法 * 要求:查询任意表的记录总数??? * sql: select count(*) from 表名 */ @SelectProvider(type = SysMapperProvider.class, method = "dynamicSQL") int findCount(); 2.编辑测试方法 /** * 目的:获取表的名称 * 1.获取方法的执行的路径 * 2.获取Mapper的接口路径 * 3.通过反射的机制获取Mapper的类型 * 4.通过Mapper的类型获取父级接口类型 * 1.判断父级接口是否为泛型 * 5.获取泛型中的类型 Item * 6.获取item类型的注解 * 7.获取表的名称 * @param ms * @return */ public SqlNode findCount(MappedStatement ms){ //1.获取当前正在执行的Mapper的方法路径 //com.jt.manage.mapper.itemMapper.findCount() try { //1.获取客户端调用的方法 //com.jt.manage.mapper.ItemMapper.findCount() String methodPath = ms.getId(); //2.获取ItemMapper的字符串 com.jt.manage.mapper.ItemMapper String targetPath = methodPath.substring(0, methodPath.lastIndexOf(".")); //3.获取ItemMapper对象 ItemMapper.Class Class<?> targetClass = Class.forName(targetPath); //4.获取ItemMapper的父级接口 由于接口是可以多继承的 Type[] types = targetClass.getGenericInterfaces(); //5.获取SysMapper Type targetType = types[0]; //判断该类型是否为泛型 SysMapper<Item> if(targetType instanceof ParameterizedType){ //表示当前接口是一个泛型,并且获取泛型参数 SysMapper<Item> ParameterizedType parameterizedType = (ParameterizedType) targetType; //SysMapper<T,V,K> 获取泛型的全部参数 Item Type Type[] supers = parameterizedType.getActualTypeArguments(); //表示成功获取第一个参数 Item.class Class<?> targetMethodClass = (Class<?>) supers[0]; //判断Class不能为空 if(targetMethodClass !=null){ //判断该类中是否含有注解 if(targetMethodClass.isAnnotationPresent(Table.class)){ //获取目标对象的注解 Table table = targetMethodClass.getAnnotation(Table.class); //获取表名 String tableName = table.name(); //定义查询sql语句 String sql = "select count(*) from "+tableName; //定义sqlNode对象 SqlNode sqlNode = new StaticTextSqlNode(sql); return sqlNode; } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; }
2 富文本编辑器
2.1 入门案例
2.1.1 引入js
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet"> <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script> <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script> <script type="text/javascript" charset="utf-8" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
2.1.2 初始化文本编辑器
<script type="text/javascript"> $(function(){ KindEditor.ready(function(){ KindEditor.create("#editor") }) }) </script>
2.2 商品描述新增
2.2.1 表设计
2.2.2 编辑pojo对象
2.2.3 页面分析
说明:根据页面中的name属性进行数据传输
<td>商品描述:</td> <td> <textarea style="width:800px;height:300px;visibility:hidden;" name="desc"></textarea> </td>
2.2.4 编辑Controller
2.2.5 编辑Service
/** * 说明: * Item对象的主键是自增的,所以item中的id现在为null * ItemDesc对象入库操作时,必须含有主键Id信息. * 困难:如果获取已经入库的id?? * 解决: * 利用通用Mapper的机制.当执行插入操作时,会先查询当前最大的id. * 之后回显. * SELECT LAST_INSERT_ID() * @param item * @param desc */ @Override public void saveItem(Item item,String desc) { //补齐Item数据 item.setStatus(1); //启用 item.setCreated(new Date()); item.setUpdated(item.getCreated()); //利用通用Mapper实现入库操作 itemMapper.insert(item); //为ItemDesc补齐数据 ItemDesc itemDesc = new ItemDesc(); itemDesc.setItemDesc(desc); itemDesc.setItemId(item.getId()); itemDesc.setCreated(item.getCreated()); itemDesc.setUpdated(item.getCreated()); itemDescMapper.insert(itemDesc); }
2.3 商品描述的回显
2.3.1 页面分析
2.3.2 编辑Controller
2.3.3 编辑Service
说明:通过通用Mapper的根据主键查询ItemDesc信息
2.4 商品描述信息修改
2.4.1 页面分析
说明:根据修改页面的语句.接收name=desc提交的数据
<tr> <td>商品描述:</td> <td> <textarea style="width:800px;height:300px;visibility:hidden;" name="desc"></textarea> </td> </tr>
2.4.2 编辑Controller
说明:接收Desc数据
2.4.3 编辑Service
2.4.4 效果展现
说明:数据已经修改
2.5 商品关联删除
2.5.1 商品描述删除
2.6 图片的上传
2.6.1 页面分析
说明:如果测试图片上传,需要使用谷歌浏览器.
2.6.2 添加文件上传解析器
<!--配置文件上传解析器 要求: 1.id的名称必须固定 multipartResolver 2.规范文件上传的参数 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--最大的上传量10M --> <property name="maxUploadSize" value="10485760"/> <property name="defaultEncoding" value="UTF-8"/> </bean>
2.7 Spring属性赋值
说明:将本地的磁盘路径和url直接写死在代码中,不是特别的好,最好使用配置文件的方式进行动态的注入.
2.7.1 编辑配置文件
2.7.2 Spring容器管理配置文件
2.7.3 动态的取值
2.8 文件上传
2.8.1 编辑Controller
2.8.2 编辑Service
/** * 文件上传的步骤 * 1.判断是否为图片 png|jpg|gif * 2.判断是否非法程序 通过BufferedImage对象 * 3.为了让图片检索快速,使用分文件夹存储 * 4.应该尽可能让图片名称不一致 * 5.将文件进行写盘操作 * 6.url和本地的文件路径的关系? * url的作用: * 通过用户访问虚拟路径,获取图片的资源 * https://img11.360buyimg.com/n1/s150x150_jfs/t4918/211/45049371/104197/15abee23/58d9d1deN542b664b.jpg * * 结论: * 1.本地的磁盘路径是保存图片的物理地址 * 2.url是用户访问图片的虚拟地址 * * 物理地址: E:\jt-upload/2018/10/1/10/abc.jpg * 虚拟地址: http://image.jt.com/2018/10/1/10/abc.jpg * * */ @Override public PicUploadResult uploadFile(MultipartFile uploadFile) { PicUploadResult result = new PicUploadResult(); //1.获取文件的名称 abc.jpg String fileName = uploadFile.getOriginalFilename(); //2.判断是否为图片类型 .代表任意一个不为空格的字符 if(!fileName.matches("^.*(jpg|png|gif)$")){ result.setError(1); //表示不是一个图片 return result; } try { //3.判断是否为恶意程序 BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream()); //4.获取图片的高度和宽度 int height = bufferedImage.getHeight();//获取高度 int width = bufferedImage.getWidth(); //获取宽度 if(height == 0 || width == 0){ //表示不是图片 result.setError(1); return result; } //如果程序执行到这里表示图片正常 //5.定义本地磁盘的路径 //String LPath = "E:/jt-upload/"; //6.采用时间格式分文件存储 yyyy/MM/dd/HH String datePath = new SimpleDateFormat("yyyy/MM/dd/HH") .format(new Date()); //7.拼接存储文件夹 E:/jt-upload/yyyy/MM/dd/HH String filePath = LPath + datePath; //8.判断文件夹是否存在 File file = new File(filePath); if(!file.exists()){ //表示文件不存在 file.mkdirs(); //创建文件夹 } //9.重构文件名,让文件名称尽可能不一致 //获取文件的类型 abc.jpg===>.jpg String fileType = fileName.substring(fileName.lastIndexOf(".")); //使用UUID生成文件名称 sdfsdfsdf-sdfsdfa-sadfasdf-asdfasd String uuid = UUID.randomUUID().toString() .replace("-", ""); /** * 形成文件的完成路径 E:/jt-upload/yyyy/MM/dd/HH/asdfasdfasdf.jpg */ String realPath = filePath + "/" + uuid + fileType; //10.写盘操作 uploadFile.transferTo(new File(realPath)); //11.封装虚拟路径,用户图片的展现 //String uPath = "http://image.jt.com/"; //拼接虚拟路径 //http://image.jt.com/2018/03/02/16/ String realUrlPath = uPath + datePath + "/" + uuid + fileType; result.setUrl(realUrlPath); //赋值url路径 result.setHeight(height+""); result.setWidth(width+""); return result; } catch (Exception e) { result.setError(1); //表示非法图片 return result; } }
3 文件上传的图片回显
3.1 url分析
3.1.1 文件回显的url
说明:文件上传后.根据自定义的虚拟路径获取图片的信息
问题:
文件在本地磁盘下存储
E:\jt-upload\2018\03\02\16\1.jpg
URL的路径
http://image.jt.com/2018/03/02/17/54d2410e4d6646a4882377d0aa0510f3.jpg
问题:本地的磁盘路径与url的路径是不匹配的
解决方法:nginx反向代理技术
3.1.2 反向代理
说明:用户根据虚拟路径请求静态资源,经过Nginx中,将请求转发真实的磁盘路径下.获取静态资源文件.再次由Nginx将结果回传给客户端.这样的方式叫做反向代理
3.2 Nginx介绍
3.2.1 Nginx说明
3.2.2 Nginx下载
3.3 Nginx本地磁盘部署
3.3.1 导入本地
说明:路径不要安装到C盘/不要有空格和中文
3.3.2 Nginx命令
- 以管理员身份运行
2.命令
1.start nginx
2.nginx -s stop
3.nginx -s reload
重启(该命令会提示报错信息)
3.3.3 Nginx配置
#定义图片服务器 root表示转向文件夹 server { listen 80; server_name image.jt.com; location / { root E:\jt-upload; } }
3.3.4 修改hosts文件
说明:修改了host文件后,可以将指定的路径发往本机.
路径:
C:\Windows\System32\drivers\etc/hosts
编辑HOST文件
3.3.5 图片回显调用过程
说明:
- 当根据虚拟路径请求图片时,首先经过Hosts中的配置转向到本地的服务器.否则会去外网中查询image.jt.com的服务器.
- 通过Hosts文件转向本地后,请求会被Nginx拦截实现反向代理.将请求转发到指定的文件夹下 E:/jt-upload下.请求图片信息
- 当获取到图片信息后,返回结果给Nginx.之后再由Nginx回传给客户端.
3.3.6 效果: