项目7

it2026-08-16  6

Activemq整合spring的应用场景 2、添加商品同步索引库 3、商品详情页面动态展示 4、展示详情页面使用缓存

Activemq整合spring    (e3-manager-service在这里面测试生产者)

第一步:引用相关的jar包。

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> </dependency>

第二步:配置Activemq整合spring。配置ConnectionFactory  (applicationContext-activemq.xml)

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 --> <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://192.168.0.246:61616" /> </bean> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> <property name="targetConnectionFactory" ref="targetConnectionFactory" /> </bean> </beans>

第三步:配置生产者。

使用JMSTemplate对象。发送消息。

第四步:在spring容器中配置Destination。

<!-- 配置生产者 --> <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 --> <property name="connectionFactory" ref="connectionFactory" /> </bean> <!--这个是队列目的地,点对点的 --> <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg> <value>spring-queue</value> </constructor-arg> </bean> <!--这个是主题目的地,一对多的 --> <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg value="topic" /> </bean>

Activemq整合spring-发送消息

@Test public void testSpringActiveMq() throws Exception { //初始化spring容器 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml"); //从spring容器中获得JmsTemplate对象 JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class); //从spring容器中取Destination对象 Destination destination = (Destination) applicationContext.getBean("queueDestination"); //使用JmsTemplate对象发送消息。 jmsTemplate.send(destination, new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { //创建一个消息对象并返回 TextMessage textMessage = session.createTextMessage("spring activemq queue message"); return textMessage; } }); }

接收消息

方式一:用单独的测试方法来消费也是可以的

@Test public void testQueueConsumer() throws Exception { // 第一步:创建一个ConnectionFactory对象。 ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.0.246:61616"); // 第二步:从ConnectionFactory对象中获得一个Connection对象。 Connection connection = connectionFactory.createConnection(); // 第三步:开启连接。调用Connection对象的start方法。 connection.start(); // 第四步:使用Connection对象创建一个Session对象。 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 第五步:使用Session对象创建一个Destination对象。和发送端保持一致queue,并且队列的名称一致。 Queue queue = session.createQueue("spring-queue"); // 第六步:使用Session对象创建一个Consumer对象。 MessageConsumer consumer = session.createConsumer(queue); // 第七步:接收消息。 consumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message message) { try { TextMessage textMessage = (TextMessage) message; String text = null; //取消息的内容 text = textMessage.getText(); // 第八步:打印消息。 System.out.println(text); } catch (JMSException e) { e.printStackTrace(); } } }); //等待键盘输入 System.in.read(); // 第九步:关闭资源 consumer.close(); session.close(); connection.close(); }

接收消息

方式二:Activemq整合spring-接收消息

e3-search-Service中接收消息。 第一步:把Activemq相关的jar包添加到工程中 第二步:创建一个MessageListener的实现类。

public class MyMessageListener implements MessageListener { @Override public void onMessage(Message message) { try { TextMessage textMessage = (TextMessage) message; //取消息内容 String text = textMessage.getText(); System.out.println(text); } catch (JMSException e) { e.printStackTrace(); } } }

第三步:配置spring和Activemq整合。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 --> <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://192.168.0.246:61616" /> </bean> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory --> <property name="targetConnectionFactory" ref="targetConnectionFactory" /> </bean> <!--这个是队列目的地,点对点的 --> <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg> <value>spring-queue</value> </constructor-arg> </bean> <!--这个是主题目的地,一对多的 --> <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg value="topic" /> </bean> <!-- 接收消息 --> <!-- 配置监听器 --> <bean id="myMessageListener" class="cn.e3mall.search.message.MyMessageListener" /> <!-- 消息监听容器 --> <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="queueDestination" /> <property name="messageListener" ref="myMessageListener" /> </bean> </beans> @Test public void testQueueConsumer() throws Exception { //初始化spring容器 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml"); //等待 System.in.read(); }

添加商品同步索引库

e3-manager-service 只需要添加商品的时候,发送一个消息(商品id)

@Resource 既可以根据id,又可以根据类型,先根据id找,如果没有就根据类型找

发送消息的时候,事务可能还没有提交(商品可能还没有添加到数据库中) 两种方案: 拿到商品信息的时候,等待一下(等待事务提交), Thread.sleep(1000)

消息等待事务提交后在发,在表现层提交信息 e3-manager-web的商品添加功能的方法里面发送消息

监听消息 e3-search-servic

监听消息,需要创建MessageListener接口的实现类。 监听商品添加消息,接收消息后,将对应的商品信息同步到索引库

从消息中获取商品id 根据商品id查询商品信息 创建一个文档对象 向文档对象中添加域 把文档写入索引库 提交

Dao层 根据商品id查询商品信息

Service层

/** 监听商品添加信息,接收信息后,将对应的商品信息同步到索引库 */ public class ItemAddMessageListener implements MessageListener { @Autowired private ItemMapper itemMapper; @Autowired private SolrServer solrServer; @Override public void onMessage(Message message) { try { TextMessage textMessage = null; Long itemId = null; //取商品id if (message instanceof TextMessage) { textMessage = (TextMessage) message; itemId = Long.parseLong(textMessage.getText()); } //等待事务提交 Thread.sleep(1000); SearchItem searchItem = itemMapper.getItemById(itemId); SolrInputDocument document = new SolrInputDocument(); // 3、使用SolrServer对象写入索引库。 document.addField("id", searchItem.getId()); document.addField("item_title", searchItem.getTitle()); document.addField("item_sell_point", searchItem.getSell_point()); document.addField("item_price", searchItem.getPrice()); document.addField("item_image", searchItem.getImage()); document.addField("item_category_name", searchItem.getCategory_name()); // 5、向索引库中添加文档。 solrServer.add(document); solrServer.commit(); } catch (Exception e) { e.printStackTrace(); } } }

也可以在service层里面写方法,然后监听器里面调用即可

applicationContext-activemq.xml中配置

商品详情页面展示

创建一个商品详情页面展示的工程。是一个表现层工程

工程搭建 e3-item-web。打包方式war。可以参考e3-portal-web

pom文件复制e3-portal-web的pom,修改的部分(别的配置文件也要修改部分内容)

<dependency> <groupId>cn.e3mall</groupId> <artifactId>e3-manager-interface</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <build> <plugins> <!-- 配置Tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <path>/</path> <port>8086</port> </configuration> </plugin> </plugins> </build>

点击商品后进入商品详情页,这是路径

业务逻辑: 1、从url中取参数,商品id 2、根据商品id查询商品信息(tb_item)得到一个TbItem对象,缺少images属性,可以创建一个pojo继承TbItem,添加一个getImages方法。在e3-item-web工程中。

3、根据商品id查询商品描述。 4、展示到页面。

public class Item extends TbItem implements Serializable { public String[] getImages(){ String image2 = this.getImage(); if(image2 !=null && !"".equals(image2)){ String[] split = image2.split(","); return split; } return null; } public Item() { super(); } public Item(TbItem tbItem){ this.setId(tbItem.getId()); this.setTitle(tbItem.getTitle()); this.setSellPoint(tbItem.getSellPoint()); this.setPrice(tbItem.getPrice()); this.setNum(tbItem.getNum()); this.setBarcode(tbItem.getBarcode()); this.setImage(tbItem.getImage()); this.setCid(tbItem.getCid()); this.setStatus(tbItem.getStatus()); this.setCreated(tbItem.getCreated()); this.setUpdated(tbItem.getUpdated()); } }

Dao层 查询tb_item, tb_item_desc两个表,都是单表查询。可以使用逆向工程。

Service层 1、根据商品id查询商品信息 2、根据商品id查询商品描述

e3-manager-interface中添加方法(前面写过一个根据商品id查询商品)

public TbItem findTbItemById(Long itemId); public TbItemDesc getTbItemDescById(Long itemId); @Service public class ItemServiceImpl implements ItemService { @Autowired private TbItemMapper itemMapper; @Autowired private TbItemDescMapper tbItemDescMapper; public TbItem findTbItemById(Long itemId) { //根据主键查询 // return itemMapper.selectByPrimaryKey(itemId); TbItemExample example=new TbItemExample(); Criteria criteria = example.createCriteria(); criteria.andIdEqualTo(itemId); // 根据条件查询 List<TbItem> list=itemMapper.selectByExample(example); if(list !=null && list.size()>0){ return list.get(0); }else{ return null; } } public TbItemDesc getTbItemDescById(Long itemId) { TbItemDesc tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId); return tbItemDesc; } }

表现层

springmvc.xml的配置文件中引入服务

<dubbo:reference interface="cn.e3mall.service.ItemService" id="itemService" />

请求的url:/item/{itemId}

@Controller public class ItemController { @Autowired private ItemService itemService; @RequestMapping("/item/{itemId}") public String showItemInfo(@PathVariable Long itemId,Model model){ //跟据商品id查询商品信息 TbItem tbItem = itemService.findTbItemById(itemId); //把TbItem转换成Item对象 Item item=new Item(tbItem); //根据商品id查询商品描述 TbItemDesc tbItemDesc = itemService.getTbItemDescById(itemId); //把数据传递给页面 model.addAttribute("item", item); model.addAttribute("itemDesc", tbItemDesc); return "item"; } }

这里解释下为啥需要转成Item对象,原因是Item中提供了getImages方法

商品详情页的效果:

向业务逻辑中添加缓存(查询商品数据,先查询缓存,没有在查询数据库)(前面写了个e3-content-service的缓存,将其配置文件applicationContext-redis.xml复制到e3-manager-service中即可) 使用redis做缓存。

业务逻辑: 1、根据商品id到缓存中查找 2、查到缓存,直接返回。 3、查不到,查询数据库 4、把数据放到缓存中 5、返回数据

缓存中缓存热点数据,提供缓存的使用率。需要设置缓存的有效期。一般是一天的时间,可以根据实际情况跳转。(提供有效期,主要是有的商品没什么人买,不需要老是放在缓存中)

需要使用String类型来保存商品数据。 可以加前缀方法对象redis中的key进行归类。 ITEM_INFO:123456:BASE ITEM_INFO:123456:DESC

前面是商品缓存的前缀  中间是商品的id  后面是商品的基础信息 和商品描述

如果把二维表保存到redis中: 1、表名就是第一层 2、主键是第二层 3、字段名第三次 三层使用“:”分隔作为key,value就是字段中的内容。

将list对象转成json字符串 商品数据在缓存中key的前缀 默认时间是秒

怎么知道配置的缓存生效,只需要刷新商品详情页的链接,第一次会在缓存中存放数据的

方法没有问题,不知道为啥缓存没有生效,以后有空在整理下

网页静态化 使用Freemarker实现网页静态化。

2.1.什么是freemarker FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

freemarker的使用方法

把freemarker的jar包添加到工程中。

Maven工程添加依赖(e3-item-web)

<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>

使用步骤: 第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是freemarker对于的版本号。 第二步:设置模板文件所在的路径。 第三步:设置模板文件使用的字符集。一般就是utf-8. 第四步:加载一个模板,创建一个模板对象。 第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。 第六步:创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名。 第七步:调用模板对象的process方法输出文件。 第八步:关闭流。

模板: ${hello}

@Test public void testFreemarker() throws Exception{ Configuration configuration=new Configuration(Configuration.getVersion()); configuration.setDirectoryForTemplateLoading(new File("E:/20200520/e3-item-web/src/main/webapp/WEB-INF/ftl")); configuration.setDefaultEncoding("utf-8"); Template template = configuration.getTemplate("hello.ftl"); Map modelMap=new HashMap<>(); modelMap.put("hello", "hello freemarker !!"); Writer out=new FileWriter(new File("E://freemarker//demo1//hello.txt")); template.process(modelMap, out); out.close(); }

 

最新回复(0)