品优购项目总结
- 之前在学习java的时候自己做过一个商城项目,采用的是SSH框架做的,当时也是为了学习SSH框架,属于那种OA系统,很单一。后来看资料发现了传智播客的品优购项目,找到了资料学习。从开始到结束,差不多用了一个月的时间,期间没有用提供的虚拟机,自己在阿里云上部署了一个服务器,也算把所有内容自己尝试了一下,包括安装FastDFS这些。
- 做的过程中遇到了很多的问题。开这个帖子的目的呢,一个是做一下学习笔记,一个是我在做的过程问题的一些汇总。
一、工程搭建问题
-
工程搭建的时候我使用的工具的IDEA来操作的,在建立的过程当中,也会区分jar包与war包的区别,这个需要在建立的时候自己选择一下。
- 使用IDEA搭建好工程以后需要手动去建立一些文件,在main目录下面创建resources与java,一定注意要写对,我当时建立的时候写成了resource,就少了一个S,spring的配置文件一个也读取不到,访问Controller一直是404,找错误找了好久。然后打开Project Structure,给这个目录作为Resources也Sources。
- 这里注意一个问题,可能你在建立web工程的时候速度特别慢,这里可以修改一下本地仓库,引用一下阿里巴巴的一个仓库,在setting.xml文件中加入一句话。
nexus
*
http://maven.aliyun.com/nexus/content/groups/public/
nexus-public-snapshots
public-snapshots
http://maven.aliyun.com/nexus/content/repositories/snapshots/
- 这样的话在新建web工程的时候速度就很快了。
二、商户修改密码阶段问题
- 这个阶段视频当中没有说过,我是后面再完善的时候看到了这个模块,主要这里涉及一个问题,就是在使用Security框架的时候,当时注册时候,密码被加密了,在修改密码的时候,会和原来的密码进行比较,因为和MD5加密不一样,每次的值都不同。查了资料才发现,提供了一个加密比较方法。
BCryptPasswordEncoder passwordEncoder =new BCryptPasswordEncoder();
boolean matches = passwordEncoder.matches(oldpass, seller.getPassword());
- 这样就能可以比较两次的密码值。
三、AngularJS跨域提交的过程中文乱码问题
- 在做跨域访问的时候,传对象、数字都是正常的,就是传输中文的时候会导致乱码的问题。一直也没找到问题。编译器编码也改了,但还是有问题,传输之前打印一个alert,正常。到了控制层打印就出现了乱码。
- 在传输的过程中,涉及到传输中文的话,我都会以对象的形式传,有问题的朋友可以尝试一下。
$scope.maps={};
$scope.findOne=function(ids){
$scope.maps.sellerId=ids;
sellerService.findOne($scope.maps).success(
function(response){
$scope.entity= response;
}
);
}
四、Solr搜索服务问题
- 在第十天、第十一天的内容里面都是在做Solr的搜索,当时在做的过程中,测试的时候发现了一个小bug,就是我点击最后一页,比如是19页,当我在搜索一个内容的时候,没有19页就会出现什么内容也没有。(后面的时候老师有讲这个过程)可以在搜索的时候每次将页面拉回去。
$scope.searchMap.pageNo=1;
这句话只要是涉及到更改搜索内容的时候都需要放上,不然都会出现没有数据的情况。
- 第二个小问题就是在更新solr库的时候,感觉需求分析稍微有点问题,个人感觉,商品上传以后运营商会进行审核,但是在审核的过程当中由于 没有修改后端代码,运用商更新的只是tb_goods表当中的audit_status字段,但是在导入solr库的时候,导入的是tb_item这个表里面的信息,而且看的也是这个表中status字段,所以在存储的过程中,永远不会添加到solr库。
- 然后我自己修改了一下需求,也就是在商户点击商家商品的时候,导入solr库,将内容放入消息中间件当中,获取。需要修改Shop-web下面的GoodsController。
@RequestMapping("/updateStatue")
public void updateStatue(final Long id, String status){
goodsService.UpdateMarkStatus(id,status);
//更新Solr
if (status.equals("1")) {
List item = goodsService.findItemListByGoodsIdListAndStatus(id, status);
// //导入solr
// itemSearchService.importList(item);
final String jsonString = JSON.toJSONString(item);
//发消息 传输对象必须是实现了序列化接口
jmsTemplate.send(queueSolrDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(jsonString);
}
});
System.out.println("消息发送完毕------");
//创建页面
// itemPageService.genItemHtml(id);
jmsTemplate.send(topicGoodsDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(id+"");
}
});
}else{
//下架以后再创建
// itemPageService.genItemHtml(id);
jmsTemplate.send(topicGoodsDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(id+"");
}
});
}
- 代码写的不是很好....凑活看看
五、Redis缓存问题
- 在做缓存的时候,当时需要把品牌列表与规格列表全部放入Redis当中,当时老师在写的时候,直接改成了一个死的,也就是每次项目运行的时候,在点击的过程中,都会有一个很长时间的导入过程,造成超时,就算把时间改成很长,但是也得过很久才会显示,这样的体验很差。
- 个人的解决办法:导入一次以后记得将之前的代码注释一下,之后在增加修改删除的时候,只执行一次。在TypeTemplateServiceImpl文件中,重新写了一个方法,每次增删改查的时候执行这个方法即可。
private void saveToRedisOne(TbTypeTemplate typeTemplate){
List brandList = JSON.parseArray(typeTemplate.getBrandIds(), Map.class);
List
- 水平有限...各位如果有好的方法可以一起交流一下。
六、支付
- 视频里面使用的是微信扫码付款方式,但是没有签名所以很多时候做到这一步基本就放弃了,由于没有营业执照什么的,微信支付自己又没办法申请,这里别着急,可以使用支付宝的,支付宝的可以个人免费申请一个,然后使用沙盒测试就ok。
- 首先去 https://docs.open.alipay.com/ 开发者中心注册这些自己就可以完成。之后进入开发中心 ----> 网页移动应用 。
- 然后选择一下支付接入,自己接入一下。这个地方其实可以随便写一下,因为app上线的话这个就很重要,我们的目的是学习,所以这个地方自己有兴趣看看,加密那块的设置。然后就是打开沙箱测试。 https://openhome.alipay.com/platform/appDaily.htm?tab=info
- 这里有几个参数一会要用到的,appid 支付宝网关 支付宝公钥。公钥怎么设置这里不做过多的赘述,鼠标放上去之后下载一个支付宝提供的加密软件,生成 复制 粘贴就ok了。说明一下这里的支付宝网关,这里一定记得用这个沙盒测试地址。正式的地址由于没有上线,appid不合法的。需要用安卓手机下载一个沙盒测试app网站里面就有。 https://docs.open.alipay.com/291/106103/ 密钥的开发文档
- 生成好密钥以后,保存一下自己的密钥和支付宝公钥。然后就开始写代码测试。如果要学习可以看看 https://docs.open.alipay.com/270/106291/ 开发文档,我用的是电脑扫码付款这个,有兴趣自己下载一下Demo看看。
- 引入阿里巴巴的sdk依赖。
com.alipay.sdk
alipay-sdk-java
3.4.49.ALL
- 创建一个类,用来完成支付。这里也需要的JSON格式的数据,但是每个都得写太麻烦了,直接就封装到Map里面然后JSON.toJSONString转换了一下字符串就可以了。这里记得要看着开发文档去做啊。我把一些文件都写到了properties文件里面了,详细可以参考一下视频里面的做法。
@Service
public class ZhiFuBaoPayServiceImpl implements ZhiFuBaoPayService {
@Value("${app_id}")
private String appid;
@Value("${merchant_private_key}")
private String merchant_private_key;
@Value("${alipay_public_key}")
private String alipay_public_key;
@Value("${notify_url}")
private String notify_url;
@Value("${return_url}")
private String return_url;
@Value("${sign_type}")
private String sign_type;
@Value("${charset}")
private String charset;
@Value("${gatewayUrl}")
private String gatewayUrl;
@Autowired
private HttpServletRequest req;
@Autowired
private HttpServletResponse response;
@Override
public String createNative(String out_trade_no, String total_fee,String subject) {
AlipayClient alipayClient=new DefaultAlipayClient(gatewayUrl,appid,merchant_private_key,"json",charset,alipay_public_key,sign_type);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl(return_url);
request.setNotifyUrl(notify_url);
//添加商品信息
Map map=new HashMap();
map.put("out_trade_no",out_trade_no);
map.put("total_amount",total_fee);
map.put("subject",subject);
map.put("body","你好,测试商品");
map.put("product_code","FAST_INSTANT_TRADE_PAY");
String parm=JSON.toJSONString(map);
request.setBizContent(parm);
// System.out.println("===这是parm:"+parm);
String result="";
try {
result = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return result;
}
}
这里注意两个地址notify_url和return_ur,这两个地址。return_url指的是用户的付款以后跳转的一个页面,这个页面尽量做一个静态页面就行,给用户展示用的。notify_url 这个页面是异步调用的,也就是说用户和我们都没办法看到这个页面,它是用来做数据的处理的,比如更改订单状态。
-
- notify_url这个地址需要公网ip能访问的,因为阿里巴巴的说法是这个页面需要他们返回执行,通知率据说可以达到99.999%,这个连接里面主要做的就是修改数据库字段,但是没有公网ip所以就写一个任意地址。
-
- return_url这个地址由于网络问题可能会通知不到,页面不跳转,建议就是不在这个地址上做任何事,放一个静态地址就可以。但是测试的时候只能用这个地址来做。
gatewayUrl 这个就是沙盒测试地址,也就是之前的说的支付宝网关。
- 创建Controller来完成支付。
@RequestMapping("/pay")
public class ZhiFuBaoController {
@Reference
private ZhiFuBaoPayService zhiFuBaoPayService;
@Reference
private OrderService orderService;
@RequestMapping("/ZhiFuBao")
public void createNativeZhiFuBao(HttpServletResponse response) throws IOException {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
TbPayLog tbPayLog = orderService.searchPayLogFromRedis(name);
String result="";
if (tbPayLog!=null){
result = zhiFuBaoPayService.createNative(tbPayLog.getOutTradeNo(),tbPayLog.getTotalFee()+"","黑蚂蚁商城家的商品");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(result);//直接将完整的表单html输出到页面
response.getWriter().flush();
response.getWriter().close();
}else{
return;
}
}
@RequestMapping("/success")
public void success(HttpServletRequest request, HttpServletResponse response){
Map parem=new HashMap();
Map map=request.getParameterMap();
for (Iterator iterator=map.keySet().iterator();iterator.hasNext();){
String name= (String) iterator.next();
String[] values= (String[]) map.get(name);
String vlaue="";
for (int i = 0; i < values.length; i++) {
vlaue = (i == values.length - 1) ? vlaue + values[i]
: vlaue + values[i] + ",";
}
parem.put(name,vlaue);
}
String outId=parem.get("out_trade_no");
String trade_no=parem.get("trade_no");
orderService.updateOrderStatus(outId,trade_no);
System.out.println("支付宝流水号:"+trade_no);
try {
response.sendRedirect("../paysuccess.html");
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 我这边测试的时候就把return_url 改成了这个Controller的success.do这个地址。更改数据库字段在跳转成功界面。
总结
整个品优购项目的完成,熟悉了很多的技术。如SpringSecurity、Dubbox,Solr等。在学习过程,遇到了很多的问题,也翻阅了很多的资料。整个品优购项目中,让我体会到一个大型项目的“魅力”。整个项目中,让我感觉到最麻烦最难的一点就是单点登录,每次看单点登录的跳转,看的头大。但是分布式应用有不可避免....自己的技术还有待提高,如果文章当中有问题,或者有什么好的意见,大家可以指出来,一起学习。