社会李

社会李 查看完整档案

上海编辑  |  填写毕业院校创业公司  |  java研发工程师 编辑 catalinali.top/ 编辑
编辑

别吵,我正在写bug。

个人动态

社会李 评论了文章 · 2018-10-12

手把手教你使用hexo搭建属于你的个人博客

front-pic-1

前言

每当看到别人精美的个人博客时,不知你是否有一点点的羡慕。别急,现在我就来手把手教你搭建自己的个人博客。
在技术日趋成熟的今天,有着很多种快速生成博客的框架:Hexo,Jekyll,Wordpress等等。今天我们就用Hexo来带着大家完成自己的博客


什么是Hexo?

Hexo官网中说是这么描述的:A fast, simple & powerful blog framework,即:一个快速、简单且强大的博客快速生产工具。它的简单体现在你完全有可能在30分钟内就生成属于你的个人博客。而它的强大体现在你对细节的调整上完全有可能花上一天的时间。

一、巧妇难为无米之炊:准备搭建环境

1.安装node.js

Node.js 的实质是一个JavaScript运行环境,这里我们主要使用它来生成我们博客的静态页面。从官网下载最新的安装包进行默认安装就好。安装过程略。

2.安装git环境

git是最流行的分布式版本控制系统,我们使用它主要是与github进行交互。安装git使用默认选项安装即可,安装过程略。如果你还对git不是特别熟悉,推荐一个学习git的教程:传送门

3.注册github

github就不用说了吧,它是一个面向开源及私有软件项目的托管平台。几乎所有的程序员都听说过它的大名。就正常注册一个账号就好了。
注册号以后首先给我们的账号添加本机的SSH,具体方法及原因在这篇文章已经有了详细说明,并且方法也很简单

二、上正菜:开始搭建博客

环境都准备好后,我们就可以开始安装博客了:
1.创建文件夹

在本地新建一个文件夹用于存放我们的博客,并且右键菜单选择Git Bash Here,然后在Git Bash里输入:

    npm install hexo

然后回车,如图:

buildHexo_1
我在执行这个的时候出现了下图的警告,但是并不影响我们的安装,不用理会它。
buildHexo_5
如果没有输出err之类的错误并且目录下多了一个node_modules文件夹,那这步就算成功了
buildHexo_6

2.执行hexo命令
依次执行以下3个命令:

    hexo init  --初始化hexo环境,这时会在目录下自动生成hexo的文件
    npm install --安装npm依赖包
    hexo generate --生成静态页面
    hexo server --生成本地服务

好了,这时候我们打开浏览器输入http://localhost:4000看看可不可以访问。如果默认的hexo博客出现,那么恭喜你,你已经搭建好了自己的博客,接下来我们就要将它发布到网上。
buildHexo_11
3.可能遇到的报错:

  • 日志报错
    这个报错一般是由于在命令执行中用户使用Ctrl+C强制中断了命令的执行,导致log中记录已经执行,但实际没有执行完成。解决办法:删除图中路径下的.log文件

buildHexo_7

  • 在非空文件夹下执行hexo init命令
    hexo init这个命令是自动生成hexo目录时使用的命令,使用他有一个前提是必须是空文件夹,如果出现了这个错误,把所有文件删除就行。如果还是报错,别着急,看看是不是有隐藏文件没有删除。

buildHexo_8

  • hexo命令未找到
    有的同学可能会出现在执行hexo命令时出现conmand not found的提示,这是由于hexo没有配到环境变量中,只需要手动配置一下就好了,这里演示一下win7的配置方式,其他系统也差不多,自行百度就好:

1.找到并进入根目录下node_modules文件夹,这时我们发现里面有很多文件夹,找到hexo文件夹,这里我们可以看到一个bin文件夹,进到bin目录下,复制当前路径:
buildHexo_9
2.右键我的电脑-->高级系统设置-->高级-->环境变量。在系统变量那栏找到Path并双击这行,在弹出的编辑系统变量这栏的变量值的最后先输入一个分号表示与前一个变量隔开,然后再把刚才复制的hexo路径添加到分号后面。
buildHexo_10

三、万事具备,只欠东风:将本地博客发布到网络上

这时候就要用到了我们的github:
1.创建远程仓库
新建一个跟自己账号名字一样的空仓库,如图:
buildHexo_2
buildHexo_3
2.连接本地与远程github仓库
打开本地博客的文件夹,打开_config.yml进行编辑
buildHexo_4
翻到文件最下方,将deploy的选项改成以下的形式,并将yournmae修改为你自己的名称:

    deploy:
    type: git
    repo: git@github.com:yourname/yourname.github.io.git
    branch: master 

然后在GitBash中执行

    npm install hexo-deployer-git --save

这时候,我们再最后执行一句

    hexo deploy

就可以在浏览器中访问http://yourname.github.io/来进入你的博客啦
大功告成!!

四、一鼓作气:详细了解Hexo

博客已经可以访问了,但我相信大家对Hexo还是一头雾水,现在我们来深入学习一下Hexo:
1.Hexo的基本命令

    hexo generate --生成个人博客所需的静态页面
    hexo server --本地预览
    hexo deploy --部署我们的个人博客
    hexo clean --清除缓存

这几个命令都能用首字母缩写完成

    hexo g --generate 
    hexo s --server 
    hexo d --deploy 

2.写文章的需要用到下面的命令

    hexo new "postName" --新建文章
    hexo new page "pageName" --新建页面

编辑我们的博客的时候可以使用

    hexo s --debug

然后访问http://localhost:4000/来进入调试模式,更改了配置或文章后随时刷新页面来查看效果。
Hexo的文章支持的是MarkDown语法。网上有很多资料,这里提供一个传送门

3.我们每次部署的步骤是

    hexo clean 
    hexo generate 
    hexo deploy

后两步可以简写为hexo g -d,另外我们也可以使用hexo help来查看hexo命令帮助

4.目录结构说明
hexo init 出来的文件各自的作用如下:

      `-----------
      |  +-- .deploy       #hexo deploy生成的文件
      |  +-- node_modules  #npm组件
      |  +-- public        #生成的静态网页文件
      |  +--scaffolds      #模板
      |  +-- source        #博客正文和其他源文件
      |  |   +-- _posts    #我们自己写的文章以md结尾
      |  +-- themes        #主题
      |  +-- _config.yml   #全局配置文件
      |  `-- package.json  #定义了hexo所需要的各种模块

5.配置文件
搭建好博客后,我们的各种细节配置基本都是在配置文件中完成的,Hexo中的配置文件一共分2中,在文件夹跟目录下的_config.yml叫做站点配置文件,同样的文件名我们可以在theme文件夹下的主题文件夹里面也找的。而主题文件夹下的_config.yml叫做主题配置文件。这里说明一下站点配置文件:

# Hexo Configuration
## Docs: http://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site #站点信息
title:  #标题
subtitle:  #副标题
description:  #站点描述,给搜索引擎看的
author:  #作者
email:  #电子邮箱
language: zh-CN #语言
# URL #链接格式
url:  #网址
root: / #根目录
permalink: :year/:month/:day/:title/ #文章的链接格式
tag_dir: tags #标签目录
archive_dir: archives #存档目录
category_dir: categories #分类目录
code_dir: downloads/code
permalink_defaults:
# Directory #目录
source_dir: source #源文件目录
public_dir: public #生成的网页文件目录
# Writing #写作
new_post_name: :title.md #新文章标题
default_layout: post #默认的模板,包括 post、page、photo、draft(文章、页面、照片、草稿)
titlecase: false #标题转换成大写
external_link: true #在新选项卡中打开连接
filename_case: 0
render_drafts: false
post_asset_folder: false
relative_link: false
highlight: #语法高亮
  enable: true #是否启用
  line_number: true #显示行号
  tab_replace:
# Category & Tag #分类和标签
default_category: uncategorized #默认分类
category_map:
tag_map:
# Archives
2: 开启分页
1: 禁用分页
0: 全部禁用
archive: 2
category: 2
tag: 2
# Server #本地服务器
port: 4000 #端口号
server_ip: localhost #IP 地址
logger: false
logger_format: dev
# Date / Time format #日期时间格式
date_format: YYYY-MM-DD #参考http://momentjs.com/docs/#/displaying/format/
time_format: H:mm:ss
# Pagination #分页
per_page: 10 #每页文章数,设置成 0 禁用分页
pagination_dir: page
# Disqus #Disqus评论,替换为多说
disqus_shortname:
# Extensions #拓展插件
theme: landscape-plus #主题
exclude_generator:
plugins: #插件,例如生成 RSS 和站点地图的
- hexo-generator-feed
- hexo-generator-sitemap
# Deployment #部署,将 lmintlcx 改成用户名
deploy:
  type: git
  repo: github创库地址.git
  branch: master

有时候我们部署了以后自己博客的链接打不开,查看生成的静态文件也没有index.html,或者是各种奇怪的报错。这时候有可能是我们的站点配置文件_config.yml格式出现了问题。这时候不妨去一些YAML格式检测网站去检测一下格式是否正确:传送门

五、结语

完成上面的操作,你就已经一只脚踏进了hexo的大门,这时的你肯定还有很多疑问,比如博客的头像怎么更换,博客的主题怎么配置等等等等。这里先留下一个悬念,有兴趣的同学可以先行查询一些资料^_^


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/fi...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

社会李 收藏了文章 · 2018-09-11

98道经典Vue面试题总结(长期更新)

写在前面


参考答案在看云平台发布,如果大家想阅读参考答案,可直接购买。

一次购买,文档所有部分(vue、http、js等)均可以观看,无时间限制,文档长期更新!

有什么意见与建议欢迎您及时联系作者或留言回复!

阅读文档47道HTTP面试题总结

Vue开发交流微信群:(二维码定期更新,长期有效!或添加群主微信hanxuming888进群)

图片描述

本文档基于vue-cli技术栈总结了

  • vue-cli工程
  • vue.js核心知识
  • vue-router路由
  • vuex状态管理器
  • axios等http请求
  • 移动端适配
  • Tab切换等常用功能
  • vue与原生app混合交互
  • vue生产环境部署
  • vue各项技术源码解析
  • MVVM设计模式
  • vue-cli工程深入拓展

等12个关于vue-cli开发的方面。

不仅可以帮你一次性详细阅读所有关于vue的面试题、更可以帮你拓展关于vue开发的视野。

关于vue的试题,看这一篇文档就够了!


vue-cli工程


1、构建的 vue-cli 工程都到了哪些技术,它们的作用分别是什么?

2、vue-cli 工程常用的 npm 命令有哪些?

3、请说出vue-cli工程中每个文件夹和文件的用处

4、config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置

5、请你详细介绍一些 package.json 里面的配置

参考答案:https://www.kancloud.cn/hanxu...


vue核心知识点


1、对于Vue是一套渐进式框架的理解

2、vue.js的两个核心是什么?

3、请问 v-ifv-show 有什么区别

4、vue常用的修饰符

5、v-on可以监听多个方法吗?

6、vue中 key 值的作用

7、vue-cli工程升级vue版本

8、vue事件中如何使用event对象?

9、$nextTick的使用

10、Vue 组件中 data 为什么必须是函数

11、v-for 与 v-if 的优先级

12、vue中子组件调用父组件的方法

13、vue中 keep-alive 组件的作用

14、vue中如何编写可复用的组件?

15、什么是vue生命周期生命周期钩子函数?

16、vue生命周期钩子函数有哪些?

17、vue如何监听键盘事件中的按键?

18、vue更新数组时触发视图更新的方法

19、vue中对象更改检测的注意事项

20、解决非工程化项目初始化页面闪动问题

21、v-for产生的列表,实现active的切换

22、v-model语法糖的组件中的使用

23、十个常用的自定义过滤器

24、vue等单页面应用及其优缺点

25、什么是vue的计算属性?

26、vue-cli提供的几种脚手架模板

27、vue父组件如何向子组件中传递数据?

28、vue-cli开发环境使用全局常量

29、vue-cli生产环境使用全局常量

30、vue弹窗后如何禁止滚动条滚动?

31、计算属性的缓存和方法调用的区别

32、vue-cli中自定义指令的使用

参考答案:https://www.kancloud.cn/hanxu...


vue-router


1、vue-router如何响应 路由参数 的变化?

2、完整的 vue-router 导航解析流程

3、vue-router有哪几种导航钩子( 导航守卫 )?

4、vue-router的几种实例方法以及参数传递

5、vue-router的动态路由匹配以及使用

6、vue-router如何定义嵌套路由?

7、<router-link></router-link>组件及其属性

8、vue-router实现路由懒加载( 动态加载路由 )

9、vue-router路由的两种模式

10、history路由模式与后台的配合

参考答案:https://www.kancloud.cn/hanxu...


vuex


1、什么是vuex?

2、使用vuex的核心概念

3、vuex在vue-cli中的应用

4、组件中使用 vuex 的值和修改值的地方?

5、在vuex中使用异步修改

6、pc端页面刷新时实现vuex缓存

参考答案:https://www.kancloud.cn/hanxu...


http请求


1、Promise对象是什么?

2、axios、fetch与ajax有什么区别?

3、什么是JS的同源策略和跨域问题?

4、如何解决跨域问题?

5、vue-cli中如何使用JSON数据模拟

6、vue-cli中http请求的统一管理。

7、axios有什么特点?

参考答案:https://www.kancloud.cn/hanxu...


UI样式


1、.vue组件的scoped属性的作用

2、如何让CSS只在当前组件中起作用?

3、vue-cli中常用的UI组件库

4、如何适配移动端?【 经典 】

5、移动端常用媒体查询的使用

6、垂直居中对齐

7、vue-cli中如何使用背景图片?

8、使用表单禁用时移动端样式问题

9、多种类型文本超出隐藏问题

参考答案:https://www.kancloud.cn/hanxu...


常用功能


1、vue中如何实现tab切换功能?

2、vue中如何利用 keep-alive 标签实现某个组件缓存功能?

3、vue中实现切换页面时为左滑出效果

4、vue中父子组件如何相互调用方法?

5、vue中央事件总线的使用

参考答案:https://www.kancloud.cn/hanxu...


混合开发


1、vue如何调用 原生app 提供的方法?

2、原生app 调用 vue 提供的方法,并将值传递到 .vue 组件中

参考答案:https://www.kancloud.cn/hanxu...


生产环境


1、vue打包命令是什么?

2、vue打包后会生成哪些文件?

3、如何配置 vue 打包生成文件的路径?

4、vue如何优化首屏加载速度?

参考答案:https://www.kancloud.cn/hanxu...


MVVM设计模式


1、MVC、MVP与MVVM模式

2、MVC、MVP与MVVM的区别

3、常见的实现MVVM几种方式

4、Object.defineProperty()方法

5、实现一个自己的MVVM(原理剖析)

6、 ES6中类和定义

7、JS中的文档碎片

8、解构赋值

9、Array.from与Array.reduce

10、递归的使用

11、Obj.keys()与Obj.defineProperty

12、发布-订阅模式

13、实现MVVM的思路分析

参考答案:https://www.kancloud.cn/hanxu...


源码剖析


1、vue内部与运行机制:

  • Vue.js 全局运行机制
  • 响应式系统的基本原理
  • 什么是 Virtual DOM?
  • 如何编译template 模板?
  • diff算法
  • 批量异步更新策略及 nextTick 原理?
  • proxy代理?

2、vuex工作原理详解

  • Vue.mixin
  • Vue.use

参考答案:https://www.kancloud.cn/hanxu...


深入拓展


1、vue开发命令 npm run dev 输入后的执行过程

2、vue的服务器端渲染

3、从零写一个npm安装包

4、vue-cli中常用到的加载器

5、webpack的特点

参考答案:https://www.kancloud.cn/hanxu...


查看原文

社会李 发布了文章 · 2018-04-27

如何在同一台电脑上使用github和gitlab

gitlabgithub_logo

换了工作后使用的是gitlab,这样对github的使用会有影响。为了解决这个问题,搜了很多资料后完美解决。现在把它记录下来。

前言

在同一台电脑上使用github和gitlab,主要的思想就是使用不同的仓库时,切换成不同的账号。不同账号的sshKey分别对应github和gitlab。接下来跟着我看看怎么做吧^_^

一、生成ssh密钥

这里我们要做的事情就是分别对githubn和gitlab生成对应的密钥(默认情况下本地生成的秘钥位于/Users/用户名/.ssh/),并且配置git访问不同host时访问不同的密钥,流程如下:
1、 在gitbash中使用ssh-keygen -t rsa -C "公司邮箱地址"生成对应的gitlab密钥:id_rsaid_rsa.pub
2、 将gitlab公钥即id_rsa.pub中的内容配置到公司的gitlab上
3、 在gitbash中使用ssh-keygen -t rsa -C "github地址" -f ~/.ssh/github_rsa生成对应的github密钥:github_rsagithub_rsa.pub
4、 将github公钥即github_rsa.pub中的内容配置到自己的github上
5、 进入密钥生成的位置,创建一个config文件,添加配置:

# gitlab
Host gitlab
    HostName git.xxx.com #这里填你的gitlab的Host
    User git
    IdentityFile ~/.ssh/id_rsa
# githab
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_rsa

二、测试连接

在密钥的生成位置/Users/用户名/.ssh/下使用gitbash运行 ssh -T git@hostName命令测试sshkey对gitlab与github的连接:

catalinaLi@catalinaLi MINGW64 ~/.ssh
$ ssh -T git@gitlab
Welcome to GitLab, catalinaLi!

catalinaLi@catalinaLi MINGW64 ~/.ssh
$ ssh -T git@github.com
Hi catalinaLi! You've successfully authenticated, but GitHub does not provide shell access.

如果出现上图结果就说明连接成功,如果不是这样的话就仔细看看第一步哪里做错了。

三、配置git仓库

这里我们要用到git的config配置。git的config文件记录了用户的基本信息,我们的账号信息也在里面,这里我们要做的就行在不同的本地仓库配置不同的用户信息来访问不同的远程仓库。config文件通常有三个位置:

  • system (系统级别):
    位于Windows下在git的安装目录, 包含了适用于系统所有用户和所有库的值。如果你传递参数选项’--system’ 给 git config,它将明确的读和写这个文件。
  • global(用户级别):
    位于~/.gitconfig,具体到你的用户。你可以通过传递--global 选项使Git 读或写这个特定的文件。
  • local(仓库级别):
    位于 .git/config,无论你当前在用的库是什么,特定指向该单一的库。每个级别重写前一个级别的值。

简单了解后我们就可以来配置了

1. 用户级别配置
因为公司的代码使用频率较高,所以我们将git配置文件的global(用户级别)设置为公司的gitlab账号,在gitlab中使用如下命令:

$ git config --global user.name 'catalinaLi' #公司账号名称
$ git config --global user.email 'catalinaLi@companyName.com' #公司账号邮箱

2. 仓库级别配置
我们将local(仓库级别)配置成github的账号。此时我们需要先init一个git的仓库并进入里面后执行如下命令:

$ git config --local user.name 'username' #github账号名称
$ git config --local user.email 'username@gmail.com' #github账号邮箱

之后我们github的代码都应该在这个仓库下拉取。

3. 克隆代码

$ git clone git@github.com:catalinaLi/ideaTaotao.git

在使用github克隆代码时,因为配置了config, 所以会通过配置的host自动查找到git@github.com。对于gitlab也是相同的道理

至此,在同一台电脑上使用gitlab与github已经成功了,尽情感受吧。另外,大家可以寻找度娘来学习关于git的config的更多使用

参考资料

http://www.arccode.net/config...
https://segmentfault.com/a/11...


本文作者: catalinaLi
本文链接: http://catalinali.top/2018/no...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 13 收藏 10 评论 1

社会李 发布了文章 · 2018-02-26

微信开发之微信网页授权获取openid

wechatOAuth_logo

不知觉间已经接触了几次微信支付开发,而要进行微信支付就需要用户的唯一标识:openid。还记得第一次获取用户openid的时候就踩了很多坑。这两天又接触了一下,想着索性就把他记录下来,也便于以后查阅

一、准备工具

不管开发什么,官方的文档应该是第一个想到的这里把官方文档贴出来:微信网页授权文档
除此之外,我们还需要一个内网穿透的工具在开发环境下让微信能访问到我们的域名。我使用的是natapp。此类工具网上有很多,大家可以自行寻找。
这里我们使用微信提供的测试账号来作为演示

二、开始开发

内网穿透就不在这里演示了,下面我们直入主题:
1.填写网页授权域名
在这篇文档的一开始就埋了一个坑
wechatOAuth_1
这段话就是说,我们在开发前需要在图片中框红的位置填入我们所要开发的域名。这里我们使用的是测试环境,所以需要在测试账号管理页面的这个位置填入我们自己的域名,这里要注意填入域名的规则。
wechatOAuth_2
2.文档阅读
接着阅读文档我们可以发现网页授权有两种scope,
snsapi_base和snsapi_userinfo。两种scope都可以获取到opeid,不同的是snsapi_userinfo除了openid外还可以获取到用户的基本信息,但是需要用户手动进行确认。
再往下阅读我们可以看到官方文档的授权步骤

  • 第一步:用户同意授权,获取code
  • 第二步:通过code换取网页授权access_token以及openid
  • 第三步:刷新access_token(如果需要)
  • 第四步:拉取用户信息(需scope为 snsapi_userinfo)

我们只需要openid,所以我们只开发到第二步就好了。下面我们就按着官方步骤来开发。

3.获取code
查看文档后我们发现我们需要拼接一个url并且访问它。url的参数文档中写的很清楚了。看他的例子也能看个清楚。这里比较重要的是redirect_uri。这个参数所填的是一个链接。我们访问url后会自动转发到这个链接并且将我们需要的code以及拼接url中的state的值作为参数。这个redirect_uri的值要填入的是我们代码中的controller的位置。
所以这里我们需要一段代码:

/**
 * <pre>
 * Description: wechat OAuth2.0
 * Author:        lllx
 * Version:        1.0
 * Created at:    2018/2/1
 * </pre>
 */
@RestController
@RequestMapping("/weixin")
@Slf4j
public class WeixinController {

    @GetMapping("/auth")
    public void auth(@RequestParam("code") String code,@RequestParam("state") String state){
        log.info("auth开始了。。。。");
        log.info("code={}",code);
        log.info("state={}",state);
    }
}

我拼接的url,这里大家要注意根据自己的情况进行拼接。拼接成功后需要在微信app中进行访问

https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&redirect_uri=http://xxx/sell/weixin/auth&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

访问后的结果
wechatOAuth_3
这样我们就拿到了code
4.获取openid
继续查看文档,发现我们只需要使用获取到的code再访问另一个url就可以获取到我们想要的了。接着上面的代码

/**
 * <pre>
 * Description: wechat OAuth2.0
 * Author:        lllx
 * Version:        1.0
 * Created at:    2018/2/1
 * </pre>
 */
@RestController
@RequestMapping("/weixin")
@Slf4j
public class WeixinController {

    @GetMapping("/auth")
    public void auth(@RequestParam("code") String code,@RequestParam("state") String state){
        log.info("auth开始了。。。。");
        log.info("code={}",code);
        log.info("state={}",state);
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=xxxx&secret=xxxx&code="+code+"&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject(url, String.class);
        log.info("result={}",result);
    }
}

这时我们再次访问第三步拼接的url就可以看到如下结果。
wechatOAuth_4
将结果格式化一下我们可以就看到我们想要的openid
wechatOAuth_5

三、总结

流程看起来还是很简单的。但以上只是一个最简单、最直接的手工获取openid的例子。真正在使用过程中需要结合自身的业务流程来进行开发,这时可能就有些麻烦了。此时我们也可以借助一些网上第三方sdk来开发。例如:weixin-java-tools。


本文作者: catalinaLi
本文链接: http://catalinali.top/2018/we...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 3 收藏 4 评论 1

社会李 发布了文章 · 2018-01-27

使用IDEA搭建第一个SpringBoot程序

startSpringBoot_logo

近来在研究SpringBoot的使用,现在把使用IDEA搭建一个SpringBoot的HelloWorld程序记录下来

新建一个SpringBoot环境

打开你的IntelliJ IDEA,然后选择Create New Project。如图,我们要选择一个Spring Initializr
startSpringBoot_1
之后我们填入自己的Group与Artifact(项目名字)后选择Next
startSpringBoot_2
由于我们是Web项目,所以我们先勾选最基本的Web选项,其他的待我们用到了再勾选。
startSpringBoot_3
接下来是选择项目存放的位置
startSpringBoot_4
选择Finish之后静静等待IEAD加载索引搭建工程。OK,一个完整的SpringBoot项目的结构我们已经搭建好了。
startSpringBoot_5
上图我用红框圈住的可以删掉,保持项目的简洁。这样,一个可供使用的SpringBoot环境就搭好了。

SpringBoot介绍

使用SpringBoot可以让你快速搭建一个SpringWeb项目,它使用“习惯优于配置”的理念让你的项目快速运行起来。使用SpringBoot可以很容易创建一个独立运行(运行jar,内嵌Servlet容器)、准生产级别的基于Spring框架的项目。使用SpringBoot你可以不用或者是很少的配置。
使用SpringBoot的优点:

  • 快速构建项;
  • 对主流开发框架的无配罝集成;
  • 项目可独立运行,无须外部依赖Servlet容器;
  • 提供运行时的应用监控;
  • 极大地提髙了开发、部署效率;
  • 与云计算的天然集成。

SpringBoot入门

我们来写一个SpringBoot的HelloWorld
打开项目自动生成的DemoApplication类,修改代码:

@Controller
@SpringBootApplication
@Configuration
public class DemoApplication {

    @RequestMapping("hello")
    @ResponseBody
    public String hello(){
        return "hello world!";
    }

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

然后右键选择Run
startSpringBoot_7
然后打开浏览器访问http://localhost:8080/hello就可以看到我们写的HelloWorld
startSpringBoot_8
代码说明:
1、@SpringBootApplication:Spring Boot项目的核心注解,主要目的是开启自动配置。;
2、@Configuration:这是一个配置Spring的配置类;
3、@Controller:标明这是一个SpringMVC的Controller控制器;
4、main方法:在main方法中启动一个应用,即:这个应用的入口;

这次只是记录了一下搭建SpringBoot的HelloWorld过程。具体的SpringBoot知识还需要大家去深入学习


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/st...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 3 收藏 3 评论 0

社会李 发布了文章 · 2018-01-08

使用JSONP解决ajax跨域

jsonp_logo

在日常开发中,不免遇到跨域的问题。在这里我们介绍使用Jsonp来解决ajax跨域的问题

什么是跨域?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。简单的理解就是开发时当客户端所在的工程与服务端的ip不同或者端口不同时进行请求,就产生了跨域,进而不能请求数据。

什么是JSONP?

官方的说法是:JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
我们都知道,JSON是一种数据交换格式。而JSONP是一种的数据调用方式。它利用<script>标签可以跨域的特性,将需要跨域获取的数据包在<script>标签中来达到目的。当我们需要使用JSONP时,客户端调用服务端时传递一个callback,这样服务端根据callback的有无就可以判断是否需要使用JSONP。可以简单的理解为带callback的json就是jsonp。

JSONP的使用

AJAX的使用与平常无异,只需要将dataType改为jsonp即可

        $.ajax({
            url : url,
            dataType : "jsonp",
            type : "GET",
            success : function(data){
                ...
            }
        });

服务端接收到以后,只需要手动判断一下有无callback再手动拼一对括号即可,这里以java为例

    @ResponseBody
    @RequestMapping(value="xxx")
    public String testJsonp(String callback) {
        Student result = new Student();
        //响应结果之前,判断是否为jsonp请求
        if (StringUtils.isNotBlank(callback)) {
            //把结果封装成一个js语句响应
            return callback + "(" + JsonUtils.objectToJson(result)  + ");";
        }
        return JsonUtils.objectToJson(result);
    }

在Spring 4.1以上的版本也可以使用MappingJacksonValue来响应

    @ResponseBody
    @RequestMapping(value="xxx")
    public Object testJsonp(String callback) {
        Student result = new Student();
        //响应结果之前,判断是否为jsonp请求
        if (StringUtils.isNotBlank(callback)) {
            //把结果封装成一个js语句响应
            MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
            mappingJacksonValue.setJsonpFunction(callback);
            return mappingJacksonValue;
        }
        return result;
    }

怎么样,简单几步就可以跨域来访问服务端了。


本文作者: catalinaLi
本文链接: http://catalinali.top/2018/us...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 1 收藏 2 评论 1

社会李 发布了文章 · 2017-12-22

ActiveMQ从入门到实践

mq_logo

一、什么是ActiveMQ

首先我们应该先了解J2EE中的一个重要规范:JMS(The Java Message Service)Java消息服务。而JMS的客户端之间可以通过JMS服务进行异步的消息传输。它主要有两种模型:点对点和发布订阅模型。

点对点的模型特点:

  • 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)。
  • 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列。
  • 接收者在成功接收消息之后需向队列应答成功。

发布订阅模型特点:

  • 每个消息可以有多个消费者
  • 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
  • 为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。

JMS还定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。

  • StreamMessage -- Java原始值的数据流
  • MapMessage--一套名称-值对
  • TextMessage--一个字符串对象
  • ObjectMessage--一个序列化的 Java对象
  • BytesMessage--一个字节的数据流

其中我们用的最多的就是TextMessage字符串对象

消息中间件作为JMS的实现,在J2EE的企业应用中扮演着特殊的角色。ActiveMQ是一个易于使用的消息中间件。作为JMS的实现,消息中间件的使用步骤都大同小异,下面我们以ActiveMQ为例来介绍一下其使用。

二、ActiveMQ的基本使用

ActiveMQ的安装:
ActiveMQ安装很简单,只需从其官网下载至linux环境,解压并进入bin目录

./activemq start #启动
./activemq stop #停止
./activemq status #查看状态

使用启动命令运行就好了。然后我们打开浏览器进入管理后台http://yourip:8161/admin/
输入默认的账号密码:admin。就可以看到管控台了。
mq_1
然后我们使用java操作ActiveMQ,mq的使用基本都需要创建连接、session、Destination这么几步,我们直接看代码吧。
点对点的模型:
生产者代码:

    @Test
    public void testQueueProducer() throws Exception {
        //1、创建一个连接工厂对象,需要指定服务的ip及端口。
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.161:61616");
        //2、使用工厂对象创建一个Connection对象。
        Connection connection = connectionFactory.createConnection();
        //3、开启连接,调用Connection对象的start方法。
        connection.start();
        //4、创建一个Session对象。
        //第一个参数:是否开启事务。如果true开启事务,第二个参数无意义。一般不开启事务false。
        //第二个参数:应答模式。自动应答或者手动应答。一般自动应答。
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5、使用Session对象创建一个Destination对象。两种形式queue、topic,现在应该使用queue
        Queue queue = session.createQueue("test-queue");
        //6、使用Session对象创建一个Producer对象。
        MessageProducer producer = session.createProducer(queue);
        //7、创建一个Message对象,可以使用TextMessage。
        /*TextMessage textMessage = new ActiveMQTextMessage();
        textMessage.setText("hello Activemq");*/
        TextMessage textMessage = session.createTextMessage("hello activemq");
        //8、发送消息
        producer.send(textMessage);
        //9、关闭资源
        producer.close();
        session.close();
        connection.close();
    }

消费者代码:

    @Test
    public void testQueueConsumer() throws Exception {
        //创建一个ConnectionFactory对象连接MQ服务器
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.161:61616");
        //创建一个连接对象
        Connection connection = connectionFactory.createConnection();
        //开启连接
        connection.start();
        //使用Connection对象创建一个Session对象
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建一个Destination对象。queue对象
        Queue queue = session.createQueue("spring-queue");
        //使用Session对象创建一个消费者对象。
        MessageConsumer consumer = session.createConsumer(queue);
        //接收消息
        consumer.setMessageListener(new MessageListener() {
            
            @Override
            public void onMessage(Message message) {
                //打印结果
                TextMessage textMessage = (TextMessage) message;
                String text;
                try {
                    text = textMessage.getText();
                    System.out.println(text);
                } catch (JMSException e) {
                    e.printStackTrace();
                }
                
            }
        });
        //等待接收消息
        System.in.read();
        //关闭资源
        consumer.close();
        session.close();
        connection.close();
    }

当我们运行了生产者后,我们可以在管控台看到Queue中多了一条消息,并且还没有被消费
mq_2
当我们运行消费者后就可以接收到生产者发送的消息。
mq_3
并且管控台也出现了相应的变化
mq_4
发布订阅的模型:
生产者代码:

    @Test
    public void testTopicProducer() throws Exception {
        //1、创建一个连接工厂对象,需要指定服务的ip及端口。
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.72.121:61616");
        //2、使用工厂对象创建一个Connection对象。
        Connection connection = connectionFactory.createConnection();
        //3、开启连接,调用Connection对象的start方法。
        connection.start();
        //4、创建一个Session对象。
        //第一个参数:是否开启事务。如果true开启事务,第二个参数无意义。一般不开启事务false。
        //第二个参数:应答模式。自动应答或者手动应答。一般自动应答。
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //5、使用Session对象创建一个Destination对象。两种形式queue、topic,现在应该使用topic
        Topic topic = session.createTopic("test-topic");
        //6、使用Session对象创建一个Producer对象。
        MessageProducer producer = session.createProducer(topic);
        //7、创建一个Message对象,可以使用TextMessage。
        /*TextMessage textMessage = new ActiveMQTextMessage();
        textMessage.setText("hello Activemq");*/
        TextMessage textMessage = session.createTextMessage("topic message");
        //8、发送消息
        producer.send(textMessage);
        //9、关闭资源
        producer.close();
        session.close();
        connection.close();
    }

消费者代码:

    @Test
    public void testTopicConsumer() throws Exception {
        //创建一个ConnectionFactory对象连接MQ服务器
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.72.121:61616");
        //创建一个连接对象
        Connection connection = connectionFactory.createConnection();
        //开启连接
        connection.start();
        //使用Connection对象创建一个Session对象
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建一个Destination对象。topic对象
        Topic topic = session.createTopic("test-topic");
        //使用Session对象创建一个消费者对象。
        MessageConsumer consumer = session.createConsumer(topic);
        //接收消息
        consumer.setMessageListener(new MessageListener() {

            @Override
            public void onMessage(Message message) {
                //打印结果
                TextMessage textMessage = (TextMessage) message;
                String text;
                try {
                    text = textMessage.getText();
                    System.out.println(text);
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });
        System.out.println("topic消费者3启动。。。。");
        //等待接收消息
        System.in.read();
        //关闭资源
        consumer.close();
        session.close();
        connection.close();
    }

发布订阅模型具有严格的时间相关性,如果没有订阅者的话,发布者发布的内容就被浪费掉了。

三、ActiveMQ与Spring整合

Spring提供了JMSTemplate,极大地便利了MQ的使用,我们只需要提前在配置文件中配置相关的JMS配置,就可在代码中直接使用。
Spring配置文件:

    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://192.168.25.161:61616" />
    </bean>
    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>
    <!-- 配置生产者 -->
    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>
    <!--这个是队列(Queue)目的地,点对点的 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>spring-queue</value>
        </constructor-arg>
    </bean>
    <!--这个是主题(Topic)目的地,一对多的 -->
    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="itemAddTopic" />
    </bean>
    
    <!-- 接收消息配置 -->
    <!-- 配置监听器 -->
    <bean id="myMessageListener" class="cn.e3mall.search.listener.MyMessageListener" />
    <!-- 消息监听容器 -->
    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="queueDestination" />
        <property name="messageListener" ref="myMessageListener" />
    </bean>
    

配置好后可在代码中使用以下方法
生产者代码:

    @Test
    public void testQueueProducer() throws Exception {
        // 第一步:初始化一个spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
        // 第二步:从容器中获得JMSTemplate对象。
        JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
        // 第三步:从容器中获得一个Destination对象
        Queue queue = (Queue) applicationContext.getBean("queueDestination");
        // 第四步:使用JMSTemplate对象发送消息,需要知道Destination
        jmsTemplate.send(queue, new MessageCreator() {
            
            @Override
            public Message createMessage(Session session) throws JMSException {
                TextMessage textMessage = session.createTextMessage("spring activemq test");
                return textMessage;
            }
        });
    }

消费者代码:

public class MyMessageListener implements MessageListener {
    //继承MessageListener接口并重新它的onMessage方法
    @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容器中注入一个监听器,所以我们需要在配置文件中配置它,它随着Spring的启动而启动,并且实时监听。当有消息向它发送时,他会立即进行逻辑处理。


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/us...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 1 收藏 9 评论 0

社会李 发布了文章 · 2017-12-18

Java设计模式之策略模式

strategy_logo

在开发中我们会使用很多中间件,开发过程当然是单机配置,可是上生产环境的时候如何快速切换到集群配置,总不能修改代码吧,这里我们就可以结合Spring来使用策略模式。

一、什么是策略模式?

在开发中常常遇到这种情况,实现某一个功能有多方式,我们可以根据不同的条件选择不同的方式来完成该功能。最常用的方法是将这些算法方式写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的算法;或者通过if…else…或者case等条件判断语句来进行选择。
然而该类代码将较复杂,维护较为困难。如果我们把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。这就是策略模式。

二、基本的策略模式使用方法

我们直接来看例子:
1.策略接口

/**
 * Description: Strategy Pattern Interface
 * Created at:    2017/12/18
 */
public interface Strategy {
    void testStrategy();
}

2.准备两个实现类

/**
 * Description: 实现类A
 * Author:    lllx
 * Created at:    2017/12/18
 */
public class StrategyA implements Strategy {
    @Override
    public void testStrategy() {
        System.out.println("我是实现类A");
    }
}

/**
 * Description: 实现类B
 * Author:    lllx
 * Created at:    2017/12/18
 */
public class StrategyB implements Strategy {
    @Override
    public void testStrategy() {
        System.out.println("我是实现类B");
    }
}

3.策略执行Context类

/**
 * Description: 策略执行
 * Author:    lllx
 * Created at:    2017/12/18
 */
public class Context {
    
    private Strategy stg;
    
    public void doAction() {
        this.stg.testStrategy();
    }
    /*  Getter And Setter */
    public Strategy getStg() {
        return stg;
    }

    public void setStg(Strategy stg) {
        this.stg = stg;
    }
}

这时候我们准备一个main方法来测试一下他

/**
 * Description: StrategyTest
 * Author:    lllx
 * Created at:    2017/12/18
 */
public class StrategyTest {
    public static void main(String[] args) {
        Strategy stgB = new StrategyB();
        Context context = new Context(stgB);
        context.setStg(stgB);
        context.doAction();
    }
}

运行结果:
strategy_1
实例化不同的实现类可以出现不同的结果。

三、与Spring想结合的策略模式

我们主要利用Spring的核心IOC来实现它,还是使用上面的例子;
由于我们要在Spring的配置文件中来注入Context的实例:

    <bean id="context" class = "top.catalinali.search.service.impl.Context">
        <property name="stg" ref="stgB"/>
    </bean>
    <bean id="stgA" class = "top.catalinali.search.service.impl.StrategyA"/>
    <bean id="stgB" class = "top.catalinali.search.service.impl.StrategyB"/>

这样就可以通过只修改配置文件来更改context的实现类,从而达到策略模式的目的。

四、通过Spring使用策略模式替换中间件的单机与集群配置

在开发环境中,许多中间件使用的是单机配置。可到了生产我们就需要使用集群配置。这里我们就可以通过策略模式来快速改变中间件的配置,现在我们以Redis为例:
1.策略接口
首先我们把Redis方法抽成一个接口

public interface JedisClient {
    String set(String key, String value);
    String get(String key);
    Boolean exists(String key);
    Long expire(String key, int seconds);
    Long ttl(String key);
    Long incr(String key);
    Long hset(String key, String field, String value);
    String hget(String key, String field);
    Long hdel(String key, String... field);
    Boolean hexists(String key, String field);
    List<String> hvals(String key);
    Long del(String key);
}

2.单机和集群两个实现类
这里我们准备单机和集群两个实现类:JedisClientPool和JedisClientCluster。实现上面的JedisClient接口,分别使用单机和集群的代码来实现这些方法。因为代码冗长就不在这里贴出来了。
3.配置文件
我们使用不同的环境只需要把不用的配置注释掉就好。

    <!-- 连接redis单机版 -->
    <bean id="jedisClientPool" class="top.catalinali.common.jedis.JedisClientPool">
        <property name="jedisPool" ref="jedisPool"></property>
    </bean>
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="host" value="192.168.72.121"/>
        <constructor-arg name="port" value="6379"/>
    </bean>
    <!-- 连接redis集群 -->
    <!-- <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
        <property name="jedisCluster" ref="jedisCluster"/>
    </bean>
    <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean> 
            </set>
        </constructor-arg>
    </bean> -->

这样在我们开发时只需要注释掉连接集群的配置,而在上线时注释掉单机的配置就好。

参考文章

spring与策略模式


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/st...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 0 收藏 0 评论 0

社会李 发布了文章 · 2017-11-27

Vue.js小白入门,搭建开发环境

installvue_logo

最近Vue.js的热度持续上升,甚至有标题说2017再不会Vue.js就out了。而作为一个不排斥前段的后端码农来说,当然也要跟得上时代。近来准备放下手中的DOM操作,来一次Vue.js从入门到放弃。现将环境搭建过程记录下来。


环境准备

  • Node.js Javascript的运行时环境
  • npm Node.js下的包管理工具
  • webpack 前端资源模块化管理和打包工具
  • vue-cli 脚手架构建工具
  • cnpm npm的淘宝镜像

如果你像我一样是个后端开发者,并且对以上的工具还处在一脸懵逼的状态下。那么可以先看一下这篇文章萌新也能懂的现代 JavaScript 开发。了解一下现代 JavaScript的演变过程。

Vue.js安装

1. Node.js的安装非常容易,首先从官网下载你所需操作系统的版本,然后一直下一步就ok,这里贴个菜鸟教程的传送门
安装完成之后,在命令行敲出node -v,如果出现对应版本号,则表示安装成功。
installvue_01
2. npm是随同Node.js一起安装的包管理工具,直接在命令行敲出npm -v就可以查看是否安装成功。
installvue_02
npm包管理器虽然有了,但是由于npm下载需要依赖包的服务器地址在国外,导致很多资源访问会很慢。所以我们可以安装淘宝的国内镜像。
3. 在命令行敲出 npm install -g cnpm --registry=http://registry.npm.taobao.org
这样就可以使用 cnpm 命令来安装模块了:

cnpm install [name]

4. 安装webpack

cnpm install webpack -g

5. 安装vue脚手架

npm install vue-cli -g

初始化一个Vue.js环境

在电脑上新建一个文件夹用来存放我们的代码。然后使用命令行进入这个文件夹cd 目录路径
之后使用命令

vue init webpack name

来初始化一个vue环境,这个命令的意思是初始化一个项目,其中webpack是构建工具,也就是整个项目是基于webpack的。在安装过程会有一些初始化的设置,我们可以采用默认配置,一路回车 。
installvue_04
从上图的我们还可以看到vue很贴心的告诉了我们快速开始(To get started)的命令
安装项目依赖
一定要从官方仓库安装,npm 服务器在国外所以这一步安装速度会很慢。

npm install

不要从国内镜像cnpm安装(会导致后面缺了很多依赖库)

cnpm install

安装 vue 路由模块vue-router和网络请求模块vue-resource

cnpm install vue-router vue-resource --save

启动项目

npm run dev

运行成功以后他会告诉你ip和端口号
installvue_05
访问这个地址
installvue_06
如果出现上图。恭喜你,已经可以开始Vue.js之旅了。


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/in...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 6 收藏 20 评论 0

社会李 发布了文章 · 2017-11-06

走进Redis:Redis的安装、使用以及集群的搭建

redis_logo

今天学习了淘淘商城中的redis的使用,在这里把它记录下来。


一、Redis的安装

Redis的安装是很简单的,安装之前我们需要c语言的编译环境。如果没有gcc需要在线安装。yum install gcc-c++

安装步骤:

第一步:redis的源码包上传到linux系统。
第二步:解压缩redis。tar -zxvf redis-3.0.0.tar.gz
第三步:编译。进入redis源码目录。make
第四步:安装。make install PREFIX=/usr/local/redis,PREFIX参数指定redis的安装目录。

二、Redis的启动与基本操作

1.运行redis
在redis的安装目录下直接运行./redis-server就可以启动redis,但这是前端启动。如果我们想后台启动就需要:
①进入redis-3.0.0.tar.gz解压出来的文件夹,复制里面的redis.conf文件到安装目录下。然后将daemonize改为yesredis_1
②执行./redis-server redis.conf运行redis。这样redis就后台运行了,我们可以使用ps aux|grep redis来查看redis的运行状态
redis_2
我们可以使用以下命令来进入操作redis:

./redis-cli ##进入redis客户端
./redis-cli -h 192.168.72.121 -p 6379 ##连接指定ip和端口的redis服务器
./redis-cli shutdown ##关闭redis客户端

2.redis中的五种类型
先来看几个操作数据库的基本命令:

KEYS *                   ##获得当前数据库的所有键
EXISTS key [key ...]     ##判断键是否存在,返回个数,如果key有一样的也是叠加数
DEL key [key ...]        ##删除键,返回删除的个数
TYPE key                 ##获取减值的数据类型(string,hash,list,set,zset)
FLUSHALL                 ##清空所有数据库
Expire key second        ##设置key的过期时间
Ttl key                  ##查看key的有效期
Persist key              ##清除key的过期时间。Key持久化。

redis中所有的数据都是Key-value类型的,其中有五种主要数据类型:字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset)。而在这五种类型中,我们最常用的是字符串类型,散列类型。这里简单介绍一下字符串类型和散列类型:
字符串类型string

SET         ##赋值,用法: SET key value
GET         ##取值,用法: GET key
INCR        ##递增数字,仅仅对数字类型的键有用,相当于Java的i++运算,用法: INCR key
INCRBY      ##增加指定的数字,仅仅对数字类型的键有用,相当于Java的i+=3,用法:INCRBY key increment,意思是key自增increment,increment可以为负数,表示减少。
DECR        ##递减数字,仅仅对数字类型的键有用,相当于Java的i–,用法:DECR key
DECRBY      ##减少指定的数字,仅仅对数字类型的键有用,相当于Java的i-=3,用法:DECRBY key decrement,意思是key自减decrement,decrement可以为正数,表示增加。
INCRBYFLOAT ##增加指定浮点数,仅仅对数字类型的键有用,用法:INCRBYFLOAT key increment
APPEND      ##向尾部追加值,相当于Java中的”hello”.append(“ world”),用法:APPEND key value
STRLEN      ##获取字符串长度,用法:STRLEN key
MSET        ##同时设置多个key的值,用法:MSET key1 value1 [key2 value2 ...]
MGET        ##同时获取多个key的值,用法:MGET key1 [key2 ...]

散列类型hash

HSET        ##赋值,用法:HSET key field value
HMSET       ##一次赋值多个字段,用法:HMSET key field1 value1 [field2 values]
HGET        ##取值,用法:HSET key field
HMGET       ##一次取多个字段的值,用法:HMSET key field1 [field2]
HGETALL     ##一次取所有字段的值,用法:HGETALL key
HEXISTS     ##判断字段是否存在,用法:HEXISTS key field
HSETNX      ##当字段不存在时赋值,用法:HSETNX key field value
HINCRBY     ##增加数字,仅对数字类型的值有用,用法:HINCRBY key field increment
HDEL        ##删除字段,用法:HDEL key field
HKEYS       ##获取所有字段名,用法:HKEYS key
HVALS       ##获取所有字段值,用法:HVALS key
HLEN        ##获取字段数量,用法:HLEN key

其他的数据类型就不详细介绍了,相关资料可以点击传送门

三、Redis的持久化方案

Redis的所有数据都是保存到内存中的。
Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案,一直开启,不会被关闭。
redis_Rdb
通过上图我们可以看到,dump.rdb会在以下情况保存一次。

  • 900秒(15分钟)之内至少有1个KEY进行了改变
  • 300秒(5分钟)之内至少有10个KEY进行了改变
  • 60秒(1分钟)之内至少有10000个KEY进行了改变

aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。要想开启aof模式需要在redis.conf配置文件中将appendonly改为yes
redis_aof

四、Redis集群的搭建

1.Redis集群特点

Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。其redis-cluster架构图如下:
redis_cluster
其架构细节:
1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
2、节点的fail是通过集群中超过半数的节点检测失效时才生效。
3、客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
4、redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value。
5、Redis集群预分好16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个槽中。

2.Redis集群环境搭建

Redis集群中至少应该有三个节点。要保证集群的高可用,需要每个节点有一个备份机。
Redis集群至少需要6台服务器。由于条件限制,这里采用与淘淘商城相同的方式搭建伪分布式。在一台虚拟机运行6个redis实例。需要修改redis的端口号7001-7006。
第一步:创建6个redis实例,每个实例运行在不同的端口。需要修改redis.conf配置文件,将端口号修改成7001-7006。除此之外,还需要把cluster-enabled yes前的注释去掉。
第二步:启动每个redis实例。这里我们可以自己写一个shell脚本,这里给出我的也就是淘淘商城中所使用的脚本:

cd redis01
./redis-server redis.conf
cd ..
cd redis02
./redis-server redis.conf
cd ..
cd redis03
./redis-server redis.conf
cd ..
cd redis04
./redis-server redis.conf
cd ..
cd redis05
./redis-server redis.conf
cd ..
cd redis06
./redis-server redis.conf
cd ..

关闭集群的脚本也类似:

./redis-cli -p 7001 shutdown
./redis-cli -p 7002 shutdown
./redis-cli -p 7003 shutdown
./redis-cli -p 7004 shutdown
./redis-cli -p 7005 shutdown
./redis-cli -p 7006 shutdown

记得在运行脚本前要添加可执行(x)的权限:chmod u+x fileName.sh
第三步:使用ruby脚本搭建集群。
首先我们需要安装ruby运行环境

yum install ruby
yum install rubygems

然后我们需要安装ruby脚本运行使用的包,将这个文件放在集群文件根目录下,然后运行

gem install redis-3.0.0.gem

文件我上传在了CSDN
这时我们就可以启动集群环境了,运行下面这条命令:

./redis-trib.rb create --replicas 1 192.168.72.121:7001 192.168.72.121:7002 192.168.72.121:7003 192.168.72.121:7004 192.168.72.121:7005  192.168.72.121:7006

从这条命令我们可以看出使用6个节点来创建一个集群,集群中每个主节点有1个从节点。运行过程中输入一个yes就成功了。需要注意的是在真正搭建的时候一定要关闭防火墙。这时候我们查看进程
第四步:连接Redis集群
因为每一个节点都是互联互通的,所以我们不论连哪个节点都是可以的。

五、使用Java操作Redis

redis的客户端有很多,从官网中我们可以看出来,不仅支持的语言众多,而且很多语言有不止一种连接方式。
redis_client
这里我们采用在JAVA中使用最广泛的Jedis作为实例。

1.连接单机版

    @Test
    public void testJedis() throws Exception {
        // 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
        Jedis jedis = new Jedis("192.168.25.153", 6379);
        // 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
        String result = jedis.get("hello");
        // 第三步:打印结果。
        System.out.println(result);
        // 第四步:关闭Jedis
        jedis.close();
    }

使用起来很简单,不过通常在连接单机版的时候我们采用的是连接池的方式。

2.连接单机版使用连接池

    @Test
    public void testJedisPool() throws Exception {
        // 第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。
        JedisPool jedisPool = new JedisPool("192.168.25.153", 6379);
        // 第二步:从JedisPool中获得Jedis对象。
        Jedis jedis = jedisPool.getResource();
        // 第三步:使用Jedis操作redis服务器。
        jedis.set("jedis", "test");
        String result = jedis.get("jedis");
        System.out.println(result);
        // 第四步:操作完毕后关闭jedis对象,连接池回收资源。
        jedis.close();
        // 第五步:关闭JedisPool对象。
        jedisPool.close();
    }

连接集群的方式就又稍微不一样了。

3.连接集群版

    @Testjava
    public void testJedisCluster() throws Exception {
        // 第一步:使用JedisCluster对象。需要一个Set<HostAndPort>参数。Redis节点的列表。
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.72.121", 7001));
        nodes.add(new HostAndPort("192.168.72.121", 7002));
        nodes.add(new HostAndPort("192.168.72.121", 7003));
        nodes.add(new HostAndPort("192.168.72.121", 7004));
        nodes.add(new HostAndPort("192.168.72.121", 7005));
        nodes.add(new HostAndPort("192.168.72.121", 7006));
        JedisCluster jedisCluster = new JedisCluster(nodes);
        // 第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。
        jedisCluster.set("hello", "100");
        String result = jedisCluster.get("hello");
        // 第三步:打印结果
        System.out.println(result);
        // 第四步:系统关闭前,关闭JedisCluster对象。
        jedisCluster.close();
    }

本文作者: catalinaLi
本文链接: http://catalinali.top/2017/bu...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 4 收藏 24 评论 0

社会李 发布了文章 · 2017-10-31

Nginx初探究:安装与简单使用

nginx_logo

在学习淘淘商城的过程中接触到了nginx,今天就把使用它的过程记录下来,作为留存。

一、什么是Nginx

Nginx是一款高性能的http服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。

应用场景

  • http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。
  • 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
  • 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

二、nginx安装

1.官网下载nginx源码。

2.外部环境准备:

  • 需要安装gcc的环境:yum install gcc-c++
  • 第三方的开发包:
    ① PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库。
yum install -y pcre pcre-devel

②zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。

yum install -y zlib zlib-devel

③OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。nginx不仅支持http协议,还支持https(即在ssl协议上传输http)

yum install -y openssl openssl-devel

3.正式安装

第一步:把nginx的源码包上传到linux系统
第二步:解压缩

tar zxf nginx-1.8.0.tar.gz 

第三步:使用configure命令创建一makeFile文件。
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi
注意:以上都是一些安装时配置nginx的一些参数,具体含义可以自行百度。另外在启动nginx之前,上边将临时文件目录指定为/var/temp/nginx,需要在/var下创建temp及nginx目录

mkdir /var/temp/nginx/client -p

第四步:编译,运行make命令
第五步:安装运行make install命令
第六步:测试
进入安装目录下的sbin文件,运行./nginx后,打开浏览器访问主机ip。
注意:①默认是80端口。②是否关闭防火墙。
nginx_1
如果出现上图,恭喜你,nginx安装成功。
相关命令:

./nginx -s stop ##关闭nginx
./nginx -s quit ##关闭nginx(推荐使用)
./nginx -s reload ##重启nginx

三、配置虚拟主机

1.通过端口号区分虚拟主机

打开nginx的配置文件

vim /usr/local/nginx/conf/nginx.conf

可以看到一个server节点,这个就是我们配置虚拟主机的关键,每一个此节点代表一台主机。

    server {
        listen       80;    ##端口号
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;    ##nginx安装目录下的html目录
            index  index.html index.htm; ##每台主机对应的页面
        }
    }

当我们配置了多个server,就相当于配置了多个虚拟主机。这时我们就可以通过不同的端口号来进行访问。

2.通过域名区分虚拟主机

首先我们要知道当我们打开浏览器访问每一个域名的时候,每一个域名对应的是一个ip地址。并且一个ip地址可以被多个域名绑定。当我们在本地hosts文件(C:WindowsSystem32driversetc)中配置了域名与ip的对应的映射关系时,浏览器就不会再去走DNS服务器
为了方便测试,我们先在本地hosts文件配置一下测试所用数据

192.168.71.121 www.taobao.com
192.168.21.121 www.baidu.com

然后配置两个server节点

    server {
        listen       80;
        server_name  www.taobao.com; ##不同域名配置

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html-taobao; ##不同域名访问的不同文件夹
            index  index.html index.htm;
        }
    }
    server {
        listen       80;
        server_name  www.baidu.com; ##不同域名配置

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html-baidu; ##不同域名访问的不同文件夹
            index  index.html index.htm;
        }
    }

然后在浏览器上访问这两个地址就可以访问到我们配置的两台虚拟主机。

四、反向代理

1.什么是反向代理

两个域名指向同一台nginx服务器,用户访问不同的域名显示不同的网页内容。
两个域名是www.sian.com.cn和www.sohu.com
nginx服务器使用虚拟机192.168.101.3

2.实现反向代理

第一步:安装两个tomcat,分别运行在8080和8081端口。
第二步:启动两个tomcat。
第三步:反向代理服务器的配置

upstream tomcat1 {
    server 192.168.25.148:8080;
    }
    server {
        listen       80;
        server_name  www.sina.com.cn;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcat1;
            index  index.html index.htm;
        }
    }
    upstream tomcat2 {
    server 192.168.25.148:8081;
    }
    server {
        listen       80;
        server_name  www.sohu.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcat2;
            index  index.html index.htm;
        }
    }

第四步:nginx重新加载配置文件
第五步:配置域名
在hosts文件中添加域名和ip的映射关系

192.168.71.121 www.sina.com.cn
192.168.71.121 www.sohu.com

五、负载均衡

如果一个服务由多条服务器提供,需要把负载分配到不同的服务器处理,需要负载均衡。

 upstream tomcat2 {
    server 192.168.71.121:8081;
    server 192.168.71.121:8082;
  }

可以根据服务器的实际情况调整服务器权重。权重越高分配的请求越多,权重越低,请求越少。默认是都是1

 upstream tomcat2 {
    server 192.168.71.121:8081;
    server 192.168.71.121:8082 weight=2;
    }

本文作者: catalinaLi
本文链接: http://catalinali.top/2017/he...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 5 收藏 18 评论 0

社会李 发布了文章 · 2017-09-27

记录:mysql中的case when|on duplicate key update|重复插入返回主键的用法

case_logo

在平时的开发中不免接触到数据库,这里记录一些平时开发中遇到的细节问题,与大家共勉。


mysql中的条件控制:case函数

在操作数据库的开发中不免遇到一些类似if else的判断,这时候就用到了Case函数,首先我们用网上用了好多次的例子来看看它的用法:

case when sex = '1' then '男'  
     when sex = '2' then '女'  
     else '其他' end

利用这个格式我们可以就可以完成类似if else的操作,比如:

SELECT
    SUM(
    case 
    when V.IN_OUT = '2' then -AMOUNT
    when V.IN_OUT = '1' then AMOUNT end) AMOUNT
FROM
    tb_financial

怎么样,很简单吧!

mysql中重复插入时更新

为了防止数据重复插入报错,我们可以让重复插入主键相同的数据时改为更新这条数据。
我们使用mysql官网的例子:

INSERT INTO t1 (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE t1 SET c=c+1 WHERE a=1;

按照官网的说法,如果列a被声明为UNIQUE并包含该值 1,则这两个语句具有类似的效果。当列b也是唯一的时候,则相当于下面这条sql:

UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

但是,并不建议ON DUPLICATE KEY UPDATE在具有多个唯一索引的表上使用。

MyBatis+MySQL 返回插入的主键ID

在使用Mybatis想返回插入的主键ID也很简单,只需要在insert的Mapper中添加useGeneratedKeys="true"和keyProperty="实体中主键属性名"两个属性:

<insert id="InsertTBFinancial" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO Tb_financial
            (id,
             amount,
             comment)
        VALUES
            (#{id},
             #{amount},
             #{comment})
      </insert>

这样在调用此方法后实体中的主键值就会自动返回:

Financial financial = new Financial();  
financial.setId("chenzhou");  
financial.setAmount("xxxx");  
financial.setComment("测试插入数据返回主键功能");  
  
System.out.println("插入前主键为:"+financial.getId());  
userDao.insertAndGetId(financial);//插入操作  
System.out.println("插入后主键为:"+financial.getId());  

本文作者: catalinaLi
本文链接: http://catalinali.top/2017/re...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。
查看原文

赞 0 收藏 0 评论 0

社会李 关注了用户 · 2017-09-26

mumubin @mumubin

关注 115

社会李 回答了问题 · 2017-09-08

解决Mybatis在做INSERT操作的时候如何返回主键?

报错说的很明白了,应该是你的id跟实体里的id没对应上

关注 8 回答 7

社会李 发布了文章 · 2017-09-06

Dubbo初体验:远程服务调用和管控台的搭建

hellodubbo_logo

Dubbo是一个阿里巴巴的分布式服务框架。虽然在很久以前阿里停止更新了,但是还是有很多公司在使用它。Dubbo致力于提供高性能和透明化的RPC远程服务调用方案以及SOA服务治理方案。通过他我们可以非常容易地通过Dubbo来构建分布式服务。哦,对了。好像最近阿里又开始更新了。

Dubbo的架构

hellodubbo_1
调用关系说明:

  • 服务容器负责启动,加载,运行服务提供者。

  • 服务提供者在启动时,向注册中心注册自己提供的服务。

  • 服务消费者在启动时,向注册中心订阅自己所需的服务。

  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  • 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

这张图和这段话你可能已经见过无数次了,但是我还是把它从官网复制了过来。原因就是这张图能很简洁的说么Dubbo的调用关系。如果你还没有使用过Dubbo,那这张图可以很快帮你理顺调用关系。

Hello Dubbo

我们在使用过程中一般是采用XML配置,原因就是简单方便。在使用之前我们需要搭建Dubbo的注册中心。官方推荐的注册中心是zookeeper。如果你还没有搭建好zookeeper,那么可以看看我之前写的小白从头到脚搭建zookeeper集群的过程
1.Dubbo依赖
如果你使用的是Maven项目,在使用Dubbo的地方加入下面的依赖即可:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.jboss.netty</groupId>
            <artifactId>netty</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
</dependency>
<dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>zkclient</artifactId>
</dependency>

2.生产者
首先展示生产者的接口,很简单的两个方法。

public interface SampleService {

    String sayHello(String name);
    
}

生产者的实现类:

public class SampleServiceImpl implements SampleService {
    
    public String sayHello(String name) {
        return "Hello " + name;
    }

}

User类的话就是name、age、sex三个属性。

接下来就是生产者的Spring配置:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">

    <!-- 具体的实现bean -->
    <bean id="sampleService" class="top.catalinali.sample.provider.impl.SampleServiceImpl" />

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="sample-provider" />

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://192.168.71.121:2181?backup=192.168.71.122:2181,192.168.71.123:2181" />

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口  写操作可以设置retries=0 避免重复调用SOA服务 -->
    <dubbo:service retries="0" interface="top.catalinali.sample.provider.SampleService" ref="sampleService" />

</beans>

3.消费者
首先消费者需要一个跟生产一模一样的接口类

public interface SampleService {

    String sayHello(String name);

}

消费者配置

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="sample-consumer" />

    <dubbo:registry address="zookeeper://192.168.71.121:2181?backup=192.168.71.122:2181,192.168.71.123:2181" />

    <!-- 生成远程服务代理,可以像使用本地bean一样使用demoService 检查级联依赖关系 默认为true 当有依赖服务的时候,需要根据需求进行设置 -->
    <dubbo:reference id="sampleService" check="false"
        interface="top.catalinali.sample.provider.SampleService" />

</beans>

Dubbo启动

首先我们先启动生产者启动:

public class Provider {

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "sample-provider.xml" });
        context.start(); 
        System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟
    }
}

启动消费者

public class Consumer {

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "sample-consumer.xml" });
        context.start();
            
        SampleService sampleService = (SampleService) context.getBean("sampleService");
        String hello = sampleService.sayHello("tom");
        System.out.println(hello);
        
        System.in.read();
    }

}

结果
hellodubbo_2
项目结构图
hellodubbo_3

Dubbo的管控台

Dubbo管控台搭建其实很容易,我们只需要一个在linux上的tomcat跑Dubbo即可,需要的环境:

  • apache-tomcat-7.0.29.tar.gz

  • dubbo-admin-2.5.4.war

1.安装tomcat
使用tar -zxvf apache-tomcat-7.0.29.tar.gz解压tar包
2.解压dubbo的war包
使用unzip dubbo-admin-2.5.3.war -d dubbo-admin解压dubbo-admin-2.5.4.war到tomcat目录下的webapps下。如果提示无unzip命令,使用yum安装yum install -y unzip zip此命令
注意:
如果zookeeper注册中心不在此服务器上,则需要打开dubbo-admin/WEB-INF/dubbo.properties文件,将红框改注册中心的ip地址。
hellodubbo_5
3.运行tomcat
①进入tomcat下的bin目录下,执行./startup.sh脚本。
②使用tail -f ../logs/catalina.out查看日志。
hellodubbo_6
③进入http://192.168.71.121:8080/du...就可以看到管控台了(IP地址改成你的服务器ip)
hellodubbo_7
也可以看到我们刚才所运行的服务
hellodubbo_8


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/he...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 0 收藏 2 评论 0

社会李 发布了文章 · 2017-09-05

小白从头到脚搭建zookeeper集群的过程

buildzk_logo

zookeeper的字面意思为动物园管理员,正如他的名字,各个子系统能正常为用户提供统一的服务。并且还可以作为Dubbo的注册中心来使用。今天进行了一番centos的安装到zookeeper集群的搭建,也遇到不少坑。特此记录下来搭建过程。


环境准备

  • VMware Workstation 11
  • centos 6.4镜像
  • jdk-7u67-linux-x64.tar.gz
  • zookeeper-3.4.6.tar.gz
  • Xshell
  • Xftp

搭建linux环境

1.linux安装过程就不赘述了,网上有很多。可以参考这一篇。需要注意的是安装过程中我们最好配置一下网络:
buildzk_8
buildzk_9
buildzk_10
最后一步中红色方框的一样就好了,ip只需要最后一段不一样即可。另外我安装的也是minimal模式。

2.安装好centos以后我们要更改一下网络连接方式。如图:

buildzk_1

3.这样我们就安装好了一台linux,由于我们要搭建集群,所以我们再克隆2台linux:

buildzk_2

除了这一步,其他的一直下一步就好

buildzk_3

这时我们就得到了3台linux环境。可是由于是克隆的,所以后两台连ip地址都是一样的。所以我们需要更改一些配置来使得后2台也能有了自己的ip。参考这一篇

4.开启我们的三台linux环境,使用Xshell分别进行连接。

buildzk_4

至此,linux环境就搭建成功了。

搭建zookeeper集群

1.由于zookeeper是Java编写的,运行在Java环境上,所以我们要先安装jdk。具体安装过程可以看我之前写的centos7下破解安装JIRA 7.2的开头部分。
2.使用tar -zxvf 将zookeeper-3.4.6.tar.gz解压到某一个位置。
3.将zookeeper-3.4.6/conf目录下面的zoo_sample.cfg修改为zoo.cfg。
4.使用vi/vim命令修改zoo.cfg的内容如下图:

buildzk_5

其中上面的红框是zookeeper的数据日志目录,可以更改成自己的位置。下面的红框是集群中服务的列表。

5.分别操作linux进入刚才修改的数据日志目录,新建一个myid文件。内容分别是012。没有错,里面就一个数字,用来唯一标识这个服务。这个id是很重要的,一定要保证整个集群中唯一。zookeeper会根据这个id来取出server.x上的配置。比如当前id为1,则对应着zoo.cfg里的server.1的配置。
6.使用关闭service iptables stop暂时关闭防火墙,或者使用chkconfig iptables off永久禁用防火墙。然后进入zookeeper下的bin目录,使用./zkServer.sh start同时对三个linux进行操作。

buildzk_6

这时候我们再使用./zkServer.sh status来查看状态如果出现下图,恭喜你搭建成功

buildzk_7

其中leader是主节点,follow是从节点。

但是大多数情况我们却出现It is probably not running。这时可以参考这篇文章去解决问题。

随便说说

首先感谢上文参考的所有文章!!
其次感谢这个开发的网络世界,让我们可以找到想找的所有资料!!!


本文作者: catalinaLi
本文链接: http://catalinali.top/2017/bu...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 0 收藏 2 评论 0

社会李 关注了标签 · 2017-08-29

springboot

Spring Boot 项目旨在简化创建产品级的 Spring 应用和服务。你可通过它来选择不同的 Spring 平台。

关注 11843

社会李 关注了标签 · 2017-08-29

spring

Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。

关注 25283

社会李 关注了标签 · 2017-08-29

java

Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaSE, JavaEE, JavaME)的总称。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

Java编程语言的风格十分接近 C++ 语言。继承了 C++ 语言面向对象技术的核心,Java舍弃了 C++ 语言中容易引起错误的指針,改以引用取代,同时卸载原 C++ 与原来运算符重载,也卸载多重继承特性,改用接口取代,增加垃圾回收器功能。在 Java SE 1.5 版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。太阳微系统对 Java 语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。

版本历史

重要版本号版本代号发布日期
JDK 1.01996 年 1 月 23 日
JDK 1.11997 年 2 月 19 日
J2SE 1.2Playground1998 年 12 月 8 日
J2SE 1.3Kestrel2000 年 5 月 8 日
J2SE 1.4Merlin2002 年 2 月 6 日
J2SE 5.0 (1.5.0)Tiger2004 年 9 月 30 日
Java SE 6Mustang2006 年 11 月 11 日
Java SE 7Dolphin2011 年 7 月 28 日
Java SE 8JSR 3372014 年 3 月 18 日
最新发布的稳定版本:
Java Standard Edition 8 Update 11 (1.8.0_11) - (July 15, 2014)
Java Standard Edition 7 Update 65 (1.7.0_65) - (July 15, 2014)

更详细的版本更新查看 J2SE Code NamesJava version history 维基页面

新手帮助

不知道如何开始写你的第一个 Java 程序?查看 Oracle 的 Java 上手文档

在你遇到问题提问之前,可以先在站内搜索一下关键词,看是否已经存在你想提问的内容。

命名规范

Java 程序应遵循以下的 命名规则,以增加可读性,同时降低偶然误差的概率。遵循这些命名规范,可以让别人更容易理解你的代码。

  • 类型名(类,接口,枚举等)应以大写字母开始,同时大写化后续每个单词的首字母。例如:StringThreadLocaland NullPointerException。这就是著名的帕斯卡命名法。
  • 方法名 应该是驼峰式,即以小写字母开头,同时大写化后续每个单词的首字母。例如:indexOfprintStackTraceinterrupt
  • 字段名 同样是驼峰式,和方法名一样。
  • 常量表达式的名称static final 不可变对象)应该全大写,同时用下划线分隔每个单词。例如:YELLOWDO_NOTHING_ON_CLOSE。这个规范也适用于一个枚举类的值。然而,static final 引用的非不可变对象应该是驼峰式。

Hello World

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

编译并调用:

javac -d . HelloWorld.java
java -cp . HelloWorld

Java 的源代码会被编译成可被 Java 命令执行的中间形式(用于 Java 虚拟机的字节代码指令)。

可用的 IDE

学习资源

常见的问题

下面是一些 SegmentFault 上在 Java 方面经常被人问到的问题:

(待补充)

关注 104794

社会李 发布了文章 · 2017-08-29

详解jdbcTemplate和namedParameterJdbcTemplate

jdbcTemplate_logo

我们开发DAO层时用的最多的就是ORM框架(Mybatis,hibernate)了。在有些特殊的情况下,ORM框架的搭建略显笨重,这时最好的选择就是Spring中的jdbcTemplate了。本文对jdbcTemplate进行详解,并且会对具名参数namedParameterJdbcTemplate进行讲解。


jdbcTemplate讲解

jdbcTemplate提供的主要方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForXXX方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

jdbcTemplate环境搭建:

1 在spring配置文件中加上jdbcTemplate的bean:

    <!--注入jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

注意:在这之前我们需要先配置好数据库数据源dateSource。
2.在使用jdbcTemplate类中使用@Autowired进行注入

    @Autowired
    private JdbcTemplate jdbcTemplate;

jdbcTemplate方法测试:

我们准备一个数据库
jdbcTemplate_1
准备数据库对应的实体pojo,实体的名称都要对应数据库的字段名称:

public class User {

  private Long id;
  private String username;
  private String password;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  @Override
  public String toString() {
    return "User{" +
            "id=" + id +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            '}';
  }
}

1.查询单个对象queryForObject:

    @Test
    public void testQuery(){
        String sql = "select id,username,password from user where id=?";

        BeanPropertyRowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class);
        User user = jdbcTemplate.queryForObject(sql, rowMapper,1);
        System.out.println(user);
    }

输出结果: User{id=1, username='123', password='123'}
2.查询多个对象query:

    @Test
    public void testMutiQuery(){
        String sql = "select id,username,password from user";

        BeanPropertyRowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class);
        List<User> users = jdbcTemplate.query(sql, rowMapper);
        for (User user : users) {
            System.out.println(user);
        }
    }

输出结果:
User{id=1, username='123', password='123'}
User{id=2, username='1234', password='1234'}
3.查询count、avg、sum等函数返回唯一值:

    @Test
    public void testCountQuery(){
        String sql = "select count(*) from user";

        BeanPropertyRowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class);
        Integer result = jdbcTemplate.queryForObject(sql, Integer.class);
        System.out.println(result);
    }

输出结果:2
4.增删改方法测试:
新增:

    @Test
    public void testCreate(){
        String sql = "insert into user (username,password) values (?,?)";
        int create = jdbcTemplate.update(sql, new Object[]{255, 255});
        System.out.println(create);
    }

输出结果为1,去数据库查看也确实插入这条。
jdbcTemplate_2
修改:

    @Test
    public void testUpdate(){
        String sql = "update user set username=? , password=? where id=?";
        int update = jdbcTemplate.update(sql, new Object[]{256, 256,3});
        System.out.println(update);
    }

输出结果为1,并且确实数据已经修改
删除:

    @Test
    public void testDelete(){
        String sql = "delete from user where id=?";
        int delete = jdbcTemplate.update(sql, new Object[]{3});
        System.out.println(delete);
    }

5.批量操作:

    @Test
    public void testBatch(){
        List<Object[]> batchArgs=new ArrayList<Object[]>();
        batchArgs.add(new Object[]{777,888});
        batchArgs.add(new Object[]{666,888});
        batchArgs.add(new Object[]{555,888});
        String sql = "insert into user (username,password) values (?,?)";
        jdbcTemplate.batchUpdate(sql, batchArgs);
    }

以上方法基本满足了日常我们多DAO层进行的操作,不过当你进行CRUD操作时如果传入的参数不确定,这时候你可能会想起ORM框架的便利。没关系!Spring也为我们提供了这样的操作NamedParameterJdbcTemplate。

NamedParameterJdbcTemplate讲解

在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定.
在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(named parameter).
那么什么是具名参数?
具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名参数由框架类在运行时用占位符取代
具名参数只在 NamedParameterJdbcTemplate 中得到支持。NamedParameterJdbcTemplate可以使用全部jdbcTemplate方法,除此之外,我们来看看使用它的具名参数案例:
具名新增:

    @Test
    public void testNamedParameter(){
        String sql = "insert into user (username,password) values (:username,:password)";
        User u = new User();
        u.setUsername("555");
        SqlParameterSource sqlParameterSource=new BeanPropertySqlParameterSource(u);
        namedParameterJdbcTemplate.update(sql,sqlParameterSource);
    }

我们来看看结果
jdbcTemplate_3
这样我们就可以根据pojo类的属性值使用JDBC来操作数据库了。
获取新增的主键:
NamedParameterJdbcTemplate还新增了KeyHolder类,使用它我们可以获得主键,类似Mybatis中的useGeneratedKeys。

   @Test
    public void testKeyHolder(){
        String sql = "insert into user (username,password) values (:username,:password)";
        User u = new User();
        u.setUsername("555");
        SqlParameterSource sqlParameterSource=new BeanPropertySqlParameterSource(u);
        KeyHolder keyHolder = new GeneratedKeyHolder();
        namedParameterJdbcTemplate.update(sql, sqlParameterSource, keyHolder);
        int k = keyHolder.getKey().intValue();
        System.out.println(k);
    }

输出结果就是新增的主键。

参考资料

本文作者: catalinaLi
本文链接: http://catalinali.top/2017/us...
版权声明: 原创文章,有问题请评论中留言。非商业转载请注明作者及出处。

查看原文

赞 5 收藏 3 评论 0