通用mapper、圖片上傳、nginx

項羽齊發表於2018-03-15

通用Mapper介紹

1.1 通用Mapper入門案例

1.1.1 通用的findCount()

  1. 編輯介面

 

/**
     * 需求:自己實現一個通用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.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.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命令

  1. 以管理員身份執行

 

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 圖片回顯呼叫過程

 

 

說明:

  1. 當根據虛擬路徑請求圖片時,首先經過Hosts中的配置轉向到本地的伺服器.否則會去外網中查詢image.jt.com的伺服器.
  2. 通過Hosts檔案轉向本地後,請求會被Nginx攔截實現反向代理.將請求轉發到指定的資料夾下 E:/jt-upload.請求圖片資訊
  3. 當獲取到圖片資訊後,返回結果給Nginx.之後再由Nginx回傳給客戶端.

3.3.6 效果:

 

相關文章