做完校园商铺平台O2O小项目1.0,项目来源慕课网,记录一下平时遇到的问题?:
项目1.0中使用SSM技术快速迭代出版校园商铺1.0;同时包含MySQL主从同步实现读写分离,利用SUI Mobile快速实现响应式页面,Redis缓存,数据库加密配置,部署上线等实用技术点。
本项目中使用Logback日志框架,Logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流。
GitHub链接地址
Thumbnailator是一个用来生成图像缩略图的 Java类库,可生成图片缩略图,支持根据一个目录批量生成缩略图,支持图片缩放,区域裁剪,水印,旋转,保持比例等等。
注意:需要封装工具类。
Data Transfer Object,即数据传送对象 。
DTO是一个普通的Java类,它封装了要传送的批量的数据。当客户端需要读取服务器端的数据的时候,服务器端将数据封装在DTO中,这样客户端就可以在一个网络调用中获得它需要的所有数据。
Shop实体类包含了Shop的基本属性,但是在前端操作时,我们希望可以返回操作的结果等信息,这个时候Shop实体类就不能满足需求了,我们将操作结果和Shop等信息统一放到DTO中处理,即可满足当前的需求。
DTO类ShopExecution:
package com.artisan.o2o.dto;
import java.util.List;
import com.artisan.o2o.entity.Shop;
import com.artisan.o2o.enums.ShopStateEnum;
/*
*DTO中还要包含操作商铺的返回结果,单个的实体类无法满足,所以封装到dto中,便于操作
*/
public class ShopExecution {
private int state ;
private String stateInfo;
private int count;
private Shop shop;
/**
* 店铺集合 (查询店铺列表的时候用)
*/
private List<Shop> shopList;
//构造函数,店铺操作失败的时候使用的构造函数
public ShopExecution(ShopStateEnum shopStateEnum) {
this.state = shopStateEnum.getState();
this.stateInfo = shopStateEnum.getStateInfo();
}
//构造函数,店铺操作成功的时候使用的构造函数
public ShopExecution(ShopStateEnum stateEnum, Shop shop) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.shop = shop;
}
//构造函数,店铺操作成功的时候使用的构造函数
public ShopExecution(ShopStateEnum stateEnum, List<Shop> shopList) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.shopList = shopList;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getStateInfo() {
return stateInfo;
}
public void setStateInfo(String stateInfo) {
this.stateInfo = stateInfo;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Shop getShop() {
return shop;
}
public void setShop(Shop shop) {
this.shop = shop;
}
public List<Shop> getShopList() {
return shopList;
}
public void setShopList(List<Shop> shopList) {
this.shopList = shopList;
}
}
枚举类:
使用枚举表述常量数据字典。例如为商品状态定义一个枚举类ShopStateEnum类。
package com.zzt.o2o.enums;
public enum ShopStateEnum {
CHECK(0, "审核中"), OFFLINE(-1, "非法店铺"), SUCCESS(1, "操作成功"), PASS(2, "审核通过"), INNER_ERROR(-1001, "操作失败"), NULL_SHOPID(-1002, "ShopId为空"), NULL_SHOP_INFO(-1003, "传入了空的信息");
private int state;
private String stateInfo;
private ShopStateEnum(int state, String stateInfo) {
this.state = state;
this.stateInfo = stateInfo;
}
public int getState() {
return state;
}
public String getStateInfo() {
return stateInfo;
}
// 定义换成pulic static 暴漏给外部,通过state获取ShopStateEnum
public static ShopStateEnum stateOf(int state) {
for (ShopStateEnum stateEnum : values()) {
if(stateEnum.getState() == state){
return stateEnum;
}
}
return null;
}
}
GitHub地址:
https://github.com/penggle/kaptcha
Kaptcha是基于SimpleCaptcha的开源项目。通过调整Kaptcha配置可以生成各种样式的验证码。
Kaptcha提供的功能如下:
验证码的字体
验证码字体的大小
验证码字体的字体颜色
验证码内容的范围
验证码图片的大小,边框,边框粗细,边框颜色
验证码的干扰线
验证码的样式
使用jackson将前端传过来的json数据格式转换为对应的pojo
GitHub:https://github.com/FasterXML/jackson-databind
设置图片:我的数据库中存储的并不是全部路径,而是部分路径,因此在传给前端路径时并不完全,因此我们在tomcat的server.xml文件中配置,解决方案:
在idea不想es直接更改,打开tomca文件夹找到server.xml文件在最后设置一个,意思相当于当我们遇到第一个参数的路径时转第二个路径就是当遇到/A就转为/A/B/C/这种
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
使用 DES 对数据库的用户名和密码进行加密。DES是一种对称加密算法。
步骤:
使用 MD5 加密算法 对用户信息进行加密。
package com.zzt.o2o.interceptor.shopadmin;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.zzt.o2o.entity.Shop;
/**
* 商家不能去操纵不属于它管理的店铺
* @author zhan
*
*/
public class ShopPermissionInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
Shop currentShop = (Shop) request.getSession().getAttribute(
"currentShop");
@SuppressWarnings("unchecked")
//从session中获取当前用户可操作的店铺列表
List<Shop> shopList = (List<Shop>) request.getSession().getAttribute(
"shopList");
if (currentShop != null && shopList != null) {
for (Shop shop : shopList) {
//如果当前店铺在可操作的列表则返回true,进行接下来的用户操作
if (shop.getShopId() == currentShop.getShopId()) {
return true;
}
}
}
//不满足返回false
return false;
}
}
package com.zzt.o2o.interceptor.shopadmin;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.zzt.o2o.entity.PersonInfo;
/**
* 店家管理系统登录验证拦截器
* @author zhan
*
*/
public class ShopLoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
Object userObj = request.getSession().getAttribute("user");
if (userObj != null) {
PersonInfo user = (PersonInfo) userObj;
if (user != null && user.getUserId() != null
&& user.getUserId() > 0 && user.getEnableStatus() == 1)
return true;
}
//若不满足登录验证,则直接跳转到账号登录页面
PrintWriter out = response.getWriter();
out.println("");
out.println("");
out.println("");
return false;
}
}