ego商城項目學習總結+出現問題及解決

1. SpringBoot整合jsp進行頁面訪問出現找不到file文件

問題:css

 

 

 

前提是:跳轉代碼沒有問題,以下圖java

 

 

 

 

解決1:配置springMVC視圖解析器

 

 

 

解決2:來源於Idea的自身bug

 

 

 

 

 

2. ego項目總結

第一天

(1)SpringSecurity結合ego項目進行操做步驟

1. 搭建ego_commons

2. 編寫ego_api

ego_api中建立com.ego.dubbo.service.ManagerDubboService實現查詢用戶功能nginx

public interface ManagerDubboService {

    /**
     * 根據用戶名查詢用戶信息
     * @param username 用戶名
     * @return 用戶信息
     */
    Manager selectManagerByUsername(String username);
}web

3. 編寫ego_provide

ego_provide中建立com.ego.dubbo.service.impl.ManagerDubboServiceImpl 實現類spring

ps:注意(provider中)此處的@Service註解導入的是apache數據庫

@Service
public class ManagerDubboServiceImpl implements ManagerDubboService {

    @Autowired
    private ManagerMapper managerMapper;

    @Override
    public Manager selectManagerByUsername(String username) {
        ManagerExample example = new ManagerExample();
        example.createCriteria().andUsernameEqualTo(username);
        List<Manager> managers = managerMapper.selectByExample(example);
        if(managers!=null && managers.size()>0){
            return managers.get(0);
        }
        return null;
    }
}apache

修改啓動類,添加MapperScanjson

@SpringBootApplication
@EnableDubbo
@MapperScan("com.ego.mapper")
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class,args);
    }
}api

 

 

4. 編寫ego_manage

建立com.ego.config.SecurityConfig數組

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder getPwdEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginProcessingUrl("/login")
                .successForwardUrl("/loginSuccess")
                .loginPage("/");
        http.authorizeRequests()
                // 放行靜態資源
                .antMatchers("/","/css/**","/js/**").permitAll()
                .anyRequest().authenticated();

        http.csrf().disable();
    }
}

建立com.ego.controller.PageController,添加跳轉成功後的控制

/**
 * 登陸成功後跳轉的控制器
 */
@RequestMapping("/loginSuccess")
@ResponseBody
public EgoResult loginSuccess(){
    return EgoResult.ok();
}

 

 

建立com.ego.service.impl.LoginServiceImpl,實現自定義登陸邏輯

// Consumer的註解是Spring的
@Service
public class LoginServiceImpl implements UserDetailsService {

    // 此註解用apache的
    @Reference
    private ManagerDubboService managerDubboService;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        Manager manager = managerDubboService.selectManagerByUsername(s);
        if(manager == null){
            throw new UsernameNotFoundException("用戶不存在");
        }
        return new User(s,manager.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("不涉及權限"));
    }
}

 

 

次日

(1)事務管理部分(事務須要放到provider中進行處理)

eg.批量修改商品狀態

@Override
// 監測異常,當有異常時會進行事務回滾,聲明式事務註解
@Transactional
public int updateStatusByIds(long[] ids, byte status) throws DaoException{
    int index = 0;
    for (long id : ids) {
        TbItem tbItem = new TbItem();
        tbItem.setId(id);
        tbItem.setStatus(status);
        // 保證批量修改時間相同
        tbItem.setUpdated(new Date());
        index += tbItemMapper.updateByPrimaryKeySelective(tbItem);
    }
    // 如何判斷是否批量修改爲功?
    // 根據索引數 = ids[] 數組的長度
    if (index == ids.length){
        return 1;
    }
    // 若是失敗,須要事務回滾(1.拋出自定義異常2.方法拋出異常3.添加註解Transaction,監聽異常從而作出回滾操做)
    throw new DaoException("修改失敗");
}

 

事務管理三步:1.拋出自定義異常2.方法拋出異常3.添加註解Transaction,監聽異常從而作出回滾操做

 

ps:假若拋出的自定義異常(DaoException)不是繼承RuntimeException而是繼承Exception,則此時的事務註解爲:@Transaction(rollbackFor = Exception.class)

 

第三天

(1)安裝Fastdfs,而且適配Nginx

按照網上步驟進行便可

(2)經過KindEditor上傳圖片,上傳至fastdfs的存儲器中

1. 搭建Fastdfs服務器,實現上傳功能

首先在ego_commons添加fastdfs依賴,其次添加FastDFSClient工具類

<dependencies>
    <dependency>
        <groupId>cn.bestwu</groupId>
        <artifactId>fastdfs-client-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

 

FastDFSClient工具類:

package com.ego.commons.utils;

import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;

import java.io.*;

/**
 * FastDFS分佈式文件系統操做客戶端.
 */
public class FastDFSClient {

    //private static final String CONF_FILENAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
    private static final String CONF_FILENAME = "fdfs_client.conf";

    private static StorageClient storageClient = null;


    /**
     * 只加載一次.
     */
    static {
        try {
            ClientGlobal.init(CONF_FILENAME);
            TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            storageClient = new StorageClient(trackerServer, storageServer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param inputStream
     *    上傳的文件輸入流
     * @param fileName
     *    上傳的文件原始名
     * @return
     */
    public static String[] uploadFile(InputStream inputStream, String fileName) {
        try {
            // 文件的元數據
            NameValuePair[] meta_list = new NameValuePair[2];
            // 第一組元數據,文件的原始名稱
            meta_list[0] = new NameValuePair("file name", fileName);
            // 第二組元數據
            meta_list[1] = new NameValuePair("file length", inputStream.available()+"");
            // 準備字節數組
            byte[] file_buff = null;
            if (inputStream != null) {
                // 查看文件的長度
                int len = inputStream.available();
                // 建立對應長度的字節數組
                file_buff = new byte[len];
                // 將輸入流中的字節內容,讀到字節數組中。
                inputStream.read(file_buff);
            }
            // 上傳文件。參數含義:要上傳的文件的內容(使用字節數組傳遞),上傳的文件的類型(擴展名),元數據
            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     *
     * @param file
     *            文件
     * @param fileName
     *            文件名
     * @return 返回Null則爲失敗
     */
    public static String[] uploadFile(File file, String fileName) {
        FileInputStream fis = null;
        try {
            NameValuePair[] meta_list = null; // new NameValuePair[0];
            fis = new FileInputStream(file);
            byte[] file_buff = null;
            if (fis != null) {
                int len = fis.available();
                file_buff = new byte[len];
                fis.read(file_buff);
            }

            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
        } catch (Exception ex) {
            return null;
        }finally{
            if (fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根據組名和遠程文件名來刪除一個文件
     *
     * @param groupName
     *            例如 "group1" 若是不指定該值,默認爲group1
     * @param remoteFileName
     *            例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
     * @return 0爲成功,非0爲失敗,具體爲錯誤代碼
     */
    public static int deleteFile(String groupName, String remoteFileName) {
        try {
            int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
            return result;
        } catch (Exception ex) {
            return 0;
        }
    }

    /**
     * 修改一個已經存在的文件
     *
     * @param oldGroupName
     *            舊的組名
     * @param oldFileName
     *            舊的文件名
     * @param file
     *            新文件
     * @param fileName
     *            新文件名
     * @return 返回空則爲失敗
     */
    public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
        String[] fileids = null;
        try {
            // 先上傳
            fileids = uploadFile(file, fileName);
            if (fileids == null) {
                return null;
            }
            // 再刪除
            int delResult = deleteFile(oldGroupName, oldFileName);
            if (delResult != 0) {
                return null;
            }
        } catch (Exception ex) {
            return null;
        }
        return fileids;
    }

    /**
     * 文件下載
     *
     * @param groupName 卷名
     * @param remoteFileName 文件名
     * @return 返回一個流
     */
    public static InputStream downloadFile(String groupName, String remoteFileName) {
        try {
            byte[] bytes = storageClient.download_file(groupName, remoteFileName);
            InputStream inputStream = new ByteArrayInputStream(bytes);
            return inputStream;
        } catch (Exception ex) {
            return null;
        }
    }

    public static NameValuePair[] getMetaDate(String groupName, String remoteFileName){
        try{
            NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
            return nvp;
        }catch(Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 獲取文件後綴名(不帶點).
     *
     * @return 如:"jpg" or "".
     */
    private static String getFileExt(String fileName) {
        if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
            return "";
        } else {
            return fileName.substring(fileName.lastIndexOf(".") + 1); // 不帶最後的點
        }
    }
}

 

ego_manage中添加PicService及實現類

功能:實現上傳二進制文件(圖片)

思路:1.manage中的返回值爲頁面須要的信息,所以須要查看KindEditor文檔,可知其爲json格式數據且key值不一樣--》採用Map集合存儲

  2.nginxHostcommons中定義application-commons.yml文件,經過SpringMVC視圖解析器來在manage中激活,以下圖。此步驟爲軟編碼

 

 

 

在此manage項目引用的時候需採用鍵值對的方式

 

package com.ego.service;

import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

public interface PicService {
    /**
     * 上傳二進制文件(圖片)
     * @param file
     * @return
     */
    Map<String,Object> upload(MultipartFile file);

}

 

package com.ego.service.impl;

import com.ego.commons.utils.FastDFSClient;
import com.ego.service.PicService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Service
public class PicServiceImpl implements PicService {

    @Value("${ego.fastdfs.nginx}")
    private String nginxHost;
    @Override
    public Map<String, Object> upload(MultipartFile file) {
        Map<String,Object> map = new HashMap<>();
        try {
            String[] results = FastDFSClient.uploadFile(file.getInputStream(), file.getOriginalFilename());
            map.put("error",0);
            // 測試環境和上線環境不一致的狀況:經過軟編碼解決
            map.put("url",nginxHost+results[0]+"/"+results[1]);
            return map;
        } catch (IOException e) {
            e.printStackTrace();
        }
        map.put("error",1);
        map.put("message","錯誤信息");
        return map;
    }
}

 

 

ego_manage中添加PicController控制器

package com.ego.controller;

import com.ego.service.PicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

@Controller
public class PicController {

    @Autowired
    private PicService picService;

    @RequestMapping("/pic/upload")
    @ResponseBody
    public Map<String,Object> update(MultipartFile uploadFile){
        return picService.upload(uploadFile);
    }
}

 

(3)根據EasyUITree添加選擇類目(頁面需求)

按照頁面所要獲取到的EasyUITree建立類TbItemCat

ego_api中添加TbItemCatDubboService

package com.ego.dubbo.service;

import com.ego.pojo.TbItemCat;

import java.util.List;

public interface TbItemCatDubboService {
    /**
     * 根據父id查詢類目信息
     * @param pid
     * @return
     */
    public List<TbItemCat> selectByPid(Long pid);
}

ego_provider中添加TbItemCatDubboServiceImpl實現類

package com.ego.dubbo.service.impl;

import com.ego.dubbo.service.TbItemCatDubboService;
import com.ego.dubbo.service.TbItemDubboService;
import com.ego.mapper.TbItemCatMapper;
import com.ego.pojo.TbItemCat;
import com.ego.pojo.TbItemCatExample;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Service
public class TbItemCatDubboServiceImpl implements TbItemCatDubboService {
    @Autowired
    private TbItemCatMapper tbItemCatMapper;
    @Override
    public List<TbItemCat> selectByPid(Long pid) {
        TbItemCatExample example = new TbItemCatExample();
        example.createCriteria().andParentIdEqualTo(pid);
        return tbItemCatMapper.selectByExample(example);
    }
}

ego_manage中添加TbItemCatService及實現類

思路:將TbItemCat類型的數據放到EasyUITree類型中,須要清楚EasyUITree結構

package com.ego.service;

import com.ego.commons.pojo.EasyUITree;

import java.util.List;

public interface TbItemCatService {
    List<EasyUITree> showTree(Long pid);
}

package com.ego.service.impl;

import com.ego.commons.pojo.EasyUITree;
import com.ego.dubbo.service.TbItemCatDubboService;
import com.ego.pojo.TbItemCat;
import com.ego.service.TbItemCatService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class TbItemCatServiceImpl implements TbItemCatService {
    @Reference
    private TbItemCatDubboService tbItemCatDubboService;
    @Override
    public List<EasyUITree> showTree(Long pid) {
        List<EasyUITree> list = new ArrayList<>();
        List<TbItemCat> tbItemCats = tbItemCatDubboService.selectByPid(pid);
        for (TbItemCat tbItemCat:tbItemCats) {
            EasyUITree easyUITree = new EasyUITree();
            easyUITree.setId(tbItemCat.getId());
            easyUITree.setText(tbItemCat.getName());
            easyUITree.setState(tbItemCat.getIsParent()?"closed":"open");
            list.add(easyUITree);
        }
        return list;
    }
}

ego_manage中添加TbItemCatController

開始在數據庫表中規定初始id0,需經過@RequestParam(defaultValue = "0")聲明

package com.ego.controller;

import com.ego.commons.pojo.EasyUITree;
import com.ego.service.TbItemCatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;

@Controller
public class TbItemCatController {
    @Autowired
    private TbItemCatService tbItemCatService;
    @RequestMapping("/item/cat/list")
    @ResponseBody
    public List<EasyUITree> showTree(@RequestParam(defaultValue = "0") Long id){
        return tbItemCatService.showTree(id);
    }
}

 

(4)功能:獲取(編輯商品信息中的商品描述tbItemDesc

思路:兩個表查詢(TbItemTbItemDesc)——》考慮事務,根據商品id獲取到商品描述

思路爲循序漸進(ego_api中聲明接口——》provider作底層調用Mapper實現數據供給——》manage作業務需求,頁面須要哪一種類型數據就給哪一種數據類型)

(5)功能:提交更新的商品信息

流程演示:

ego_api

int update(TbItem tbItem,TbItemDesc tbItemDesc) throws DaoException;

 

provider

@Override
@Transactional
public int update(TbItem tbItem, TbItemDesc tbItemDesc) throws DaoException{
    try {
        int index1 = tbItemMapper.updateByPrimaryKeySelective(tbItem);
        if(index1==1){
            int index2 = tbItemDescMapper.updateByPrimaryKeySelective(tbItemDesc);
            if(index2==1){
                return 1;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    throw new DaoException("更新失敗");
}

 

 

manage

/**
 * 更新商品信息
 * @param tbItem
 * @param desc
 * @return
 */
EgoResult update(TbItem tbItem,String desc);

 

@Override
public EgoResult update(TbItem tbItem, String desc) {
    Date date = new Date();
    tbItem.setUpdated(date);

    TbItemDesc tbItemDesc = new TbItemDesc();
    tbItemDesc.setItemId(tbItem.getId());
    tbItemDesc.setItemDesc(desc);
    tbItemDesc.setCreated(tbItem.getCreated());
    tbItemDesc.setUpdated(date);

    try {
        int index = tbItemDubboService.update(tbItem, tbItemDesc);
        if(index==1){
            return EgoResult.ok();
        }
    } catch (DaoException e) {
        e.printStackTrace();
    }
    return EgoResult.error();
}

controller

 

@RequestMapping("/rest/item/update")
@ResponseBody
public EgoResult update(TbItem tbItem,String desc){
    return tbItemService.update(tbItem,desc);}

相關文章
相關標籤/搜索