本文是《Solo 从设计到实现》的一个章节,该系列文章将介绍 Solo 这款 Java 博客系统是如何从无到有的,希望大家能通过它对 Solo 从设计到实现有个直观地了解、能为想参与贡献的人介绍清楚项目,也希望能为给
重复发明重新定义博客系统的人做个参考 ❤️
后台切换
管理员可以在管理后台切换皮肤,并且可以为桌面端和移动端指定不同的皮肤。配置保存在 option 表中,对应的 id 为 skinDirName
和 mobileSkinDirName
。
设置好以后选用的皮肤名称会被写入 Cookie,以便前台请求时可以快速获取到皮肤信息,避免查库。
后台切换皮肤请求处理 SkinConsole#updateSkin 方法:
public void updateSkin(final RequestContext context) { final JsonRenderer renderer = new JsonRenderer(); context.setRenderer(renderer); try { final JSONObject requestJSONObject = context.requestJSON(); final JSONObject skin = requestJSONObject.getJSONObject(Option.CATEGORY_C_SKIN); final JSONObject ret = new JSONObject(); renderer.setJSONObject(ret); skinMgmtService.updateSkin(skin); final Response response = context.getResponse(); final Cookie skinDirNameCookie = new Cookie(Common.COOKIE_NAME_SKIN, skin.getString(Option.ID_C_SKIN_DIR_NAME)); skinDirNameCookie.setMaxAge(60 * 60); // 1 hour skinDirNameCookie.setPath("/"); response.addCookie(skinDirNameCookie); final Cookie mobileSkinDirNameCookie = new Cookie(Common.COOKIE_NAME_MOBILE_SKIN, skin.getString(Option.ID_C_MOBILE_SKIN_DIR_NAME)); mobileSkinDirNameCookie.setMaxAge(60 * 60); // 1 hour mobileSkinDirNameCookie.setPath("/"); response.addCookie(mobileSkinDirNameCookie); ret.put(Keys.STATUS_CODE, true); ret.put(Keys.MSG, langPropsService.get("updateSuccLabel")); } catch (final ServiceException e) { LOGGER.log(Level.ERROR, e.getMessage(), e); final JSONObject jsonObject = new JSONObject().put(Keys.STATUS_CODE, false); renderer.setJSONObject(jsonObject); jsonObject.put(Keys.MSG, langPropsService.get("updateFailLabel")); } }
前台切换
为了方便预览皮肤,访客可从前台自行切换皮肤,仅在首页路径下有效:/skin=xxx
。实现逻辑是在 IndexProcessor#showIndex 时获取 skin 参数,然后用该参数指定的皮肤进行渲染,并写入 Cookie 以备其他页面请求使用。
String specifiedSkin = Skins.getSkinDirName(context); if (StringUtils.isBlank(specifiedSkin)) { final JSONObject skinOpt = optionQueryService.getSkin(); specifiedSkin = Solos.isMobile(request) ? skinOpt.optString(Option.ID_C_MOBILE_SKIN_DIR_NAME) : skinOpt.optString(Option.ID_C_SKIN_DIR_NAME); } request.setAttribute(Keys.TEMAPLTE_DIR_NAME, specifiedSkin); Cookie cookie; if (!Solos.isMobile(request)) { cookie = new Cookie(Common.COOKIE_NAME_SKIN, specifiedSkin); } else { cookie = new Cookie(Common.COOKIE_NAME_MOBILE_SKIN, specifiedSkin); } cookie.setMaxAge(60 * 60); // 1 hour cookie.setPath("/"); response.addCookie(cookie);
解析所需皮肤
请求到服务端后会优先从 Cookie 中获取皮肤名,如果为空再从查 option 表获取管理员指定的皮肤。同时也会判断是否是移动端,移动端请求需要使用移动端指定皮肤。实现代码在 SkinHandler#resolveSkinDir:
private void resolveSkinDir(final Request request) { String skin = Skins.getSkinDirNameFromCookie(request); if (StringUtils.isBlank(skin)) { final BeanManager beanManager = BeanManager.getInstance(); final OptionQueryService optionQueryService = beanManager.getReference(OptionQueryService.class); final JSONObject skinOpt = optionQueryService.getSkin(); if (Solos.isMobile(request)) { if (null != skinOpt) { skin = skinOpt.optString(org.b3log.solo.model.Option.ID_C_MOBILE_SKIN_DIR_NAME); } else { skin = org.b3log.solo.model.Option.DefaultPreference.DEFAULT_MOBILE_SKIN_DIR_NAME; } } else { if (null != skinOpt) { skin = skinOpt.optString(org.b3log.solo.model.Option.ID_C_SKIN_DIR_NAME); } else { skin = org.b3log.solo.model.Option.DefaultPreference.DEFAULT_SKIN_DIR_NAME; } } } request.setAttribute(Keys.TEMAPLTE_DIR_NAME, skin); }
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于