## 项目第14天 ##


Redis缓存的应用

1. 问题:使用系统管理员登录后,选择角色,点击权限按钮,每一次都会查询角色及其对应的权限,每一次都查询数据库。
    * 一个角色用于哪些菜单,类似这种是公有的数据,可以存入到缓存中

2. 重构代码:加入Redis缓存技术
    /**
     * 使用FastJson转换json字符串
     * @return
     * @throws Exception
     */
    public String roleModuleJsonStr() throws Exception {
        // 先查询该角色对象
        model = roleService.get(Role.class, model.getId());
        Set<Module> modules = model.getModules();
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();

        // ==============加入Redis代码====================
        // 先获取到连接池对象
        Jedis jedis = jedisPool.getResource();

        // 定义key值,这个key值注意:使用字符串和角色的ID拼接到一起组成的
        String key = SysConstant.REDIS_TREE+model.getId();

        // 先通过key从缓存中获取数据
        String value = jedis.get(key);
        // 判断,如果获取的值是空的,说明缓存中没有
        if(UtilFuns.isEmpty(value)){
            // 从数据库中查询
            // 查询所有的菜单
            List<Module> moduleList = moduleService.find("from Module where state = 1", Module.class, null);
            // 拼接json的字符串
            for (Module module : moduleList) {
                Map<String, String> map = new HashMap<String, String>();
                map.put("id", module.getId());
                map.put("pId", module.getParentId());
                map.put("name", module.getName());
                // 判断
                if(modules.contains(module)){
                    map.put("checked", "true");
                }else{
                    map.put("checked", "false");
                }
                list.add(map);
            }
            // 查询到了数据,把数据转换成json字符串
            String jsonString = FastJsonUtils.toJSONString(list);
            // 把jsonString存入到缓存中
            jedis.set(key, jsonString);
            // 关闭连接
            jedis.close();

            // 给字符串赋值
            value = jsonString;
            System.out.println("查询的数据库...");
        }else{
            System.out.println("从Redis缓存中获取...");
        }

        // 响应
        // FastJsonUtils.write_json(ServletActionContext.getResponse(), list);

        // 响应json
        FastJsonUtils.write_json(ServletActionContext.getResponse(), value);
        return NONE;
    }

3. 问题:当为角色分配了新的菜单,那么需要清除Redis缓存中的数据
    /**
     * 菜单分配功能
     * @return
     * @throws Exception
     */
    public String module() throws Exception {
        model = roleService.get(Role.class, model.getId());

        Set<Module> modules = new HashSet<Module>();
        String[] ids = moduleIds.split(",");
        for (String id : ids) {
            Module module = moduleService.get(Module.class, id);
            modules.add(module);
        }
        model.setModules(modules);
        roleService.saveOrUpdate(model);

        // 清除指定的缓存
        Jedis jedis = jedisPool.getResource();
        // 定义key值,这个key值注意:使用字符串和角色的ID拼接到一起组成的
        String key = SysConstant.REDIS_TREE+model.getId();
        // 清除缓存
        jedis.del(key);
        // 关闭连接
        jedis.close();

        return "page";
    }

Spring Data JPA整合Redis缓存的配置

1. 整合的配置文件如下
    <!-- Spring整合redis -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="30"/>
    </bean>

    <!-- 配置JedisConnectionFactoryBean对象 -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost"/>
        <property name="port" value="6379"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
    </bean>

2. 测试代码如下
    @Test
    public void run7() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-redis.xml");
        RedisTemplate<String, String> t = (RedisTemplate<String, String>) ac.getBean("redisTemplate");
        t.opsForValue().set("msg", "haha");
    }

消息中间件


消息中间件

1. 消息中间件的概述
2. 消息中间件的应用场景(查看大纲文档,了解消息队列的应用场景)
    * 异步处理
    * 应用解耦
    * 流量削峰
    * 消息通信

JMS消息服务


JMS的概述

1. JMS消息服务的概述
2. JMS消息模型
    * P2P模式
    * Pub/Sub模式

3. 消息消费的方式
    * 同步的方式
    * 异步的方式

4. JMS编程模型

消息中间件:ActiveMQ


ActiveMQ的下载与安装

1. ActiveMQ的下载与安装
    * 在资料中找到ActiveMQ的压缩文件,解压apache-activemq-5.14.5-bin.zip文件
    * 双击运行:activemq.bat文件,启动服务

2. 测试ActiveMQ是否安装成功
    * 打开浏览器,输入:http://localhost:8161

3. 点击Manage ActiveMQ broker连接,可以查看ActiveMQ中已经发布的消息等
    * 用户名密码都是:admin

4. ActiveMQ的服务器和默认的端口号
    * 使用协议是TCP的协议:tcp://localhost:61616

ActiveMQ的消息队列方式入门

1. 在父工程的pom.xml文件中引入ActiveMQ和Spring整合JMS的坐标依赖(项目中已经引入)
    <!-- activemq start -->
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-all</artifactId>
        <version>5.2.0</version>
    </dependency>

    <!-- activemq end -->

    <!-- spring 与 mq整合 start -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>4.2.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.xbean</groupId>
        <artifactId>xbean-spring</artifactId>
        <version>3.7</version>
    </dependency>
    <!-- spring 与 mq整合 end -->

2. ActiveMQ的向消息队列中发送消息的入门程序(没有使用Spring整合JMS的方式)
    * 具体的代码如下
        @Test
        public void run1() throws Exception{
            // 创建连接工厂
            ConnectionFactory factory = new ActiveMQConnectionFactory();
            // 使用工厂,创建连接
            Connection connection = factory.createConnection();
            // 启动连接
            connection.start();
            // 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
            Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            // 创建队列队形
            Queue queue = session.createQueue("hello");
            // 创建生产者
            MessageProducer producer = session.createProducer(queue);
            // 创建消息
            TextMessage message = session.createTextMessage("美美");
            // 发送消息
            producer.send(message);
            // 提交事务
            session.commit();
            session.close();
            connection.close();
        }

3. ActiveMQ从消息队列中获取消息
    * 具体的代码如下
        @Test
        public void run2() throws Exception{
            // 创建连接工厂
            ConnectionFactory factory = new ActiveMQConnectionFactory();
            // 使用工厂,创建连接
            Connection connection = factory.createConnection();
            // 启动连接
            connection.start();
            // 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
            Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            // 创建队列队形
            Queue queue = session.createQueue("hello");

            // 创建消费者
            MessageConsumer consumer = session.createConsumer(queue);
            // 接收消息
            TextMessage message = (TextMessage)consumer.receive();

            System.out.println(message.getText());
            // 提交事务
            session.commit();
            session.close();
            connection.close();
        }

4. 使用监听器的方式,从队列中消费消息
    /**
     * 使用监听器的方式消费消息
     * @throws Exception
     */
    @Test
    public void run3() throws Exception{
        // 创建连接工厂
        ConnectionFactory factory = new ActiveMQConnectionFactory();
        // 使用工厂,创建连接
        Connection connection = factory.createConnection();
        // 启动连接
        connection.start();
        // 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 创建队列队形
        Queue queue = session.createQueue("hello");
        // 创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
        // 给消费者添加监听器
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message msg) {
                TextMessage message = (TextMessage) msg;
                try {
                    System.out.println(message.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        while(true){}

        // 使用监听器的方式不能关闭,需要监听器一直工作
        // session.commit();
        // session.close();
        // connection.close();
    }

ActiveMQ的消息订阅方式入门

1. 发送消息的入门程序
    /**
     * 订阅方式发送消息
     * @throws Exception
     */
    @Test
    public void run4() throws Exception{
        // 创建连接工厂
        ConnectionFactory factory = new ActiveMQConnectionFactory();
        // 使用工厂,创建连接
        Connection connection = factory.createConnection();
        // 启动连接
        connection.start();
        // 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        // 创建消息订阅
        Topic topic = session.createTopic("helloTopic");
        // 创建生产者
        MessageProducer producer = session.createProducer(topic);
        // 创建消息,一组可以存储key value的消息
        MapMessage message = session.createMapMessage();
        message.setString("phone", "119");
        message.setString("code", "123456");
        // 发送消息
        producer.send(message);
        // 提交事务
        session.commit();
        session.close();
        connection.close();
    }

2. 消费者的代码如下
    /**
     * 消费者
     * @throws Exception
     */
    @Test
    public void run5() throws Exception{
        // 创建连接工厂
        ConnectionFactory factory = new ActiveMQConnectionFactory();
        // 使用工厂,创建连接
        Connection connection = factory.createConnection();
        // 启动连接
        connection.start();
        // 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 创建消息订阅
        Topic topic = session.createTopic("helloTopic");
        // 创建消费者
        MessageConsumer consumer = session.createConsumer(topic);

        // 设置监听器
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message msg) {
                MapMessage message = (MapMessage) msg;
                try {
                    String phone = message.getString("phone");
                    String code = message.getString("code");
                    System.out.println(phone + ":" + code);
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
        while(true){

        }
    }

Spring整合ActiveMQ


Spring整合ActiveMQ

1. 创建applicationContext-mq.xml的配置文件,导入约束
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
        xmlns:amq="http://activemq.apache.org/schema/core"
        xmlns:jms="http://www.springframework.org/schema/jms"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/data/jpa 
            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
            http://www.springframework.org/schema/jms
            http://www.springframework.org/schema/jms/spring-jms.xsd
            http://activemq.apache.org/schema/core
            http://activemq.apache.org/schema/core/activemq-core.xsd">

    </beans>

2. 具体的配置如下
    <!-- 配置连接工厂 -->
    <amq:connectionFactory id="connectionFactory" userName="admin" password="admin" brokerURL="tcp://localhost:61616"/>

    <!-- 配置Session,但是Spring已经整合了,进行管理,使用Spring的配置 -->
    <bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <!-- 要缓存Session的数量  -->
        <property name="sessionCacheSize" value="5"/>
        <!-- 连接工厂 -->
        <property name="targetConnectionFactory" ref="connectionFactory"/>
    </bean>

    <!-- 配置queue的jms模板 -->
    <bean id="queueJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 不是pubsub方式是,那就是队列方式 -->
        <property name="pubSubDomain" value="false"/>
        <property name="connectionFactory" ref="cachingConnectionFactory"/>
    </bean>

    <!-- 配置topic的jms模板 -->
    <bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 是主题方式 -->
        <property name="pubSubDomain" value="true"/>
        <property name="connectionFactory" ref="cachingConnectionFactory"/>
    </bean>

3. 发送消息的代码如下
    @Test
    public void run6() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq.xml");
        JmsTemplate template = (JmsTemplate) ac.getBean("queueJmsTemplate");
        // 发送消息
        template.send("hello",new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                // 使用session创建消息,发送
                TextMessage message = session.createTextMessage("haha");
                return message;
            }
        });
    }

4. 接收消息的代码如下
    @Test
    public void run7() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq.xml");
        JmsTemplate template = (JmsTemplate) ac.getBean("queueJmsTemplate");
        // 发送消息
        TextMessage message = (TextMessage) template.receive("hello");
        System.out.println(message.getText());
    }

Spring配置监听器

1. 自定义监听器代码的编写
    public class MyQueueListener implements MessageListener{

        public void onMessage(Message msg) {
            // 把msg强转
            TextMessage message = (TextMessage) msg;
            try {
                // 输出消息
                System.out.println(message.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }

    }

2. 编写配置文件
    <!-- 配置连接工厂 -->
    <amq:connectionFactory id="connectionFactory" userName="admin" password="admin" brokerURL="tcp://localhost:61616"/>

    <!-- 配置Session,但是Spring已经整合了,进行管理,使用Spring的配置 -->
    <bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <!-- 要缓存Session的数量  -->
        <property name="sessionCacheSize" value="5"/>
        <!-- 连接工厂 -->
        <property name="targetConnectionFactory" ref="connectionFactory"/>
    </bean>

    <!-- 配置自定义的监听器 -->
    <bean id="myQueueListener" class="ee66_jms.MyQueueListener"/>

    <!-- 配置监听器 -->
    <jms:listener-container destination-type="queue" connection-factory="cachingConnectionFactory">
        <!-- 监听的是hello的消息队列 -->
        <jms:listener destination="hello" ref="myQueueListener"/>
    </jms:listener-container>

3. 编写测试的方法
    @Test
    public void run8() throws Exception{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq-listener.xml");
        while(true){

        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值