Java 电商项⽬⾯试--商品模块
⾯试:商品模块技术要点 1、POJO、BO、VO抽象模型 2、⾼效分页及动态排序 3、FTP服务对接、富⽂本上传
⼀、商品模块功能
前台功能:
1、产品搜索
2、动态排序列表
3、商品详情读取配置文件失败
林妙可图片后台功能:
1、商品列表
2、商品搜索
3、图⽚上传
4、增加商品、更新商品、商品上下架
⼆、后台新增和更新商品
Controller:Service层:
@Controller
@RequestMapping ("/manage/product")
public  class  ProductManageController {
@Autowired
private  IUserService iUserService;
@Autowired
private  IProductService iProductService;
@Autowired
private  IFileService iFileService;
@RequestMapping ("save.do")
@ResponseBody
public  ServerResponse productSave (HttpSession session, Product product) {
User user = (User) Attribute(Const.CURRENT_USER);
if  (user == null ) {
return  ateByErrorCodeMessage(ResponseCode.Code(), "⽤户未登录,请登录管理员");
}
//如果是管理员
if  (iUserService.checkAdminRole(user).isSuccess()) {
//增加或者更新商品
return  iProductService.saveOrUpdateProduct(product);
} else  {
return  ateByErrorMessage("⽆权限操作");
}
}
@Service("iProductService")
public class ProductServiceImpl implements IProductService {
@Autowired
private ProductMapper productMapper;
@Autowired
private CategoryMapper categoryMapper;
@Autowired
private ICategoryService iCategoryService;
//保存或者更新商品
public ServerResponse saveOrUpdateProduct(Product product){
if(product != null)  //产品不为空
{
// 获取前端传来的⼦图字符串⽤;分割~譬如前端传来1.jpg,2.jpg,3.jpg,
// 然后第⼀块代码就是将这个字符串按照;来分割成字符串数组,就可以获得所有⼦图,
// 然后把第⼀张⼦图当做主图来存储
if(StringUtils.SubImages())){
String[] subImageArray = SubImages().split(",");
if(subImageArray.length > 0)
product.setMainImage(subImageArray[0]);
}
//当产品id存在则更新商品
Id() != null){
int rowCount = productMapper.updateByPrimaryKey(product);
if(rowCount > 0)
ateBySuccess("更新产品成功");
ateBySuccess("更新产品失败");
}
//不存在则添加
else
{
int rowCount = productMapper.insert(product);
if(rowCount > 0)
ateBySuccess("新增产品成功");
ateBySuccess("新增产品失败");
}
}
ateByErrorMessage("新增或更新产品参数不正确");
}
}
三、后台新增和更新商品
Controller:
@RequestMapping("set_sale_status.do")
@ResponseBody
public ServerResponse setSaleStatus(HttpSession session, Integer productId,Integer status){
User user = (Attribute(Const.CURRENT_USER);
if(user == null){
ateByErrorCodeMessage(ResponseCode.Code(),"⽤户未登录,请登录管理员");
}
if(iUserService.checkAdminRole(user).isSuccess()){
return iProductService.setSaleStatus(productId,status);
}else{
ateByErrorMessage("⽆权限操作");
}
}
Service:
public ServerResponse<String> setSaleStatus(Integer productId,Integer status){
if(productId == null || status == null){
ateByErrorCodeMessage(ResponseCode.Code(),ResponseCode.    }
Product product = new Product();
product.setId(productId);
product.setStatus(status);
int rowCount = productMapper.updateByPrimaryKeySelective(product);
if(rowCount > 0){
ateBySuccess("修改产品销售状态成功");
}
ateByErrorMessage("修改产品销售状态失败");
}
四、后台获取产品详情
Controller:
@RequestMapping("detail.do")
@ResponseBody
public ServerResponse getDetail(HttpSession session, Integer productId){
User user = (Attribute(Const.CURRENT_USER);
if(user == null)
ateByErrorCodeMessage(ResponseCode.Code(),"⽤户未登录,请登录管理员");
if(iUserService.checkAdminRole(user).isSuccess()){
return iProductService.manageProductDetail(productId);
}else{
ateByErrorMessage("⽆权限操作");
}
}
Service:
@Service("iProductService")
public class ProductServiceImpl implements IProductService {
@Autowired
private ProductMapper productMapper;
@Autowired
private CategoryMapper categoryMapper;
@Autowired
private ICategoryService iCategoryService;
public ServerResponse<ProductDetailVo> manageProductDetail(Integer productId){
if(productId == null){
ateByErrorCodeMessage(ResponseCode.Cod
e(),ResponseCode.De    }
苹果手机如何越狱Product product = productMapper.selectByPrimaryKey(productId);
if(product == null)
ateByErrorMessage("产品已下架或者删除");
//VO -- value object
ProductDetailVo productDetailVo = assembleProductDetailVo(product);
ateBySuccess(productDetailVo);
}
private ProductDetailVo assembleProductDetailVo(Product product){
ProductDetailVo productDetailVo = new ProductDetailVo();
productDetailVo.Id());
productDetailVo.Subtitle());
productDetailVo.Price());
productDetailVo.MainImage());
productDetailVo.SubImages());
productDetailVo.CategoryId());
productDetailVo.Detail());
productDetailVo.Name());
productDetailVo.Status());
productDetailVo.Stock());
productDetailVo.Property("ftp.server.http.prefix","image.long/"));
Category category = categoryMapper.CategoryId());
if(category == null){
productDetailVo.setParentCategoryId(0);//默认根节点
}else{
productDetailVo.ParentId());
}
productDetailVo.setCreateTime(DateTimeUtil.CreateTime()));
productDetailVo.setUpdateTime(DateTimeUtil.UpdateTime()));
return productDetailVo;
}
VO:
佳宁组合public class ProductDetailVo {
dnf炮师刷图加点private Integer  id;
private Integer categoryId;
private String name;
private String subtitle;
打针的故事
private String mainImage;
private String subImages;
private String detail;
private BigDecimal price;
private Integer stock;
private Integer status;
private String createTime;
private String updateTime;
/*******相对于Product对象对出来的属性******/
private String imageHost;  //图⽚服务器url前缀
private Integer parentCategoryId;  //⽗分类
//...setter和getter⽅法...
}
简单分析下VO:
包装类其实就是我们项⽬中的pojo类,字段与数据库表的字段是相同的,⽽vo类可以简单理解成专门⽤于展⽰给⽤户看的类。
这⾥使⽤VO,这样可以减少⼤量的⼯作量(也就意味着减少bug,减少风险),也不需要担⼼未来的维护⼯作!VO还有⼀个好处就是是例如时间类型,返回给前台的时候需要转String类型,pojo转vo是为了封装,例如时间做成字符串,或者枚举转换成汉字,或者增加其他属性,这样vo的灵活性就突显出来了。
使⽤流读取配置properties配置⽂件:
基础部分可以看这个:
1、为什么使⽤p r op e r tie
有些常量需要动态的配置,如果项⽬上线后,每次修改Constants.java然后再编译,再上传Constants.class⽂件,再重启服务器。这样导致很繁琐。
如果将需要修改的配置项写成properties⽂件,程序写好后,以后要修改数据,直接在配置⽂件⾥修改,程序就不⽤修改,也不⽤重新编译了,将会在项⽬后期维护带来很⼤的⽅便~!
2、p r op e r tie⽂件读取⽅式
① 基于 ClassLoader 读取配置⽂件:
注意:该⽅式只能读取类路径下的配置⽂件,有局限但是如果配置⽂件在类路径下⽐较⽅便。
Properties properties = new Properties();
// 使⽤ClassLoader加载properties配置⽂件⽣成对应的输⼊流
InputStream in = ClassLoader().getResourceAsStream("config/config.properties");
// 使⽤properties对象加载输⼊流
properties.load(in);
//获取key对应的value值
② 基于 InputStream 读取配置⽂件:
注意:该⽅式的优点在于可以读取任意路径下的配置⽂件
Properties properties = new Properties();
// 使⽤InPutStream流读取properties⽂件
BufferedReader bufferedReader = new BufferedReader(new FileReader("E:/config.properties"));
properties.load(bufferedReader);
// 获取key对应的value值
③ 通过 java.util.ResourceBundle 类来读取,这种⽅式⽐使⽤ Properties 要⽅便⼀些:
注意:该⽅式的优点在于这种⽅式来获取properties属性⽂件不需要加.properties后缀名,只需要⽂件名即可