标签:second web eem stat 环境 首页 org 应用 users
简介
Spring 诞生时是 Java 企业版(Java Enterprise Edition,JEE,也称 J2EE)的
轻量级代替品。无需开发重量级的 Enterprise JavaBean(EJB),Spring 为企业级
Java 开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java 对象(Plain Old Java Object,POJO)实现了 EJB 的功能。
springboot起步
1、添加依赖
在pom.xml中添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
</parent>
<groupId>com.huiyang.springboot</groupId>
<artifactId>huiyang-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
这样就将简单的web服务依赖所需的jar包添加完毕,是不是很简单,注意是springboot默认的jdk版本是1.6,官方推荐使用1.8版本,所以需要添加
<properties>
<java.version>1.8</java.version>
</properties>
2、引导类
引导类是springboot服务启动的开端:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo {
public static void main(String[] args) {
SpringApplication.run(Demo.class, args);
}
}
它会扫描本包下所有类和子包,所以只需要将controller层,service层,dao层放到同级目录或者子包下即可,不需要添加扫描;
Springboot的整合
在MySQL数据库执行以下语句
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL COMMENT ‘用户名‘,
`password` varchar(100) DEFAULT NULL COMMENT ‘密码‘,
`name` varchar(100) DEFAULT NULL COMMENT ‘姓名‘,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (‘1‘, ‘zhangsan‘, ‘123456‘, ‘张三‘);
INSERT INTO `user` VALUES (‘2‘, ‘lisi‘, ‘123456‘, ‘李四‘);
INSERT INTO `user` VALUES (‘3‘, ‘wangwu‘, ‘123456‘, ‘王五‘);
INSERT INTO `user` VALUES (‘4‘, ‘zhangwei‘, ‘123456‘, ‘张伟‘);
INSERT INTO `user` VALUES (‘5‘, ‘lina‘, ‘123456‘, ‘李娜‘);
INSERT INTO `user` VALUES (‘6‘, ‘lilei‘, ‘123456‘, ‘李磊‘);
在pom.xml中加入如下依赖
<!-- MyBatis启动器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- MySQL连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
在src/main/resources 下添加application.properties 配置文件,内容如下:
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/huiyang?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
public class User {
// 主键
private Long id;
// 用户名
private String username;
// 密码
private String password;
// 姓名
private String name;
get/set。。。。。。
}
和之前的方式一样,只是多了两个注解
@Mapper:声明Mapper接口
@Select:声明这个接口所需要使用的sql,当然,有查询的注解,肯定就有增删改的注解。
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.huiyang.info.pojo.User;
@Mapper
public interface UserMapper {
@Select("select * from user where name like ‘%${value}%‘")
public List<User> queryUserByName(String name);
}
编写Service接口
import java.util.List;
import com.huiyang.info.pojo.User;
public interface UserService {
List<User> queryUserByName(String name);
}
编写Service实现类
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryUserByName(String name) {
List<User> list = this.userMapper.queryUserByName(name);
return list;
}
}
编写Controller
@RestController
@RequestMapping("user")
public class UserControlelr {
@Autowired
private UserService userService;
@RequestMapping("list/{name}")
public List<User> queryUserByName(@PathVariable String name) {
List<User> list = this.userService.queryUserByName(name);
return list;
}
}
浏览器地址栏输入:http://localhost:8080/user/list/张
显示效果:
以上所有的配置都是使用的默认配置,我们只需要专注java代码的开发即可,不需要加入配置文件了。
但并不是所有得场景都是简单的业务,有时候业务复杂,需要我们加入自定义的配置文件;有时候需要载入例如分页助手这样的插件,辅助开发,所以我们也需要了解如何加载这些配置。
需求:
效果如下:
我们需要加入通用Mapper和分页插件,所以需要在pom.xml加入以下依赖
<!-- 通用Mapper -->
<dependency>
<groupId>com.github.abel533</groupId>
<artifactId>mapper</artifactId>
<version>2.3.4</version>
</dependency>
<!-- 分页助手 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
在application.properties添加配置
#spring集成Mybatis环境
#pojo别名扫描包
mybatis.type-aliases-package=com.huiyang.springboot.pojo
#加载Mybatis核心配置文件
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
mybatis.config-location=classpath:mybatis/SqlMapConfig.xml
#配置连接池,还需要在pom.xml中加入该连接池的依赖
#spring.datasource.type=com.jolbox.bonecp.BoneCPDataSource
在src\main\resources\mapper路径下加入UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.huiyang.springboot.mapper.UserMapper">
<select id="queryAll" resultType="user">
select * from user
</select>
</mapper>
在src\main\resources\mybatis加入SqlMapConfig.xml配置文件,用以加载通用Mapper和分页助手
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 分页助手 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql" />
<!-- 该参数默认为false -->
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
<property name="rowBoundsWithCount" value="true" />
</plugin>
<!-- 通用Mapper -->
<plugin interceptor="com.github.abel533.mapperhelper.MapperInterceptor">
<!--主键自增回写方法,默认值MYSQL,详细说明请看文档 -->
<property name="IDENTITY" value="MYSQL" />
<!--通用Mapper接口,多个通用接口用逗号隔开 -->
<property name="mappers" value="com.github.abel533.mapper.Mapper" />
</plugin>
</plugins>
</configuration>
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.huiyang.info.pojo.User;
//extends com.github.abel533.mapper.Mapper<User>:需要继承通用Mapper
@Mapper
public interface UserMapper extends com.github.abel533.mapper.Mapper<User> {
@Select("select * from user where name like ‘%${value}%‘")
public List<User> queryUserByName(String name);
// 使用UserMapper.xml配置文件
public List<User> queryAll();
}
编写Service接口
import java.util.List;
import com.huiyang.info.pojo.User;
public interface UserService {
List<User> queryUserByName(String name);
List<User> queryAll();
List<User> queryUserByPage(Integer page, Integer rows);
}
Service实现类编写
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.PageHelper;
import com.huiyang.info.dao.UserMapper;
import com.huiyang.info.pojo.User;
import com.huiyang.info.service.UserService;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryUserByName(String name) {
List<User> list = this.userMapper.queryUserByName(name);
return list;
}
// 调用使用UserMapper.xml的Mapper
@Override
public List<User> queryAll() {
List<User> list = this.userMapper.queryAll();
return list;
}
// 使用通用Mapper和分页助手
@Override
public List<User> queryUserByPage(Integer page, Integer rows) {
// 设置分页
PageHelper.startPage(page, rows);
// 使用通用Mapper的方法进行查询所有数据
List<User> list = this.userMapper.select(null);
return list;
}
}
Controller编写
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.huiyang.info.pojo.User;
import com.huiyang.info.service.UserService;
@RestController
@RequestMapping("user")
public class UserControlelr {
@Autowired
private UserService userService;
@RequestMapping("list/{name}")
public List<User> queryUserByName(@PathVariable String name) {
List<User> list = this.userService.queryUserByName(name);
return list;
}
@RequestMapping("list")
public List<User> queryAll() {
List<User> list = this.userService.queryAll();
return list;
}
@RequestMapping("list/{page}/{rows}")
public List<User> queryUserAll(@PathVariable Integer page, @PathVariable Integer rows) {
List<User> list = this.userService.queryUserByPage(page, rows);
return list;
}
}
把资料中的static文件夹,拷贝到src/main/resources路径下
注意:
放在src/main/resources/static路径下的资源可以直接访问
测试使用通用Mapper和分页助手
浏览器地址栏输入:http://127.0.0.1:8080/user/list/2/2
测试使用UserMapper.xml
浏览器地址栏输入:http://localhost:8080/user.html
需求:基于上例代码,将列表数据缓存到Redis
在pom.xml加入依赖
<!-- 配置使用redis启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
修改开启缓存,添加注解@EnableCaching
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
要缓存到redis中的实体,需要让实体实现序列化接口
public class User implements Serializable {
private Long id;
private String userName;
private String password;
private String name;
。。。。。。
}
修改UserServiceImpl,
添加@Cacheable注解实现缓存添加
@Cacheable注解有三个参数,value是必须的,还有key和condition。第一个参数,也就是value指明了缓存将被存到什么地方。
任何存储在缓存中的数据为了高速访问都需要一个key。spring默认使用被@Cacheable注解的方法的签名来作为key,当然你可以重写key,自定义key可以使用SpEL表达式。
1 2 3 4 |
<span style="font-size:14px;">@Cacheable(value = "employee", key = "#surname")</span> publicPerson findEmployeeBySurname(String firstName, String surname, intage) {
returnnew Person(firstName, surname, age); } |
在findEmployeeBySurname()的注解中"#surname"是一个SpEL表达式,他将使用findEmployeeBySurname()方法中的surname参数作为key。
@Cacheable的最后一个参数是condition(可选),同样的,也是引用一个SpEL表达式。但是这个参数将指明方法的返回结果是否被缓存。
添加@CacheEvict注解实现缓存删除
@Override
@CacheEvict(value = "userCache", key = "‘user.queryAll‘")
public List<User> queryUserByName(String name) {
System.out.println("缓存清理了!");
List<User> list = this.userMapper.queryUserByName(name);
return list;
}
// 调用使用UserMapper.xml的Mapper
@Override
@Cacheable(value = "userCache", key = "‘user.queryAll‘")
public List<User> queryAll() {
System.out.println("从MySQL中查询");
List<User> list = this.userMapper.queryAll();
return list;
}
这样设置完成后,执行queryAll()方法就会使用缓存,如果缓存没有就添加缓存,而queryUserByName(String name)方法则是删除缓存
@Cacheable:添加/使用缓存
@CacheEvict:删除缓存
参数value是缓存的名字,在执行的时候,会找叫这个名字的缓存使用/删除
参数key默认情况下是空串””,是Spring的一种表达式语言SpEL,我们这里可以随意指定,但是需要注意一定要加单引号
redis除了作为缓存使用,还有很多其他的作用,例如利用redis的单线程获取唯一数,例如使用redis为单点登录系统存储用户登录信息等,我们就需要直接操作redis。
官网提供了三种接口RedisConnectionFactory, StringRedisTemplate 和 RedisTemplate,我们可以直接注入或者自己实现其他的实现类,来直接操作redis。我们这里使用RedisTemplate来操作Redis。
如下所示,我们只需要直接注入RedisTemplate即可使用以下方法操作redis的五种不同的数据类型
测试:
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
@CacheEvict(value = "userCache", key = "‘user.findAll‘")
public List<User> queryUserByName(String name) {
// 保存数据
this.redisTemplate.boundValueOps("redis").set("Hello redis !");
// 设置有效时间为100秒
this.redisTemplate.boundValueOps("redis").expire(100l, TimeUnit.SECONDS);
// 给value每次执行加一操作
this.redisTemplate.boundValueOps("count").increment(1l);
System.out.println("缓存清理了!");
List<User> list = this.userMapper.queryUserByName(name);
return list;
}
redis单机版
redis启动器默认情况下会找本地的redis服务,端口号默认是6379如果需要访问其他服务器的redis,则需要在application.properties中进行如下配置:
#Redis
spring.redis.host=192.168.37.161
spring.redis.port=6379
这表示会去找ip为192.168.37.161和端口为6379的服务
redis集群版
#Redis
#spring.redis.host=192.168.37.161
#spring.redis.port=6379
#Redis Cluster
spring.redis.cluster.nodes=192.168.37.161:7001,192.168.37.161:7002,192.168.37.161:7003,192.168.37.161:7004,192.168.37.161:7005,192.168.37.161:7006
切换到集群版只需要做以上配置,配置集群版节点信息,注释掉单机版信息
在pom.xml中加入以下配置
<!-- 配置ActiveMQ启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
在引导类中添加以下方法,设置队列
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Queue queue() {
return new ActiveMQQueue("huiyang.queue");
}
}
编写Controller,发送消息
import javax.jms.Destination;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("queue")
public class QueueController {
//注入发送消息的对象
@Autowired
private JmsTemplate jmsTemplate;
//注入消息队列
@Autowired
private Destination destination;
//编写发送消息的方法
@RequestMapping("send/{message}")
public String send(@PathVariable String message) {
this.jmsTemplate.convertAndSend(destination, message);
return "消息发送成功!消息内容:" + message;
}
}
编写bean,加入@Component注解让spring管理这个bean,作为接收消息的消费者
package com.huiyang.info.queue;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class Consumer {
// 接受消息方法
@JmsListener(destination = "huiyang.queue")
public void readMessage(String text) {
System.out.println("接受到的消息是:" + text);
}
}
测试:
启动服务后,在浏览器输入以下地址
http://127.0.0.1:8080/queue/send/发消息了11
显示效果:
即可看到消息发送成功
同时可以在控制台看到以下打印信息
我们没有安装ActiveMQ,为什么可以使用?因为Spring Boot 内置了ActiveMQ 的服务,所以我们不用单独启动也可以实现消息的发送和接收。
首先确认有一台外部ActiveMQ服务可以使用
在application.properties中加入以下配置
#ActiveMQ
spring.activemq.broker-url=tcp://192.168.37.161:61616
这样就加入了ActiveMQ服务的地址
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
@SpringBootApplication
@EnableScheduling//启用任务调度.
(4) 配置信息
所以spring boot提供了默认的配置,那么我们应该怎么修改配置呢,只需要在application.properties进行配置即可:
# RABBIT (RabbitProperties)
spring.rabbitmq.host= # connection host
spring.rabbitmq.port=# connection port
spring.rabbitmq.addresses= # connection addresses (e.g. myhost:9999,otherhost:1111)
spring.rabbitmq.username= # login user
spring.rabbitmq.password= # login password
spring.rabbitmq.virtualhost=
spring.rabbitmq.dynamic=
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
* RabbitMQDemo
*
* @author: sunjie
* @date: 16/01/10
*/
@Configuration
@SuppressWarnings("SpringJavaAutowiringInspection")public class RabbitMQDemoConfigration {
@Bean
public CachingConnectionFactory myConnectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setHost("192.168.1.1");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/myHost");
return connectionFactory;
}
// 生成CachingConnectionFactory 也可以使用下面的方式,在application.properties
// 中定义好属性即可
// @Autowired
// ConnectionFactory connectionFactory;@Bean
public DirectExchange myExchange() {
return new DirectExchange("myExchangeDemo", true, false);
}
@Bean
public Queue myQueue() {
return new Queue("myQueueDemo", true);
}
@Bean
public Binding myExchangeBinding(@Qualifier("myExchange") DirectExchange directExchange,
@Qualifier("myQueue") Queue queue) {
return BindingBuilder.bind(queue).to(directExchange).with("routeDemo");
}
@Bean
public RabbitTemplate myExchangeTemlate() {
RabbitTemplate r = new RabbitTemplate(myConnectionFactory());
r.setExchange("myExchangeDemo");
r.setRoutingKey("routeDemo");
return r;
}
/**
* 发送消息,工业使用需要自己做个性化实现
*/
@Bean
public void sendMessage(RabbitTemplate myExchangeTemlate) {
String string = "Hello RabbitmQ";
myExchangeTemlate.convertAndSend(string);
}
/**
* 接受消息,工业使用时需要在监听类中实现process逻辑
*/
@RabbitListener(queues = "myQueueDemo")
public void process(Message message) {
System.out.println("__________" + message.getBody().toString() + "__________");
try {
this.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
在pom.xml中加入测试依赖
<!-- 配置测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
import javax.jms.Destination;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.huiyang.info.Application;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class MessageTest {
@Autowired
private Destination destination;
@Autowired
private JmsTemplate jmsTemplate;
@Test
public void test() {
System.out.println("我发消息了!");
this.jmsTemplate.convertAndSend(destination, "Hello ActiveMQ!");
}
}
SpringRunner 与SpringJUnit4ClassRunner 是继承关系,但是没有不同的地方,只是看起来子类SpringRunner要短一些而已。
@SpringBootTest 注解的class 属性要指定引导类的class
<!-- FreeMarker启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("fm")
public class FreeMarkerController {
@RequestMapping
public String fm(Map<String, Object> root) {
root.put("name", "张三");
root.put("date", new Date());
return "template";
}
}
在src\main\resources\templates路径下创建template.ftl模板,内容如下:
Hello ${name} !
当前时间是
${date?datetime}
启动引导类测试效果:
<!-- solr启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
在application.properties添加配置
#solr配置
spring.data.solr.host=http://127.0.0.1:8081/solr
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("solr")
public class SolrController {
@Autowired
private SolrClient solrClient;
@RequestMapping("query/{data}")
public String query(@PathVariable String data, Map<String, Object> root) throws Exception {
// 查询solr
SolrQuery solrQuery = new SolrQuery("title:" + data);
QueryResponse response = this.solrClient.query(solrQuery);
SolrDocumentList results = response.getResults();
// 解析查询结果
List<String> list = new ArrayList<String>();
for (SolrDocument solrDocument : results) {
list.add(solrDocument.get("title").toString());
}
// 传递数据
root.put("total", results.getNumFound());
root.put("list", list);
return "solr";
}
@RequestMapping("save/{id}/{title}")
@ResponseBody
public String save(@PathVariable String id, @PathVariable String title) throws Exception {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", id);
doc.addField("title", title);
this.solrClient.add(doc);
this.solrClient.commit();
return "保存成功";
}
}
在src\main\resources\templates路径下创建solr.ftl模板,内容如下
查询到了${total}条数据
<br>
查询结果如下:
<#list list as l >
<br>${l}
</#list>
运行引导类
访问地址:http://localhost:8080/solr/query/测试,得到如下结果:
访问地址: http://localhost:8080/solr/query/save/s001/solr测试,查看索引库数据保存成功。
dubbo是一个分布式的服务架构,可直接用于生产环境作为SOA服务框架。官网首页:http://dubbo.io/
淘宝将这个项目开源出来以后,得到了不少同行的支持,包括:
当当网的扩展版本dubbox :https://github.com/dangdangdotcom/dubbox
京东的扩展版本jd-hydra: http://www.oschina.NET/p/jd-hydra
不过,略有遗憾的是, dubbo由于某些原因导致dubbo团队已经解散,已经很牛没有更新了,反到是当当网的扩展版本仍在持续发展。因为dubbox支持更新的spring版本,所以我们使用dubbox。
Dubbox在maven中央仓库并没有对应的依赖,所以我们需要自己动手将其发布到我们的本地仓库来使用。
使用git从码云上把dubbox的代码clone下来,
地址:https://git.oschina.net/wuyu15255872976/dubbox.git
执行Maven命令把工程安装到本地仓库
命令:clean install -Dmaven.test.skip
课程资料提供的仓库已经安装好了,可以直接使用
我们以前在使用dubbo的时候都是用的xml配置。而在整合Spring Boot的时候可以使用@ImportResource注解来引入的dubbo的xml配置。
但是Spring Boot本身并不推荐xml配置。怎么解决这个矛盾,我们可以自己准备一个Spring Boot Starter dubbo的项目来引导Spring Boot对Dubbo的自动化配置。已经有人开发好了这个自动化配置项目,我们直接使用就行了
使用git从码云上把spring-boot-starter-dubbo的代码clone下来,
地址:https://git.oschina.net/wuyu15255872976/spring-boot-starter-dubbo.git
执行Maven命令把工程安装到本地仓库
命令:clean install -Dmaven.test.skip
为了统一管理,把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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
</parent>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.4.4.RELEASE</version>
<name>Spring Boot Dubbo Rpc</name>
<description>Spring Boot Dubbo Rpc</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.8.5-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- zookeeper 客户端 -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
课程资料提供的仓库已经安装好了,可以直接使用
## Dubbo 应用配置
# 应用名称
spring.dubbo.application.name=xxx
# 模块版本
spring.dubbo.application.version=xxx
# 应用负责人
spring.dubbo.application.owner=xxx
# 组织名(BU或部门)
spring.dubbo.application.organization=xxx
# 分层
spring.dubbo.application.architecture=xxx
# 环境,如:dev/test/run
spring.dubbo.application.environment=xxx
# Java代码编译器
spring.dubbo.application.compiler=xxx
# 日志输出方式
spring.dubbo.application.logger=xxx
# 注册中心 0
spring.dubbo.application.registries[0].address=zookeeper:#127.0.0.1:2181=xxx
# 注册中心 1
spring.dubbo.application.registries[1].address=zookeeper:#127.0.0.1:2181=xxx
# 服务监控
spring.dubbo.application.monitor.address=xxx
## Dubbo 注册中心配置类
# 注册中心地址
spring.dubbo.application.registries.address=xxx
# 注册中心登录用户名
spring.dubbo.application.registries.username=xxx
# 注册中心登录密码
spring.dubbo.application.registries.password=xxx
# 注册中心缺省端口
spring.dubbo.application.registries.port=xxx
# 注册中心协议
spring.dubbo.application.registries.protocol=xxx
# 客户端实现
spring.dubbo.application.registries.transporter=xxx
spring.dubbo.application.registries.server=xxx
spring.dubbo.application.registries.client=xxx
spring.dubbo.application.registries.cluster=xxx
spring.dubbo.application.registries.group=xxx
spring.dubbo.application.registries.version=xxx
# 注册中心请求超时时间(毫秒)
spring.dubbo.application.registries.timeout=xxx
# 注册中心会话超时时间(毫秒)
spring.dubbo.application.registries.session=xxx
# 动态注册中心列表存储文件
spring.dubbo.application.registries.file=xxx
# 停止时等候完成通知时间
spring.dubbo.application.registries.wait=xxx
# 启动时检查注册中心是否存在
spring.dubbo.application.registries.check=xxx
# 在该注册中心上注册是动态的还是静态的服务 spring.dubbo.application.registries.dynamic=xxx
# 在该注册中心上服务是否暴露 spring.dubbo.application.registries.register=xxx
# 在该注册中心上服务是否引用 spring.dubbo.application.registries.subscribe=xxx |
# 服务协议
spring.dubbo.application.protocol.name=xxx
# 服务IP地址(多网卡时使用)
spring.dubbo.application.protocol.host=xxx
# 服务端口
spring.dubbo.application.protocol.port=xxx
# 上下文路径
spring.dubbo.application.protocol.contextpath=xxx
# 线程池类型
spring.dubbo.application.protocol.threadpool=xxx
# 线程池大小(固定大小)
spring.dubbo.application.protocol.threads=xxx
# IO线程池大小(固定大小)
spring.dubbo.application.protocol.iothreads=xxx
# 线程池队列大小
spring.dubbo.application.protocol.queues=xxx
# 最大接收连接数
spring.dubbo.application.protocol.accepts=xxx
# 协议编码
spring.dubbo.application.protocol.codec=xxx
# 序列化方式
spring.dubbo.application.protocol.serializatio
# 字符集
spring.dubbo.application.protocol.charset=xxx
# 最大请求数据长度
spring.dubbo.application.protocol.payload=xxx
# 缓存区大小
spring.dubbo.application.protocol.buffer=xxx
# 心跳间隔
spring.dubbo.application.protocol.heartbeat=xxx
# 访问日志
spring.dubbo.application.protocol.accesslog=xxx
# 网络传输方式
spring.dubbo.application.protocol.transporter=xxx
# 信息交换方式
spring.dubbo.application.protocol.exchanger=xxx
# 信息线程模型派发方式
spring.dubbo.application.protocol.dispatcher=xxx
# 对称网络组网方式
spring.dubbo.application.protocol.networker=xxx
# 服务器端实现
spring.dubbo.application.protocol.server=xxx
# 客户端实现
spring.dubbo.application.protocol.client=xxx
# 支持的telnet命令,多个命令用逗号分隔
spring.dubbo.application.protocol.telnet=xxx
# 命令行提示符
spring.dubbo.application.protocol.prompt=xxx
# status检查
spring.dubbo.application.protocol.status=xxx
# 是否注册
spring.dubbo.application.protocol.status=xxx
我们使用zookeeper作为dubbo的注册中心。
这里使用的zookeeper注册中心地址是:192.168.37.161:2181
huiyang-parent作为所有工程的父工程
huiyang- interface作为提供pojo和抽取服务接口的
huiyang-provider作为服务提供者
huiyang-consumer作为服务消费者
创建huiyang-parent,并打pom包,这里配置公共使用的依赖。
修改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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
</parent>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<!-- 配置java版本 -->
<java.version>1.7</java.version>
</properties>
<dependencies>
<!-- 配置测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 配置web启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<!-- 配置dubbo启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.4.4.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
创建huiyang-interface,并打jar包。
修改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.huiyang</groupId>
<artifactId>huiyang-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
创建huiyang-provider,并打jar包。
修改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.huiyang</groupId>
<artifactId>huiyang-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- 加入huiyang-interface依赖 -->
<dependency>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置MyBatis启动器 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- MySQL连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
创建huiyang-consumer,并打jar包。
修改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.huiyang</groupId>
<artifactId>huiyang-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- 加入huiyang-interface依赖 -->
<dependency>
<groupId>com.huiyang</groupId>
<artifactId>huiyang-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
编写pojo
import java.io.Serializable;
public class User implements Serializable {
private Long id;
private String userName;
private String password;
private String name;
get/set方法
}
编写Service接口
import com.huiyang.pojo.User;
public interface UserService {
public User queryUserById(Long id);
}
编写UserMapper
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.huiyang.common.pojo.User;
@Mapper
public interface UserMapper {
@Select("select * from user where id=#{id}")
public User queryUserById(Long id);
}
编写UserServiceImpl实现类
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.huiyang.common.consumer.UserService;
import com.huiyang.common.pojo.User;
import com.huiyang.mapper.UserMapper;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User queryUserById(Long id) {
User user = this.userMapper.queryUserById(id);
return user;
}
}
编写引导类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;
@SpringBootApplication
@EnableDubboAutoConfiguration
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
在src/main/resources加入配置文件application.properties
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/huiyang
spring.datasource.username=root
spring.datasource.password=root
#配置服务器访问端口号
server.port=8081
#配置dubbo信息
#配置服务名称
spring.dubbo.application.name=huiyang-provider
#注册中心类型
spring.dubbo.registry.protocol=zookeeper
#注册中心连接方式
spring.dubbo.registry.address=192.168.37.161:2181
#配置服务调用所使用的协议
spring.dubbo.protocol.name=dubbo
#配置服务端口号
spring.dubbo.protocol.port=20880
#配置服务访问地址
spring.dubbo.protocol.host=localhost
#配置dubbo扫描
spring.dubbo.scan=com.huiyang.provider
编写Controller
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.huiyang.common.consumer.UserService;
import com.huiyang.common.pojo.User;
@RestController
@RequestMapping("user")
public class UserController {
@Reference
private UserService userService;
@RequestMapping("{id}")
public User queryUserById(@PathVariable Long id) {
User user = this.userService.queryUserById(id);
return user;
}
}
编写引导类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;
@SpringBootApplication
@EnableDubboAutoConfiguration
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
在src/main/resources加入配置文件application.properties
#配置服务器访问端口号
server.port=8080
#配置dubbo信息
#配置服务名称
spring.dubbo.application.name=huiyang-consumer
#注册中心类型
spring.dubbo.registry.protocol=zookeeper
#注册中心连接方式
spring.dubbo.registry.address=192.168.37.161:2181
#配置服务调用所使用的协议
spring.dubbo.protocol.name=dubbo
#配置服务端口号
spring.dubbo.protocol.port=20880
#配置服务访问地址
spring.dubbo.protocol.host=localhost
#配置dubbo扫描
spring.dubbo.scan=com.huiyang.consumer
spring支持多种定时任务的实现。我们来介绍下使用spring的定时器和使用quartz定时器
1.我们使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式。
2.使用spring的定时器:
spring自带支持定时器的任务实现。其可通过简单配置来使用到简单的定时任务。
@Component
@Configurable
@EnableSchedulingpublic class ScheduledTasks{
@Scheduled(fixedRate = 1000 * 30)
public void reportCurrentTime(){
System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat ().format (new Date ()));
}
//每1分钟执行一次
@Scheduled(cron = "0 */1 * * * * ")
public void reportCurrentByCron(){
System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
}
private SimpleDateFormat dateFormat(){
return new SimpleDateFormat ("HH:mm:ss");
}
}
没了,没错,使用spring的定时任务就这么简单,其中有几个比较重要的注解:
@EnableScheduling:标注启动定时任务。
@Scheduled(fixedRate = 1000 * 30) 定义某个定时任务。
3.使用quartz实现定时任务。
Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。
CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。
使用quartz说使用的maven依赖。
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>1.8.4</version></dependency>
由于我们使用的是spring-boot框架,其目的是做到零配置文件,所以我们不使用xml文件的配置文件来定义一个定时器,而是使用向spring容器暴露bean的方式。
@Configuration
public class SchedledConfiguration {
// 配置中设定了
// ① targetMethod: 指定需要定时执行scheduleInfoAction中的simpleJobTest()方法
// ② concurrent:对于相同的JobDetail,当指定多个Trigger时, 很可能第一个job完成之前,
// 第二个job就开始了。指定concurrent设为false,多个job不会并发运行,第二个job将不会在第一个job完成之前开始。
// ③ cronExpression:0/10 * * * * ?表示每10秒执行一次,具体可参考附表。
// ④ triggers:通过再添加其他的ref元素可在list中放置多个触发器。 scheduleInfoAction中的simpleJobTest()方法
@Bean(name = "detailFactoryBean")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledTasks scheduledTasks){
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean ();
bean.setTargetObject (scheduledTasks);
bean.setTargetMethod ("reportCurrentByCron");
bean.setConcurrent (false);
return bean;
}
@Bean(name = "cronTriggerBean")
public CronTriggerBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean){
CronTriggerBean tigger = new CronTriggerBean ();
tigger.setJobDetail (detailFactoryBean.getObject ());
try {
tigger.setCronExpression ("0/5 * * * * ? ");//每5秒执行一次
} catch (ParseException e) {
e.printStackTrace ();
}
return tigger;
}
@Bean
public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){
SchedulerFactoryBean bean = new SchedulerFactoryBean ();
System.err.println (cronTriggerBean[0]);
bean.setTriggers (cronTriggerBean);
return bean;
}
}
MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个jobDetail,即制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。
注意:其setTargetObject所设置的是一个对象而不是一个类。
CronTriggerBean:定义一个触发器。
注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。
SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。
4.对quartz的封装
由上面代码可以看出来,此处我们设置的是一个固定的cronExpression,那么,做为项目中使用的话,我们一般是需要其动态设置比如从数据库中取出来。
其实做法也很简单,我们只需要定义一个Trigger来继承CronTriggerBean。顶用其setCronExpression方法即可。
那么另外一个问题,如果我们要定义两个定时任务则会比较麻烦,需要先注入一个任务工厂,在注入一个触发器。
为了减少这样的配置,我们定义了一个抽象的超类来继承CronTriggerBean。
具体代码如下:
public abstract class BaseCronTrigger extends CronTriggerBean implements Serializable {
private static final long serialVersionUID = 1L;
public void init(){
// 得到任务
JobDetail jobdetail = new JobDetail (this.getClass ().getSimpleName (),this.getMyTargetObject ().getClass ());
this.setJobDetail (jobdetail);
this.setJobName (jobdetail.getName ());
this.setName (this.getClass ().getSimpleName ());
try {
this.setCronExpression (this.getMyCronExpression ());
} catch (java.text.ParseException e) {
e.printStackTrace ();
}
}
public abstract String getMyCronExpression();
public abstract Job getMyTargetObject();
}
其init()方法,来为这个触发器绑定任务。其任务为一个Job类型的,也就是说其执行的任务为实现了Job接口的类,这个任务会有一个execute()方法,来执行任务题。
public class ScheduledTasks implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
}
private SimpleDateFormat dateFormat(){
return new SimpleDateFormat ("HH:mm:ss");
}
}
为了给触发器添加任务,我们需要在子类中调用init()方法,由于spring容器注入时是使用的空参的构造函数,所以我们在此构造函数中调用init()方法。
@Componentpublic class InitializingCronTrigger extends BaseCronTrigger implements Serializable {
private static final long serialVersionUID = 1L;
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
public InitializingCronTrigger() {
init ();
}
@Override
public String getMyCronExpression(){
return "0/5 * * * * ?";
}
@Override
public Job getMyTargetObject(){
return new ScheduledTasks ();
}
public void parse(){
try {
schedulerFactoryBean.getObject ().pauseAll ();
} catch (SchedulerException e) {
e.printStackTrace ();
}
}
}
此时我们只需要在配置类中加入一个配置就可以了。
@Bean
public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){
SchedulerFactoryBean bean = new SchedulerFactoryBean ();
System.err.println (cronTriggerBean[0]);
bean.setTriggers (cronTriggerBean);
return bean;
}
标签:second web eem stat 环境 首页 org 应用 users
原文地址:http://www.cnblogs.com/lihuiyang/p/7297937.html