基於SpringBoot從零構建博客網站 - 新增創建、修改、刪除專欄功能


守望博客是支持創建專欄的功能,即可以將一系列相關的文章歸檔到專欄中,方便用戶管理和查閱文章。這里主要講解專欄的創建、修改和刪除功能,至於專欄還涉及其它的功能,例如關注專欄等后續會穿插着介紹。

1、創建專欄

接收和處理專欄相關功能的操作的方法會放在GroupController類中,首先創建專欄的頁面為:

這里有兩個地方需要特別說明:

第一這個分類數據,此處分類數據正是本博客網站的分類數據,這個分類數據是系統初始化時加入的,這個初始化的功能后續會加入,目前此處就是提前將數據先寫入到數據庫中,例如本博客作為技術類博客,則分類有:前端、架構、區塊鏈、雲計算等。

然后這個分類信息數據一般初始化后,就不會有修改,則這個數據是放入緩存中,即,CategoryCache:

/**
 * 緩存分類信息
 * 分類信息放到系統永久緩存中,存放形式為:"_CATEGORY" + categoryId為key,value為分類信息對象
 *
 * @author lzj
 * @since 1.0
 * @date [2019-07-22]
 */
@Slf4j
@DependsOn("categoryService")
@Component("categoryCache")
public class CategoryCache implements ICache<List<Category>> {

    /**
     * 注入基於Spring提供的Cache接口實例,默認由Ehcache實現
     * TODO 以后也可以是Redis、Memcached提供實現
     */
    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private ICategoryService categoryService;

    /**
     * 緩存實例
     */
    private Cache cache;

    /**
     * key的前綴
     */
    private String keyPrefix = "_CATEGORY";

    /**
     * 分類信息根節點ID
     */
    public static final String ROOT_CATEGORY_ID = "0";

    @PostConstruct
    public void init() {
        // 獲取系統永久緩存實例
        cache = cacheManager.getCache(Const.CACHE_SYSTEM_ETERNAL);
        log.info("獲取系統永久緩存實例");

        log.debug("開始加載父分類信息");
        List<Category> categorys = categoryService.getByParentId(ROOT_CATEGORY_ID);
        if (categorys != null && !categorys.isEmpty()) {
            put(keyPrefix + ROOT_CATEGORY_ID, categorys);
        }
        log.debug("加載完畢父分類信息");
    }

    @Override
    public List<Category> get(Object key) {
        Cache.ValueWrapper valueWrapper = cache.get(keyPrefix + key);
        if (valueWrapper == null) {
            // 從數據庫重新加載一次
            List<Category> categorys = categoryService.getByParentId((String) key);
            if (categorys == null) {
                return null;
            }

            // 再次放到緩存中
            put(key, categorys);

            return categorys;
        }
        return (List<Category>) valueWrapper.get();
    }

    @Override
    public void put(Object key, List<Category> value) {
        cache.put(keyPrefix + key, value);
    }

    @Override
    public void remove(Object key) {
        cache.evict(keyPrefix + key);
    }
}

第二需要說明的是,此處的上傳控制是用的webuploader,利用webuploader處理的上傳文件的話,需要按如下方式初始化:

$(function() {
    var _list = $('#fileList');
    var ratio = window.devicePixelRatio || 1;
    var thumbnailWidth = 100 * ratio;
    var thumbnailHeight = 100 * ratio;

    // 初始化Web Uploader
    var uploader = WebUploader.create({

        // 選完文件后,是否自動上傳。
        auto: true,

        // swf文件路徑
        swf: '${rc.contextPath}/static/plugins/webuploader/Uploader.swf',

        // 文件接收服務端。
        server: '${rc.contextPath}/upload',

        // 選擇文件的按鈕。可選。
        // 內部根據當前運行是創建,可能是input元素,也可能是flash.
        pick: '#filePicker',

        fileVal: "_uploadFile",

        formData: {
            _distId:'_distId',
            _distType:'_groupLogo',
        },

        // 只允許選擇圖片文件。
        accept: {
            title: 'Images',
            extensions: 'gif,jpg,jpeg,png',
            mimeTypes: 'image/*'
        },

        fileNumLimit: 1,
        fileSizeLimit: 2 * 1024 * 1024,    // 2 M
        fileSingleSizeLimit: 2 * 1024 * 1024    // 2 M
    });

    // 當有文件添加進來的時候
    uploader.on( 'fileQueued', function( file ) {
        var li = $(
            '<div id="' + file.id + '" class="file-item thumbnail text-center">' +
            '<img>' +
            // '<div class="info">' + file.name + '</div>' +
            '</div>'
            ),
            img = li.find('img');


        // _list為容器jQuery實例
        _list.append( li );

        // 創建縮略圖
        // 如果為非圖片文件,可以不用調用此方法。
        // thumbnailWidth x thumbnailHeight 為 100 x 100
        uploader.makeThumb( file, function( error, src ) {
            if ( error ) {
                img.replaceWith('<span>不能預覽</span>');
                return;
            }

            img.attr( 'src', src );
        }, thumbnailWidth, thumbnailHeight );
    });

    // 文件上傳過程中創建進度條實時顯示。
    uploader.on( 'uploadProgress', function( file, percentage ) {
    });

    // 文件上傳成功,給item添加成功class, 用樣式標記上傳成功。
    uploader.on( 'uploadSuccess', function(file, response) {
        $( '#'+file.id ).addClass('upload-state-done');
        $( '#'+file.id ).append('<a class="del" href="javascript:void(0);">刪除</a>' )
        $("#logo").val(response.url);
    });

    // 文件上傳失敗,顯示上傳出錯。
    uploader.on( 'uploadError', function( file ) {
        var li = $( '#'+file.id ),
            error = li.find('div.error');

        // 避免重復創建
        if ( !error.length ) {
            error = $('<div class="error"></div>').appendTo( li );
        }

        error.text('上傳失敗');
    });

    // 完成上傳完了,成功或者失敗,先刪除進度條。
    uploader.on( 'uploadComplete', function( file ) {
    });

    // 執行刪除方法
    _list.on('click', '.del', function () {
        var Id = $(this).parent().attr('id');
        //刪除該圖片
        uploader.removeFile(uploader.getFile(Id, true));
        $(this).parent().remove();
        $("#logo").val("");
    });
});

這里后台需要處理專欄的Logo圖片的信息,根據上一章節的方式處理,即有UploadGroupLogoHandler類,如:

/**
 * 上傳專欄Logo處理類
 *
 * @author lzj
 * @since 1.0
 * @date [2019-07-23]
 */
@Slf4j
@Component("_groupLogo")
public class UploadGroupLogoHandler implements IUploadHandler {

    @Resource(name = "configCache")
    private ICache<Config> configCache;

    @Override
    public Object upload(MultipartFile file, String distType, String userId) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            // 獲取圖片的原始名稱
            String originalName = file.getOriginalFilename();

            // 判斷圖片的類型
            if (!(originalName.endsWith(".jpg") || originalName.endsWith(".JPG") || originalName.endsWith(".png") || originalName.endsWith(".PNG") || originalName.endsWith(".gif") || originalName.endsWith(".GIF") || originalName.endsWith(".jpeg") || originalName.endsWith(".JPEG"))) {
                throw new TipException("您上傳的圖片類型有誤,請上傳格式為jpg、png或gif");
            }

            // 獲取圖片的大小
            long fileSize = file.getSize();

            // 圖片大小不能超過2M, 2M = 2 * 1024 * 1024B = 2097152B
            if (fileSize > 2097152L) {
                throw new TipException("您上傳的圖片超過2M");
            }

            Config config = configCache.get(Config.CONFIG_IMG_GROUP_LOGO_PATH);
            // 保存頭像的根目錄
            String basePath = config.getConfigValue();
            if (!(basePath.endsWith("/") || basePath.endsWith("\\"))) {
                basePath += "/";
            }

            // 根據當前時間構建yyyyMM的文件夾,建立到月的文件夾
            String dateDirName = DateUtil.date2Str(new Date(), DateUtil.YEAR_MONTH_FORMAT);
            basePath += dateDirName;

            File imageDir = new File(basePath);
            if (!imageDir.exists()) {
                imageDir.mkdirs();
            }

            String fileNewName = IdGenarator.guid() + originalName.substring(originalName.lastIndexOf("."));
            FileUtil.copy(file.getInputStream(), new FileOutputStream(new File(imageDir, fileNewName)));

            result.put("url", dateDirName + "/" + fileNewName);
            result.put("msg", "上傳成功");
        } catch (TipException e) {
            result.put("url", "");
            result.put("msg", e.getMessage());
        } catch (Exception e) {
            log.error("上傳失敗", e);
            result.put("url", "");
            result.put("msg", "上傳失敗");
        }
        return result;
    }

    @Override
    public void download(String fileId, HttpServletResponse response) throws Exception {
    }

    @Override
    public Object list(String distType, String userId) throws Exception {
        return null;
    }
}

最后創建專欄的核心代碼如下:

/**
 * 創建專欄
 *
 * @param request
 * @param session
 * @return
 */
@RequestMapping(value = "/user/group/add", method = RequestMethod.POST)
@ResponseBody
public Result add(HttpServletRequest request, HttpSession session) {
    Result result = new Result();
    try {
        // 接收參數
        String categoryId = request.getParameter("categoryId");
        String name = request.getParameter("name");
        String logo = request.getParameter("logo");
        String introduce = request.getParameter("introduce");

        // 校驗參數
        if (StringUtils.isEmpty(categoryId) || StringUtils.isEmpty(name) || StringUtils.isEmpty(logo) || StringUtils.isEmpty(introduce)) {
            throw new TipException("缺少必要參數");
        }

        // 獲取登錄信息
        User tempUser = (User) session.getAttribute(Const.SESSION_USER);
        String userId = tempUser.getUserId();

        // 構建專欄對象
        Group group = new Group();
        group.setGroupId(IdGenarator.longIdStr());
        group.setName(name);
        group.setLogo(logo);
        group.setIntroduce(introduce);
        group.setCategoryId(categoryId);
        group.setCreator(userId);
        group.setCreateTime(new Date());
        // 從系統配置項獲取專欄是否審核
        Config config = configCache.get(Config.CONFIG_GROUP_AUDIT);
        if (config != null && "1".equals(config.getConfigValue())) {
            // 需要審核
            group.setStatus(Group.STATUS_NO);
        } else {
            // 不需要審核
            group.setStatus(Group.STATUS_SUCCESS);
        }

        // 保存專欄信息
        boolean flag = groupService.save(group);
        if (!flag) {
            throw new TipException("創建專欄失敗");
        }

        result.setCode(Result.CODE_SUCCESS);
        result.setMsg("成功創建專欄");
    } catch (TipException e) {
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg(e.getMessage());
    } catch (Exception e) {
        log.error("創建專欄失敗", e);
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg("創建專欄失敗");
    }
    return result;
}

2、修改專欄

有了前面新增專欄的基礎,其實修改專欄的功能就相對簡單很多了,此處只列出處理修改的核心代碼即可,如:

/**
 * 修改專欄
 *
 * @param groupId
 * @param request
 * @param session
 * @return
 */
@RequestMapping(value = "/user/group/edit/{groupId}", method = RequestMethod.POST)
@ResponseBody
public Result edit(@PathVariable("groupId") String groupId, HttpServletRequest request, HttpSession session) {
    Result result = new Result();
    try {
        // 根據id獲取專欄信息
        Group group = groupService.getById(groupId);
        if (group == null || StringUtils.isEmpty(group.getGroupId())) {
            log.error("groupId: " + groupId + ": 該專欄不存在");
            throw new TipException("該專欄不存在");
        }

        // 獲取用戶信息
        User tempUser = (User) session.getAttribute(Const.SESSION_USER);
        String userId = tempUser.getUserId();
        if (!userId.equals(group.getCreator())) {
            log.error("userId: " + userId + "修改別人的groupId: " + groupId);
            throw new TipException("不能修改別人的專欄");
        }

        // 接收參數
        String categoryId = request.getParameter("categoryId");
        String name = request.getParameter("name");
        String introduce = request.getParameter("introduce");
        String logo = request.getParameter("logo");

        // 校驗參數
        if (StringUtils.isEmpty(categoryId) || StringUtils.isEmpty(name) || StringUtils.isEmpty(introduce)) {
            throw new TipException("缺少必要參數");
        }

        group.setCategoryId(categoryId);
        group.setName(name);
        group.setIntroduce(introduce);
        if (!StringUtils.isEmpty(logo)) {
            group.setLogo(logo);
        }
        group.setUpdateTime(new Date());

        // 修改
        boolean flag = groupService.updateById(group);
        if (!flag) {
            throw new TipException("修改專欄失敗");
        }

        result.setCode(Result.CODE_SUCCESS);
        result.setMsg("修改專欄成功");
    } catch (TipException e) {
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg(e.getMessage());
    } catch (Exception e) {
        log.error("修改專欄失敗", e);
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg("修改專欄失敗");

    }
    return result;
}

3、刪除專欄

刪除專欄功能是很簡單的,但是需要考慮到,刪除專欄后,需要處理其它與之關聯的數據信息,此處由於其它模塊還沒有完成,所以先將加一個TODO,后續會再處理。那刪除專欄的核心代碼如下:

/**
 * 根據ID刪除專欄
 *
 * @param groupId
 * @param session
 * @return
 */
@RequestMapping(value = "/user/group/delete/{groupId}", method = RequestMethod.GET)
@ResponseBody
public Result delete(@PathVariable("groupId") String groupId, HttpSession session) {
    Result result = new Result();
    try {
        // 根據id獲取專欄信息
        Group group = groupService.getById(groupId);
        if (group == null || StringUtils.isEmpty(group.getGroupId())) {
            log.error("groupId: " + groupId + ": 該專欄不存在");
            throw new TipException("該專欄不存在");
        }

        // 獲取用戶信息
        User tempUser = (User) session.getAttribute(Const.SESSION_USER);
        String userId = tempUser.getUserId();
        if (!userId.equals(group.getCreator())) {
            log.error("userId: " + userId + "刪除別人的groupId: " + groupId);
            throw new TipException("不能刪除別人的專欄");
        }

        // 刪除
        boolean flag = groupService.removeById(groupId);
        if (!flag) {
            throw new TipException("刪除專欄失敗");
        }

        // TODO 刪除專欄后,需要處理其它關聯的數據,由於其它模塊還沒有,此處后續處理

        result.setCode(Result.CODE_SUCCESS);
        result.setMsg("刪除專欄成功");
    } catch (TipException e) {
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg(e.getMessage());
    } catch (Exception e) {
        log.error("刪除專欄失敗", e);
        result.setCode(Result.CODE_EXCEPTION);
        result.setMsg("刪除專欄失敗");
    }
    return result;
}

關注我

以你最方便的方式關注我:
微信公眾號:
架構與我


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM