前台系统开发
来源:互联网 发布:淘宝发货地址怎么改 编辑:程序博客网 时间:2024/05/16 04:14
商城前台页面系统
1、技术选型
后台技术: Spring+SpringMVC
前台技术:html+CSS+JS
商品数据的获取途径:从后台系统的接口获取数据。
2、建立Maven工程
- pom.xml文件内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.enjoyshop.parent</groupId> <artifactId>enjoyshop-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.enjoyshop.web</groupId> <artifactId>enjoyshop-web</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.enjoyshop.common</groupId> <artifactId>enjoyshop-common</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.enjoyshop.manage</groupId> <artifactId>enjoyshop-manage-pojo</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> <!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- Apache工具组件 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> </dependency> <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.6.0</version> </dependency> <!-- 时间操作组件 --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>1.4.0.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <port>8082</port> <path>/</path> </configuration> </plugin> </plugins> </build></project>
- web.xml内容如下
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>enjoyshop-web</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext*.xml</param-value> </context-param> <!--Spring的ApplicationContext 载入 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 编码过滤器,以UTF8编码 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置SpringMVC框架入口 --> <servlet> <servlet-name>enjoyshop-web</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/enjoyshop-web-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>enjoyshop-web</servlet-name> <!-- 伪静态,好处:有利于SEO(搜索引擎优化) --> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>enjoyshop-web</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list></web-app>
- Spring和SpringMVC配置文件
这部分配置和后台系统配置类似,不做具体描述。
3、编写通用控制类
package com.enjoyshop.web.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;import com.enjoyshop.web.service.IndexService;@Controllerpublic class IndexController { @Autowired private IndexService indexService; @RequestMapping(value = "index", method = { RequestMethod.GET, RequestMethod.POST }) public ModelAndView index() { ModelAndView mv = new ModelAndView("index"); // 获取大广告位数据 String indexAD1 = this.indexService.queryIndexAD1(); //将数据放入request请求中 mv.addObject("indexAD1", indexAD1); // 右上角广告位数据 String indexAD2 = this.indexService.queryIndexAD2(); mv.addObject("indexAD2", indexAD2); return mv; }}
- 封装HttpClient的接口服务
@Servicepublic class ApiService implements BeanFactoryAware { private BeanFactory beanFactory; @Autowired(required=false) private RequestConfig requestConfig; /** * 执行GET请求,响应200返回内容,404返回null * * @param url * @return * @throws ClientProtocolException * @throws IOException */ public String doGet(String url) throws ClientProtocolException, IOException { // 创建http GET请求 HttpGet httpGet = new HttpGet(url); httpGet.setConfig(requestConfig); CloseableHttpResponse response = null; try { // 执行请求 response = getHttpClient().execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { return EntityUtils.toString(response.getEntity(), "UTF-8"); } } finally { if (response != null) { response.close(); } } return null; } /** * 带有参数的GET请求,响应200返回内容,404返回null * * @param url * @param params * @return * @throws ClientProtocolException * @throws IOException * @throws URISyntaxException */ public String doGet(String url, Map<String, String> params) throws ClientProtocolException, IOException, URISyntaxException { URIBuilder builder = new URIBuilder(url); for (Map.Entry<String, String> entry : params.entrySet()) { builder.setParameter(entry.getKey(), entry.getValue()); } return doGet(builder.build().toString()); } /** * 执行post请求 * * @param url * @param params * @return * @throws IOException */ public HttpResult doPost(String url, Map<String, String> params) throws IOException { // 创建http POST请求 HttpPost httpPost = new HttpPost(url); httpPost.setConfig(requestConfig); if (null != params) { List<NameValuePair> parameters = new ArrayList<NameValuePair>(0); for (Map.Entry<String, String> entry : params.entrySet()) { parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } // 构造一个form表单式的实体 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); // 将请求实体设置到httpPost对象中 httpPost.setEntity(formEntity); } CloseableHttpResponse response = null; try { // 执行请求 response = getHttpClient().execute(httpPost); return new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(), "UTF-8")); } finally { if (response != null) { response.close(); } } } public HttpResult doPostJson(String url, String json) throws IOException { // 创建http POST请求 HttpPost httpPost = new HttpPost(url); httpPost.setConfig(requestConfig); if (null != json) { // 构造一个字符串式的实体 StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON); // 将请求实体设置到httpPost对象中 httpPost.setEntity(stringEntity); } CloseableHttpResponse response = null; try { // 执行请求 response = getHttpClient().execute(httpPost); return new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(), "UTF-8")); } finally { if (response != null) { response.close(); } } } //每次都从工厂中获取一个bean,实现httpclient的多例 private CloseableHttpClient getHttpClient() { return this.beanFactory.getBean(CloseableHttpClient.class); } //用于spring初始化时设置BeanFactory,否则spring无法初始化这个service @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; }}
- 获取首页大广告位的数据
通过访问后台系统接口获取数据
@Autowired private ApiService apiService; private static final ObjectMapper MAPPER = new ObjectMapper(); @Value("${ENJOYSHOP_MANAGE_URL}") private String ENJOYSHOP_MANAGE_URL; @Value("${INDEX_AD1_URL}") private String INDEX_AD1_URL; @Value("${INDEX_AD2_URL}") private String INDEX_AD2_URL; public String queryIndexAD1() { try { String url = ENJOYSHOP_MANAGE_URL + INDEX_AD1_URL; String jsonData = this.apiService.doGet(url); if (StringUtils.isEmpty(jsonData)) { return null; } // 解析json,生成相应的json数据 JsonNode jsonNode = MAPPER.readTree(jsonData); ArrayNode rows = (ArrayNode) jsonNode.get("rows"); List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(); for (JsonNode row : rows) { Map<String, Object> map = new LinkedHashMap<String, Object>(); map.put("srcB", row.get("pic").asText()); map.put("height", 240); map.put("alt", row.get("title").asText()); map.put("width", 670); map.put("src", row.get("pic").asText()); map.put("widthB", 550); map.put("href", row.get("url").asText()); map.put("heightB", 240); result.add(map); } return MAPPER.writeValueAsString(result); } catch (Exception e) { e.printStackTrace(); } return null; }
- 获取右侧小广告位的数据
public String queryIndexAD2() { try { String url = ENJOYSHOP_MANAGE_URL + INDEX_AD2_URL; String jsonData = this.apiService.doGet(url); if (StringUtils.isEmpty(jsonData)) { return null; } // 解析json,生成前端所需要的json数据 JsonNode jsonNode = MAPPER.readTree(jsonData); ArrayNode rows = (ArrayNode) jsonNode.get("rows"); List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(); for (JsonNode row : rows) { Map<String, Object> map = new LinkedHashMap<String, Object>(); map.put("width", 310); map.put("height", 70); map.put("src", row.get("pic").asText()); map.put("href", row.get("url").asText()); map.put("alt", row.get("title").asText()); map.put("widthB", 210); map.put("heightB", 70); map.put("srcB", row.get("pic").asText()); result.add(map); } return MAPPER.writeValueAsString(result); } catch (Exception e) { e.printStackTrace(); } return null; }
4、首页左侧商品类目的显示
- 跨域请求问题
因为商品类目的数据接口在后台系统中,所以前台系统可以直接通过接口服务获取数据。但是后台系统的URL为manage.enjoyshop.com,而前台系统的URL为www.enjoyshop.com。这里涉及到了跨域请求的问题。浏览器对ajax请求的限制,不允许跨域请求资源。
http://www.a.com请求http://www.b.com下的资源是跨域。
http://www.a.com请求http://www.a.com:8080下的资源是跨域。
http://a.a.com请求http://b.a.com下的资源是跨域。
http://www.a.com http://www.a.com/api下的资源不是跨域。
不同的域名或不同的端口都是跨域请求。
- 跨域请求解决方案
可以使用jsonp技术来解决这个问题。具体关于jsonp的介绍请参考这里。点我
- 前端页面请求后台接口
var category = {OBJ: $("#_JD_ALLSORT"), URL_Serv: "http://manage.enjoyshop.com/rest/api/item/cat?callback=category.getDataService", ······· }
- 乱码问题解决
虽然jsonp解决了跨域请求的问题,成功的请求到了数据。但是展示出来时却是乱码。这是SpringMVC消息转化器引起的。如果使用默认的消息转化器,其对于字符串的编码采用的是ISO-8859-1。如下所示:
public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> { public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); private final Charset defaultCharset; ······}
这里来自定义一个消息转化器来处理json
package com.enjoyshop.common.spring.exetend.converter.json;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.springframework.http.HttpOutputMessage;import org.springframework.http.converter.HttpMessageNotWritableException;import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import com.fasterxml.jackson.core.JsonEncoding;import com.fasterxml.jackson.core.JsonProcessingException;//继承自MappingJackson2HttpMessageConverter,自定义消息转化器public class CallbackMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { // 做jsonp的支持的标识,在请求参数中加该参数 private String callbackName; @Override protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { // 从threadLocal中获取当前的Request对象 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String callbackParam = request.getParameter(callbackName); if(StringUtils.isEmpty(callbackParam)){ // 没有找到callback参数,直接返回json数据 super.writeInternal(object, outputMessage); }else{ JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType()); try { String result =callbackParam+"("+super.getObjectMapper().writeValueAsString(object)+");"; IOUtils.write(result, outputMessage.getBody(),encoding.getJavaName()); } catch (JsonProcessingException ex) { throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex); } } } public String getCallbackName() { return callbackName; } public void setCallbackName(String callbackName) { this.callbackName = callbackName; }}
需要在SpringMVC的配置文件中来加载该消息转化器。
<!-- 定义注解驱动 --> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!-- 配置一个消息转化器解决中文乱码(将对象序列化为json时默认使用iso-8859-1) <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg index="0" value="UTF-8"></constructor-arg> </bean> --> <!-- 设置自定义的消息转化器处理json --> <bean class="com.enjoyshop.common.spring.exetend.converter.json.CallbackMappingJackson2HttpMessageConverter"> <property name="callbackName" value="callback"></property> </bean> </mvc:message-converters> </mvc:annotation-driven>
5、商品详情信息的显示
商品详情页面的URL形式为http://www.enjoyshop.com/item/{itemId}.html。
- 相应的controller层代码如下:
@RequestMapping("item")@Controllerpublic class ItemController { @Autowired private ItemService itemService; @RequestMapping(value="{itemId}",method=RequestMethod.GET) public ModelAndView showDetail(@PathVariable("itemId") Long itemId){ ModelAndView mv=new ModelAndView("item"); //添加商品基本数据 Item item=this.itemService.queryItemById(itemId); mv.addObject("item",item); //添加商品描述数据 ItemDesc itemDesc=this.itemService.queryItemDescByItemId(itemId); mv.addObject("itemDesc", itemDesc); //添加商品规格参数 String itemParam=this.itemService.queryItemParamByItemId(itemId); mv.addObject("itemParam", itemParam); return mv; }}
- 对应的service层关键代码如下:这里通过apiService向后台系统请求数据,并且为商品信息加入了缓存功能
@Servicepublic class ItemService { @Autowired private ApiService apiService; @Value("${ENJOYSHOP_MANAGE_URL}") private String ENJOYSHOP_MANAGE_URL; private static final ObjectMapper MAPPER = new ObjectMapper(); public static final String REDIS_KEY="ENJOYSHOP_WEB_ITEM_DETAIL_"; private static final Integer REDIS_TIME=60*60*24; @Autowired private RedisService redisService; //获取商品基本信息 public Item queryItemById(Long itemId) { String key=REDIS_KEY+itemId; try { //先从缓存中命中 String cacheData=this.redisService.get(key); if(StringUtils.isNotEmpty(cacheData)){ return MAPPER.readValue(cacheData, Item.class); } } catch (Exception e1) { e1.printStackTrace(); } try { String url = ENJOYSHOP_MANAGE_URL + "/rest/item/" + itemId; String jsonData = this.apiService.doGet(url); if (StringUtils.isEmpty(jsonData)) { return null; } try {//需要加try catch防止影响原逻辑 //写入缓存 this.redisService.set(key, jsonData, REDIS_TIME); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return MAPPER.readValue(jsonData, Item.class); } catch (Exception e) { e.printStackTrace(); } return null; } //获取商品描述信息 public ItemDesc queryItemDescByItemId(Long itemId) { try { String url = ENJOYSHOP_MANAGE_URL + "/rest/item/desc/" + itemId; String jsonData = this.apiService.doGet(url); if (StringUtils.isEmpty(jsonData)) { return null; } return MAPPER.readValue(jsonData, ItemDesc.class); } catch (Exception e) { e.printStackTrace(); } return null; } //获取商品规格参数信息 public String queryItemParamByItemId(Long itemId) { try { String url = ENJOYSHOP_MANAGE_URL + "/rest/item/param/item/" + itemId; String jsonData = this.apiService.doGet(url); // 解析JSON JsonNode jsonNode = MAPPER.readTree(jsonData); ArrayNode paramData = (ArrayNode) MAPPER.readTree(jsonNode.get("paramData").asText()); StringBuilder sb = new StringBuilder(); sb.append( "<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"0\" class=\"Ptable\"><tbody>"); for (JsonNode param : paramData) { sb.append("<tr><th class=\"tdTitle\" colspan=\"2\">" + param.get("group").asText() + "</th></tr>"); ArrayNode params = (ArrayNode) param.get("params"); for (JsonNode p : params) { sb.append("<tr><td class=\"tdTitle\">" + p.get("k").asText() + "</td><td>" + p.get("v").asText() + "</td></tr>"); } } sb.append("</tbody></table>"); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; }}
- 后台系统提供的接口如下:
查询商品基本信息
@RequestMapping(value = "{itemId}", method = RequestMethod.GET) public ResponseEntity<Item> queryById(@PathVariable("itemId") Long itemId) { try { Item item = this.itemService.queryById(itemId); if (null == item) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); } return ResponseEntity.ok(item); } catch (Exception e) { e.printStackTrace(); } // 出错 500 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); }
查询商品描述信息
@RequestMapping(value = "{itemId}", method = RequestMethod.GET) public ResponseEntity<ItemDesc> queryByItemId(@PathVariable("itemId") Long itemId) { try { ItemDesc itemDesc = this.itemDescService.queryById(itemId); if (null == itemDesc) { // 资源不存在,404 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); } // 200 return ResponseEntity.ok(itemDesc); } catch (Exception e) { e.printStackTrace(); } // 错误,500 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); }
查询商品规格参数信息
@RequestMapping(method = RequestMethod.GET) public ResponseEntity<EasyUIResult> queryItemParamList(@RequestParam(value = "page", defaultValue = "1") Integer page, @RequestParam(value = "rows", defaultValue = "30") Integer rows) { try { PageInfo<ItemParam> pageInfo = this.itemParamService.queryPageList(page, rows); EasyUIResult easyUIResult = new EasyUIResult(pageInfo.getTotal(), pageInfo.getList()); return ResponseEntity.ok(easyUIResult); } catch (Exception e) { e.printStackTrace(); } // 出错 500 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); }
6、解决系统间的数据同步问题
- 面临的问题:
后台系统中如果将商品修改,前台系统没有进行数据的同步,仍然从Redis的缓存中获取数据,导致前端系统不能够实时显示最新的数据。
- 解决方案一:手动实现系统间的更新通知
基本思路:如果在后台系统中商品修改后向其他系统发送通知,其他系统做出对应的处理(清理Redis中的缓存),就可以实现同步。
首先在前台系统中开发一个接口,用于后台系统调用该接口来删除缓存。
@RequestMapping("item/cache")@Controllerpublic class ItemCacheController { @Autowired private RedisService redisService; //删除缓存数据 @RequestMapping(value="{itemId}",method=RequestMethod.POST) public ResponseEntity<Void> deleteCache(@PathVariable("itemId") Long itemId){ try { String key=ItemService.REDIS_KEY+itemId; this.redisService.del(key); return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); }}
在后台系统更新商品数据的逻辑中,加入调用前台接口的方法。
public void updateItem(Item item, String desc, String itemParams) { // 强制设置不能修改的字段为null item.setStatus(null); item.setCreated(null); super.updateSelective(item); // 修改商品描述数据 ItemDesc itemDesc = new ItemDesc(); itemDesc.setItemId(item.getId()); itemDesc.setItemDesc(desc); this.itemDescService.updateSelective(itemDesc); // 修改商品规格参数 this.itemParamItemService.updateItemParamItem(item.getId(), itemParams); try { // 需要通知其他系统进行数据更新 String url = ENJOYSHOP_WEB_URL + "/item/cache/" + item.getId() +".html"; this.apiService.doPost(url, null); } catch (Exception e) { e.printStackTrace(); } }
- 解决方案二:使用消息队列RabbitMQ
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
关于RabbitMQ的更多介绍请参考这里。点我
7、使用RabbitMQ解决据同步问题
- 选用队列模式
这里采用通配符模式,这种模式更具有扩展性。
- 队列和交换机的绑定方法
有两种方法:
1、 在配置文件中将队列和交换机完成绑定。
2、 在RabbitMQ的管理界面中手动完成绑定。
这里采用手动绑定的方式,优点如下:
1、 若使用配置文件绑定的方式,如果绑定关系发生变化,需要修改配置文件,并且服务需要重启。
2、 采用手动绑定,管理更加灵活,更容易对绑定关系进行权限管理,流程管理。
- 发送的消息内容
1、 将Item对象做json序列化发送
a) 数据大
b) 有些数据其他人是可能用不到的
2、 发送商品的id、操作类型。
这里采用第二种方式。
- 在后台系统中添加Spring和RabbitMQ的整合文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 定义RabbitMQ的连接工厂 --> <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" virtual-host="${rabbitmq.vhost}" /> <!-- 定义管理 --> <rabbit:admin connection-factory="connectionFactory"/> <!-- 定义交换机 --> <rabbit:topic-exchange name="enjoyshop-item-exchange" durable="true" auto-declare="true"/> <!-- 定义模板 --> <rabbit:template id="template" connection-factory="connectionFactory" exchange="enjoyshop-item-exchange"/></beans>
- 后台系统中在新增和修改商品时发送消息
@Autowired private RabbitTemplate rabbitTemplate; private static final ObjectMapper MAPPER = new ObjectMapper(); public void saveItem(Item item, String desc, String itemParams) { // 默认为上架状态 item.setStatus(1); // 防止前端恶意添加id值 item.setId(null); //保存商品信息 super.save(item); //构建ItemDesc数据并保存 ItemDesc itemDesc = new ItemDesc(); itemDesc.setItemId(item.getId()); itemDesc.setItemDesc(desc); this.itemDescService.save(itemDesc); //构建ItemParamItem数据并保存 ItemParamItem itemParamItem = new ItemParamItem(); itemParamItem.setItemId(item.getId()); itemParamItem.setParamData(itemParams); this.itemParamItemService.save(itemParamItem); //发送mq消息 sendMsg(item.getId(), "insert"); } public void updateItem(Item item, String desc, String itemParams) { // 强制设置不能修改的字段为null item.setStatus(null); item.setCreated(null); super.updateSelective(item); // 修改商品描述数据 ItemDesc itemDesc = new ItemDesc(); itemDesc.setItemId(item.getId()); itemDesc.setItemDesc(desc); this.itemDescService.updateSelective(itemDesc); // 修改商品规格参数 this.itemParamItemService.updateItemParamItem(item.getId(), itemParams); // try { // // 需要通知其他系统进行数据更新 // String url = ENJOYSHOP_WEB_URL + "/item/cache/" + item.getId() + // ".html"; // this.apiService.doPost(url, null); // } catch (Exception e) { // e.printStackTrace(); // } //发送mq消息 sendMsg(item.getId(), "update"); } private void sendMsg(long itemId,String type){ try { //发送mq详细通知其他系统进行数据更新 Map<String, Object> msg = new HashMap<String, Object>(); msg.put("itemId", itemId); msg.put("type", type); msg.put("date", System.currentTimeMillis()); this.rabbitTemplate.convertAndSend("item."+type, MAPPER.writeValueAsString(msg)); } catch (Exception e) { e.printStackTrace(); } }
- 前台系统接收消息
Spring和RabbitMQ整合文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 定义RabbitMQ的连接工厂 --> <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" virtual-host="${rabbitmq.vhost}" /> <!-- 定义管理 --> <rabbit:admin connection-factory="connectionFactory"/> <!-- 定义队列 --> <rabbit:queue name="enjoyshop-web-item-queue" durable="true" auto-declare="true"/> <!-- 定义消费者 --> <bean id="itemMQHandler" class="com.enjoyshop.web.mq.handler.ItemMQHandler"/> <!-- 消费者监听队列 --> <rabbit:listener-container connection-factory="connectionFactory"> <rabbit:listener ref="itemMQHandler" method="execute" queue-names="enjoyshop-web-item-queue"/> </rabbit:listener-container></beans>
接收消息,清理缓存
package com.enjoyshop.web.mq.handler;import org.springframework.beans.factory.annotation.Autowired;import com.enjoyshop.common.service.RedisService;import com.enjoyshop.web.service.ItemService;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;public class ItemMQHandler { private static final ObjectMapper MAPPER = new ObjectMapper(); @Autowired private RedisService redisService; //拿到商品id,删除redis缓存 public void execute(String msg) { try { JsonNode jsonNode = MAPPER.readTree(msg); Long itemId = jsonNode.get("itemId").asLong(); String key = ItemService.REDIS_KEY + itemId; this.redisService.del(key); } catch (Exception e) { e.printStackTrace(); } }}
- 前台系统开发
- 银行MIS系统前台开发总结(1)
- 银行MIS系统前台开发总结(2)-dataTable控件
- [原创]银行MIS系统前台开发总结(3)
- 小型bbs论坛系统开发6 前台注册/登录页
- asp拍卖系统前台
- web系统 前台组件
- webgame前台开发总结
- WEB开发前台常用
- Ext前台开发
- 前台页面开发规范
- django前台开发框架
- web 开发,前台验证
- Web前台开发基础
- 前台开发框架
- 前台开发总结01
- 前台开发总结02
- 前台开发总结03
- 集合
- spring-session使用配置(分布式共享session配置)
- 类与类之间的关系
- iptables的一些配置
- 夜神模拟器链接eclipse并导出模拟器中app的db文件,查看sqlite数据库过程
- 前台系统开发
- angular-ui-router (上)
- 如何使用Loading
- python日志体系logging模块学习
- win7系统IE9控件注册的问题
- dovecot + mysql
- php值引用和传递引用以及 变量函数
- java基础:继承关系类加载顺序问题
- 解析PSNR和SSIM