Posted in Spring, Spring Boot, 技术

Spring Boot 之 HelloWorld详解

摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!

“以前是人放狗看家,现在是狗牵着人散步” — 随笔

Spring Boot 系列文章:《Spring Boot 那些事

一、Spring Boot 自述

世界上最好的文档来源自官方的《Spring Boot Reference Guide》,是这样介绍的:

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.

Spring Boot(英文中是“引导”的意思),是用来简化Spring应用的搭建到开发的过程。应用开箱即用,只要通过 “just run”(可能是 java -jar 或 tomcat 或 maven插件run 或 shell脚本),就可以启动项目。二者,Spring Boot 只要很少的Spring配置文件(例如那些xml,property)。

因为“习惯优先于配置”的原则,使得Spring Boot在快速开发应用和微服务架构实践中得到广泛应用。

 

Javaer装好JDK环境和Maven工具就可以开始学习Boot了~

二、HelloWorld实战详解

首先得有个maven基础项目,可以直接使用Maven骨架工程生成Maven骨架Web项目,即man archetype:generate命令:

mvn archetype:generate -DgroupId=springboot -DartifactId=springboot-helloworld -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

2.1  pom.xml配置

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>springboot</groupId>
    <artifactId>springboot-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-helloworld :: HelloWorld Demo</name>

    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

    <dependencies>
        <!-- Spring Boot web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

只要加入一个 Spring Boot 启动父依赖即可。

 

2.2 Controller层

HelloWorldController的代码如下:

/**
 * Spring Boot HelloWorld案例
 *
 * Created by bysocket on 16/4/26.
 */
@RestController
public class HelloWorldController {

    @RequestMapping("/")
    public String sayHello() {
        return "Hello,World!";
    }
}

@RestController和@RequestMapping注解是来自SpringMVC的注解,它们不是SpringBoot的特定部分。

1. @RestController:提供实现了REST API,可以服务JSON,XML或者其他。这里是以String的形式渲染出结果。

2. @RequestMapping:提供路由信息,”/“路径的HTTP Request都会被映射到sayHello方法进行处理。

具体参考,世界上最好的文档来源自官方的《Spring Framework Document

2.3 启动应用类

和第一段描述一样,开箱即用。如下面Application类:

/**
 * Spring Boot应用启动类
 *
 * Created by bysocket on 16/4/26.
 */
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

1. @SpringBootApplication:Spring Boot 应用的标识

2. Application很简单,一个main函数作为主入口。SpringApplication引导应用,并将Application本身作为参数传递给run方法。具体run方法会启动嵌入式的Tomcat并初始化Spring环境及其各Spring组件。

 

2.4 Controller层测试类

一个好的程序,不能缺少好的UT。针对HelloWorldController的UT如下:

/**
 * Spring Boot HelloWorldController 测试 - {@link HelloWorldController}
 *
 * Created by bysocket on 16/4/26.
 */
public class HelloWorldControllerTest {

    @Test
    public void testSayHello() {
        assertEquals("Hello,World!",new HelloWorldController().sayHello());
    }
}

 

三、运行

Just Run的宗旨,运行很简单,直接右键Run运行Application类。同样你也可以Debug Run。可以在控制台中看到:

Tomcat started on port(s): 8080 (http)
Started Application in 5.986 seconds (JVM running for 7.398)

然后访问 http://localhost:8080/ ,即可在页面中看到Spring Boot对你 say hello:

Hello,World!

 

四、小结

1. Spring Boot pom配置

2. Spring Boot 启动及原理

3. 对应代码分享在 Github 主页


如以上文章或链接对你有帮助的话,别忘了在文章结尾处评论哈~ 你也可以点击页面右边“分享”悬浮按钮哦,让更多的人阅读这篇文章。

Posted in Spring Boot, 技术

Spring Boot 之 RESRful API 权限控制

摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!

“简单,踏实~ 读书写字放屁”

一、为何用RESTful API

1.1 RESTful是什么?

RESTful(Representational State Transfer)架构风格,是一个Web自身的架构风格,底层主要基于HTTP协议(ps:提出者就是HTTP协议的作者),是分布式应用架构的伟大实践理论。RESTful架构是无状态的,表现为请求-响应的形式,有别于基于Bower的SessionId不同。

 

1.2理解REST有五点:

1.资源 

2.资源的表述 

3.状态的转移 

4.统一接口 

5.超文本驱动

需要理解详情,请点[传送门]

 

1.3 什么是REST API?

基于RESTful架构的一套互联网分布式的API设计理论。和上面资源,状态和统一接口有着密切的关系。

为啥分布式互联网架构很常见呢?请看下面两个模式

MVC模式:

 

REST API模式:


 

1.4 权限怎么控制?

RESTful针对资源的方法定义分简单和关联复杂两种。

基本方法定义:

GET /user # 获取user列表
GET /user/3 # 查看序号为3的user
POST /user # 新建一个user
PUT /user/3  # 更新序号为3的user
DELETE /user/3 #删除user 3

资源之间的关联方法如下定义:

GET /admin/1/user/10 # 管理员1号,查看序号为3的user信息
...

那么权限如何控制?

 

二、权限控制

前面说到,RESTful是无状态的,所以每次请求就需要对起进行认证和授权。

2.1 认证

身份认证,即登录验证用户是否拥有相应的身份。简单的说就是一个Web页面点击登录后,服务端进行用户密码的校验。

2.2 权限验证(授权)

也可以说成授权,就是在身份认证后,验证该身份具体拥有某种权限。即针对于某种资源的CRUD,不同用户的操作权限是不同的。

一般简单项目:做个sign(加密加盐参数)+ 针对用户的access_token

复杂的话,加入 SLL ,并使用OAuth2进行对token的安全传输。

自然,技术服务于应用场景。既简单又可以处理应用场景即可。简单,实用即可~

 

三、Access Token权限解决

3.1 AccessToken 拦截器

/**
 * Access Token拦截器
 * <p/>
 * Created by bysocket on 16/4/18.
 */
@Component
public class AccessTokenVerifyInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    ValidationService validationService;

    private final static Logger LOG = LoggerFactory.getLogger(AccessTokenVerifyInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        LOG.info("AccessToken executing ...");
        boolean flag = false;
        // token
        String accessToken = request.getParameter("token");
        if (StringUtils.isNotBlank(accessToken)) {
            // 验证
            ValidationModel v = validationService.verifyAccessToken(accessToken);
            // 时间过期

            // 用户验证
            if (v != null) {
                User user = userService.findById(v.getUid());
                if(user != null) {
                    request.setAttribute(CommonConst.PARAM_USER, user);
                    LOG.info("AccessToken SUCCESS ...  user:" + user.getUserName() + " - " + accessToken);
                    flag = true;
                }
            }
        }

        if (!flag) {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            response.getWriter().print("AccessToken ERROR");
        }

        return flag;
    }
}

 

第一步:从request获取token

第二步:根据token获取校验对象信息(也可以加入过期时间校验,简单)

第三步:通过校验信息获取用户信息

3.2 配置拦截

/**
 * MVC 设置
 *
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public AccessTokenVerifyInterceptor tokenVerifyInterceptor() {
        return new AccessTokenVerifyInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenVerifyInterceptor()).addPathPatterns("/test");
        super.addInterceptors(registry);
    }

}

 

第一步:将拦截器配置成Bean

第二步:拦截器注册注入该拦截器,并配置拦截的URL

 

token存哪里?

ehcache,redis,db都可以。自然简单的当然是db。

 

四、小结

1. REST API

2. Spring Boot 拦截器

 

欢迎点击我的博客及GitHub — 博客提供RSS订阅哦!

———- http://www.bysocket.com/ ————-https://github.com/JeffLi1993 ———-

微         博:BYSocket  豆         瓣:BYSocket  FaceBook:BYSocket  Twitter    :BYSocket

Posted in 技术

Linux之Redis安装

摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!


一、下载解压

## 下载Redis
wget http://download.redis.io/releases/redis-2.8.17.tar.gz
## 解压
tar zxvf redis-2.8.17.tar.gz

二、编译安装

cd redis-2.8.17/
make ## 编译

三、Redis配置设置

## 拷贝配置和启动命令到快捷目录
sudo cp redis.conf /etc/
cd src/ ## 启动命令在src目录
sudo cp redis-benchmark redis-cli redis-server /usr/bin/

上面是方便启动罢了。

Redis配置设置

vim /etc/redis.conf

将 daemonize 从 no 修改成 yes,运行为了守护进程。

(ps:vim 搜索文本 esc — :/daemonize)

四、启动Redis

redis-server /etc/redis.conf

五、 验证

ps -ef | grep redis
redis-cli
ping ## response 'pong'
可以看到起进程。

欢迎点击我的博客及GitHub — 博客提供RSS订阅哦!———- http://www.bysocket.com/ ————-https://github.com/JeffLi1993 ———-

微         博:BYSocket  豆         瓣:BYSocket  FaceBook:BYSocket  Twitter    :BYSocket

Posted in 清文

随笔,名为无题

有道云数据丢失,整理发现 一些好玩的随笔
2015.11.11
夜有时候是亮的,因为有你的眼睛
2015.10.16
上班路上,走在盲人道上的我
脚底按摩着,耳朵听着歌,也在挺享受和盲人一样的路。
2015.09.16
和谐号像一条温柔的蛇,蛇想回家了
2015.09.02
不仅仅是花儿是向着阳光的
早上三叶草的叶子面朝着阳光
2015.07.27
鸡汤,自己熬的。
多年后才觉得,和父母在一起的时候,真的很少;多少年后,在异乡独居,才想起那时候的宿舍。
我在阳台看天空
北极星的地方朝向你
2015.07.26
好像,一切都没有意义
好像,忘了初心,初心里面的梦想
2015.06.07
路很多,沙子的、柏油的、水泥的
还有两根铁轨的
2015.03.30
健身房,镜子里面的自己的脸
嘴唇有着血的颜色
当你病了,嘴唇也会累了
2015.03.16
为了挂衣服的线两头,紧紧挂在树干
多年以后,树依旧向上生长
把线吃进去了
2015.03.15
树藤儿包裹着冰冷的铁栏
2015.02.24
妈的故事
2015.02.24

人应该有梦
有梦就别怕疼痛
让上次犯的教训
反省出梦想
2015.02.17
年30前晚,站在家村的桥上
年味 在哪里
只有取悦小朋友的小烟火。
正态分布的人生 酒绿灯红
Posted in Working Skills, 技术

Dubbo实战一:快速入门 [译]

本文根据https://github.com/alibaba/dubbo 的README,然后实战操作记录如下:

一、简介

Dubbo不单单只是高性能的RPC调用框架,更是SOA服务治理的一种方案。

核心:

1. 远程通信,向本地调用一样调用远程方法。

2. 集群容错

3. 服务自动发现和注册,可平滑添加或者删除服务提供者。

二、快速入门

环境:Maven,git,jdk

1. 克隆dubbo开源项目

  1. cd ~
  2. git clone https://github.com/alibaba/dubbo.git

2. Maven编译项目

  1. cd ~/dubbo
  2. mvn clean install -Dmaven.test.skip ## 跳过测试

下面核心点有:zookeeper作为注册中心(服务订阅和发布依托于注册中心)、服务生产者(提供服务)项目、服务生产者(提供服务)项目和监控Web项目。

过程如下:

3. 下载启动zk

  1. cd ~
  2. ## 下载解压
  3. wget http://www.apache.org/dist//zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz
  4. tar zxvf zookeeper-3.3.3.tar.gz
  5. ## 启动
  6. cd ../bin
  7. ./zkServer.sh start

下面项目遇到target目录中编译好的项目为xxx.tar.gz。请自行用下面命令解压:

  1. tar zxvf XXX.tar.gz

4. 启动服务消费者

  1. cd ~/dubbo/dubbo-demo/dubbo-demo-consumer/target/dubbo-demo-consumer-2.5.4-SNAPSHOT/conf
  2. vim dubbo.properties
  3.    - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181 ## 更改注册中心为zk
  4. cd ../bin
  5. sh ./start.sh

5. 启动服务生产者

  1. cd ~/dubbo/dubbo-demo/dubbo-demo-provider/target/dubbo-demo-provider-2.5.4-SNAPSHOT/conf
  2. vim dubbo.properties
  3.   - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181
  4. cd ../bin
  5. sh ./start.sh

其实到这里已经o了,可以打开生产者消费者项目的log进行查看:

  1. ## 打开消费者的log
  2. cd dubbo-demo-consumer/target/dubbo-demo-consumer-2.5.4-SNAPSHOT/logs
  3. tail -f dubbo-demo-consumer.log

熟悉的Hello,World的案例coming…

6. 启动监控Web项目

  1. cd ~/dubbo/dubbo-simple/dubbo-monitor-simple/target/dubbo-monitor-simple-2.5.4-SNAPSHOT/conf
  2. vim dubbo.properties
  3.    - edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181
  4. cd ../bin./start.sh
  5. ## 浏览器访问
  6. http://127.0.0.1:8080

可以在监控中看到消费者,生产者实例等信息

Posted in Working Skills, 技术

Git 备忘录

设置相关

设置用户姓名和邮箱:

git config --global user.name "Your Name”
git config --global user.email "email@example.com”

常用指令

克隆远程库到本地

git clone

将本地目录变成Git管理的仓库

git init

将文件添加到仓库

git add 'filename'

将文件提交到仓库

git commit -m "说明"

显示工作区的状态

git status

从上一个git status看出哪些文件被修改,则查看修改内容

git diff 

显示提交的日志

git log
git log --graph // 可以方便看出分支合并图

回滚到版本,也可以将工作区的回滚到暂存区

git reset
git reset --hard 'commitid' // HEAD指向当前版本

回滚工作区的修改

git checkout -- 'filename'

主要考虑工作区,暂存区和仓库之间的操作:

git add files //把当前文件放入暂存区域。
git commit //给暂存区域生成快照并提交。
git reset -- files //用来撤销最后一次git add files,你也可以用git reset 撤销所有暂存区域文件。
git checkout -- files //把文件从暂存区域复制到工作目录,用来丢弃本地修改。

image

关于分支 远程库待续。。。

Posted in Java, 技术

图解微服务架构演进

图解服务化架构演进

许久没摘记了,继续告诫自己:

要静下心来,低调多做事

前言

来自dubbo的用户手册中的一句话:
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

常规的垂直应用架构就相当于传统的那种,现阶段传统垂直架构改造的核心就是对应用做服务化改造,服务话改造使用的核心技术架构就是分布式服务框架。

其实这篇是概念上的总结,技术概念软文,纪录此文让自己更明白什么是微服务化架构。

服务化架构演进

请看下图,也来自dubbo的用户手册,图中恰恰少了微服务架构的图。
image

那什么是微服务架构呢?
先从第一个图中第一个说起吧。

1.orm – 单一应用架构

我认为是一个高内聚版本,所有功能部署在一起。数据访问框架(orm)成为关键。这个架构很少被人使用,几乎接近灭绝了吧。

优点:成本低,适合功能少又简单 缺点:很多,比如无法适应高流量,二次开发难,部署成本高

2.mvc架构 - 垂直应用架构

当访问量渐渐增大,慢慢演化成用的很多的mvc架构。虽然还是所有的功能都是部署在同一个进程中,但是可以通过双机或者前置负载均衡来实现负载分流。这样应用也可以拆分成不同的几个应用,以提升性能和效率。

此时,mvc架构用于分离前后端逻辑。一方面,有一定的模块化。另一方面,加速和方便了开发。

3.rpc架构 - 分布式服务架构

当mvc垂直应用分成不同应用时,越来越多的情况下。不可避免的事应用a与应用b之间的交互。此时将核心和公共的 业务功能抽出来,作为单独的服务,并实现前后端逻辑分离。

此时则就需要提高业务的复用及整合的分布式rpc框架,例如dubbo等。

4.soa架构 - 流动计算架构

当rpc架构中的服务越来越多时,服务的生命周期的管控,容量的评估等各种问题会出现,使服务化成为瓶颈。需要增加一个调度中心来进行对服务管控,监督等。

然后,提到关键的 --

5.微服务架构

问:什么是微服务架构?

答:它就是将功能分散到各个离散的服务中然后实现对方案的解耦。服务更原子,自治更小,然后高密度部署服务。

下面是对微服务架构的图解:

image

小结

伴随敏捷开发,持续交付,DevOps,Docker等高速发展,微服务必然是未来演进方向。加油~ 多了解吧。

Posted in Working Skills, 技术

Mac使用zsh后, mvn命令无效的解决方案

Mac使用zsh后, mvn命令无效的解决方案

问题:

这里使用了zsh + iterm2 的配置
1.我配置好maven后,也source ~/.bash_profile。此时,我mvn -v 使是生效的。

2.问题就来了,我new了个窗口出来。mvn -v无效了。

解决:

将以下针对mvn的配置,放到.zshrc 中

export M2_HOME="/opt/maven" export PATH="$PATH:$M2_HOME/bin"export MAVEN_OPTS="-Xmx512m"

重启终端就可以了。
后来某大神说
在l.zshrc里加上source .bash_profile

Posted in Java, 技术

google collection工具包的MapMaker使用

 

摘自网上描述语段:

Google Collections中的MapMaker融合了Weak Reference线程安全高并发性能异步超时清理自定义构建元素等强大功能于一身。

常阅读优秀源代码的童鞋都知道,一般叫Maker的对象都是Builder模式,而这个MapMaker就是来”Build“Map的.

一、google collection工具包的MapMaker使用:

public static void main(String[] args) {
        /**
         * expiration(3, TimeUnit.SECONDS)设置超时时间为3秒
         */
        ConcurrentMap<String , String> map = new MapMaker().concurrencyLevel(32).softKeys().weakValues()
                .expiration(3, TimeUnit.SECONDS).makeComputingMap(
                        /**
                         * 提供当Map里面不包含所get的项,可以自动加入到Map的功能
                         * 可以将这里的返回值放到对应的key的value中
                         */
                        new Function<String, String>() {
                            public String apply(String s) {
                                return "creating " + s + " -> Object";
                            }
                        }
                );

        map.put("a","testa");
        map.put("b","testb");

        System.out.println(map.get("a"));
        System.out.println(map.get("b"));
        System.out.println(map.get("c"));

        try {
            // 4秒后,大于超时时间,缓存失效。
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(map.get("a"));
        System.out.println(map.get("b"));
        System.out.println(map.get("c"));
    }

结果如下:

testa
testb
creating c -> Object
creating a -> Object
creating b -> Object
creating c -> Object

 

二、先看下其api的相关demo片段:

// 使用案例:存储验证码
    // <String, String> == <用户唯一,验证码>
    // expiration(15, TimeUnit.MINUTES) 有效期15分钟
    ConcurrentMap<String,String> capthcaMap = new MapMaker().expiration(15, TimeUnit.MINUTES).makeMap();

    // 设置ConcurrentMap的concurrencyLevel参数 ,例如ConcurrentHashMap是用来控制其Segment数组的大小
    ConcurrentMap<String,Object> map1 = new MapMaker().concurrencyLevel(8).makeMap();

    // 构造各种不同reference作为key和value的map
    ConcurrentMap<String,Object> map2 = new MapMaker().softKeys().weakValues().makeMap();

    // 提供当Map里面不包含所get的项,可以自动加入到Map的功能
    ConcurrentMap<String,Integer> map3 = new MapMaker()
            .makeComputingMap(
                    new Function<String, Integer>() {
                        public Integer apply(String key) {
                            return 1;
                        }
                    }
            );

可以看出过了4秒后,缓存失效,所以呈现如此结果。