Nginx配置使用入门

Nginx作为当今数一数二的负载均衡服务器,应用十分广泛,今天记录一下,大名鼎鼎的Nginx的配置信息 一个简单的负载均衡的示例,把www.domain.com均衡到本机不同的端口,也可以改为均衡到不同的地址上。 http { upstream myproject { server 127.0.0.1:8000 weight=3; server 127.0.0.1:8001; server 127.0.0.1:8002; server 127.0.0.1:8003; } server { listen 80; server_name www.domain.com; location / { proxy_pass http://myproject; } } } weight就是权重,数值越大,分配到这个服务器的概率就越大,以本例来说,分配8000上的概率为二分之一,其他的三个均为为六分之一,另外需要注意的是:proxy_pass和upstream一定要一样 注:这么配置仅仅是解决了负载均衡的问题,但是没有解决session共享的问题,为了解决session共享我们有两个方案: 配置粘连,也就是说,只要某一个请求被分配到该服务器,那么今后的该客端的所有请求全都分配到该服务器上; 在代码中解决session共享问题 目前针对这两种方案,我都不是很熟悉,我将来会写一篇文章来解决这个问题 静态资源处理 location ~ .(jpg|png|jpeg|bmp|gif|swf|css|js)$ { expires 30d; root /nginx-1.8.0;#root break; } 就是说上面的这些静态资源文件都是相对于:/nginx-1.8.0的,所以如果我们代码中写的路径是img/bridgeli.png,那么我们就需要在nginx-1.8.0建一个img目录,把我们bridgeli.png放在里面。 完整示例 #!nginx \# 使用的用户和组 user www www; \# 指定工作衍生进程数 worker_processes 2; \# 指定 pid 存放的路径 pid /var/run/nginx.pid; \# [ debug | info | notice | warn | error | crit ] \# 可以在下方直接使用 [ debug | info | notice | warn | error | crit ] 参数 error_log /var/log/nginx.error_log info; events { \# 允许的连接数 connections 2000; \# use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ; \# 具体内容查看 http://wiki.codemongers.com/事件模型 use kqueue; } http { include conf/mime.types; default_type application/octet-stream; log_format main ‘$remote_addr – $remote_user [$time_local] ‘ ‘"$request" $status $bytes_sent ‘ ‘"$http_referer" "$http_user_agent" ‘ ‘"$gzip_ratio"’; log_format download ‘$remote_addr – $remote_user [$time_local] ‘ ‘"$request" $status $bytes_sent ‘ ‘"$http_referer" "$http_user_agent" ‘ ‘"$http_range" "$sent_http_content_range"’; client_header_timeout 3m; client_body_timeout 3m; send_timeout 3m; client_header_buffer_size 1k; large_client_header_buffers 4 4k; gzip on; gzip_min_length 1100; gzip_buffers 4 8k; gzip_types text/plain; output_buffers 1 32k; postpone_output 1460; sendfile on; tcp_nopush on; tcp_nodelay on; send_lowat 12000; keepalive_timeout 75 20; #lingering_time 30; #lingering_timeout 10; #reset_timedout_connection on; server { listen one.example.com; server_name one.example.com www.one.example.com; access_log /var/log/nginx.access_log main; location / { proxy_pass http://127.0.0.1/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; client_body_temp_path /var/nginx/client_body_temp; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_send_lowat 12000; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; proxy_temp_path /var/nginx/proxy_temp; charset UTF-8; } error_page 404 /404.html; location /404.html { root /spool/www; charset on; source_charset UTF-8; } location /old_stuff/ { rewrite ^/old_stuff/(.*)$ /new_stuff/$1 permanent; } location /download/ { valid_referers none blocked server_names *.example.com; if ($invalid_referer) { #rewrite ^/ http://www.example.com/; return 403; } #rewrite_log on; \# rewrite /download/\*/mp3/\*.any_ext to /download/\*/mp3/\*.mp3 rewrite ^/(download/.\*)/mp3/(.\*)..*$ /$1/mp3/$2.mp3 break; root /spool/www; #autoindex on; access_log /var/log/nginx-download.access_log download; } location ~* ^.+.(jpg|jpeg|gif)$ { root /spool/www; access_log off; expires 30d; } } } 这是Nginx官方网站的一个例子,说实话里面的很多配置我也不是很清楚,但很多并不是非常难以理解 ...

May 17, 2015 · 3 min · 471 words · Bridge Li

ANT(build)脚本模板示例

近来虽然Maven构建的项目越来越盛行,但是依然还有很多遗留(暂且称之为遗留吧)项目依然是由ANT编译的,今天老夫就整理一下自己目前公司项目用到的ANT模板,既作为老夫的学习笔记,以供将来查看,也分享出来供需要的参考,因为比较简单易懂,就不多说了,直接上代码 <?xml version="1.0" encoding="UTF-8"?> <!&#8211; Ant工程build模板 ant build file Example: ant -Dprofile=dev deploy test IDC测试环境 dev 本地开发环境 (default) &#8211;> <project name="antProject" basedir="." default="prompt"> <property name="javac.version" value="1.6" /> <property name="project.name" value="projectname" /> <property name="source.encoding" value="UTF-8" /> <property name="deploy.dir" value="/tmp/${project.name}" /> <!&#8211; project var set &#8211;> <property name="target.path" value="build" /> <property name="target.root.path" value="${target.path}/ROOT" /> <property name="target.root.classes" value="${target.root.path}/WEB-INF/classes" /> <property name="webroot.path" value="WebRoot" /> <property name="compileSrc" value="src" /> <property name="compileDest" value="${target.root.classes}" /> <property name="env.dir" value="env" /> <property name="env.cfg" value="${env.dir}/${profile}" /> <tstamp> <format property="now" pattern="yyyyMMddHHmmss" /> </tstamp> <path id="compileClassPath"> <fileset dir="${webroot.path}/WEB-INF/lib"> <include name="*.jar" /> </fileset> </path> <target name="prompt" description="show prompt information"> <echo>Please choose task: clean, compile, war, deploy. ${line.separator} Example: ${line.separator} ant compile ${line.separator} ant -Dprofile=test deploy </echo> </target> <target name="clean"> <delete dir="${target.path}" /> <mkdir dir="${target.path}" /> <delete dir="${compileDest}" /> <mkdir dir="${compileDest}" /> <delete dir="${target.root.classes}" /> <mkdir dir="${target.root.classes}" /> <echo>cleaned for ${compileDest}, ${target.root.path},${target.path}/*.war</echo> </target> <target name="compile" depends="clean,testIfProfileSet"> <echo>starting compile the source from ${compileSrc}</echo> <javac srcdir="${compileSrc}" includeantruntime="false" fork="true" memoryinitialsize="256m" memorymaximumsize="512m" destdir="${compileDest}" classpathref="compileClassPath" encoding="${source.encoding}" source="${javac.version}" target="${javac.version}" debug="true" verbose="false" optimize="true" deprecation="false"> </javac> <copy todir="${compileDest}"> <fileset dir="${compileSrc}" excludes="*\*/\*.svn,*\*/\*.java" /> </copy> <echo>compiled classes copied to ${compileDest}</echo> <copy todir="${target.root.path}"> <fileset dir="${webroot.path}" excludes="*\*/\*.svn,*\*/\*.java" /> </copy> <echo>copied to ${webroot.path} to ${compileDest}</echo> <echo>compile finished</echo> </target> <target name="testIfProfileSet"> <echo>ant param profile: ${profile}</echo> <condition property="isProfileSet"> <!&#8211; <isset property="${profile}" /> &#8211;> <or> <equals arg1="${profile}" arg2="dev" /> <equals arg1="${profile}" arg2="test" /> </or> </condition> <antcall target="profileProvided"> </antcall> <antcall target="noProfile"> </antcall> </target> <target name="profileProvided" if="isProfileSet"> <copy todir="${target.root.classes}"> <fileset dir="${env.cfg}" /> </copy> <echo>copied config files ${env.cfg} to ${target.root.classes}</echo> </target> <target name="noProfile" if="isProfileSet"> <echo>ant param profile is none, use default config files</echo> </target> <target name="war" depends="compile"> <jar jarfile="${target.path}/${project.name}-${profile}${now}.war"> <fileset dir="${target.root.path}"> <include name="*\*/\*" /> <exclude name="*\*/\*.fla" /> <exclude name="*\*/\*.mp3" /> <exclude name="*\*/\*.as" /> <exclude name="*\*/\*.bak" /> <exclude name="*\*/\*.swd" /> <exclude name="*\*/\*.db" /> </fileset> </jar> </target> <target name="deploy" depends="compile"> <delete dir="${deploy.dir}" /> <mkdir dir="${deploy.dir}" /> <copy todir="${deploy.dir}"> <fileset dir="${target.root.path}"> </fileset> </copy> <echo>deploy ${target.root.path} to ${deploy.dir}</echo> </target> </project>

May 10, 2015 · 2 min · 303 words · Bridge Li

Spring加Mybatis实现MySQL数据库主从读写分离

上周在一个同事的指点下,实现了Spring加Mybatis实现了MySQL的主从读写分离,今天记一下笔记,以供自己今后参考,下面是配置文件的写法。 数据源也就是jdbc.properties,因为是主从读写分离,那么肯定有两个数据源了 jdbc.driver=org.mariadb.jdbc.Driver \# 从库,只读 slave.jdbc.url=jdbc:mariadb://xxx.xxx.xxx.xxx:3306/xxx?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&noAccessToProcedureBodies=true&autoReconnect=true slave.jdbc.username=xxx slave.jdbc.password=xxx \# 主库,需要写 master.jdbc.url=jdbc:mariadb://xxx.xxx.xxx.xxx:3306/xxx?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&noAccessToProcedureBodies=true&autoReconnect=true master.jdbc.username=xxx master.jdbc.password=xxx 这个非常简单和普通的区别不是很大,另外数据库的驱动是:mariadb,动下面就是第二个配置文件spring.xml spring.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!&#8211; Import properties file &#8211;> <context:property-placeholder location="classpath:jdbc.properties" /> <!&#8211; Auto Scan &#8211;> <context:component-scan base-package="cn.bridgeli.demo" /> </beans> 这个文件很简单,有两个作用,①. 引入数据源配置文件;②. spring扫描的文件的路径 spring-mybatis.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <bean id="slaveDataSourceImpl" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${slave.jdbc.url}" /> <property name="username" value="${slave.jdbc.username}" /> <property name="password" value="${slave.jdbc.password}" /> <!&#8211; 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 &#8211;> <property name="idleConnectionTestPeriodInMinutes" value="10" /> <!&#8211; 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 &#8211;> <property name="idleMaxAgeInMinutes" value="10" /> <!&#8211; 每个分区最大的连接数 &#8211;> <property name="maxConnectionsPerPartition" value="20" /> <!&#8211; 每个分区最小的连接数 &#8211;> <property name="minConnectionsPerPartition" value="10" /> <!&#8211; 分区数 ,默认值2,最小1,推荐3-4,视应用而定 &#8211;> <property name="partitionCount" value="3" /> <!&#8211; 每次去拿数据库连接的时候一次性要拿几个,默认值:2 &#8211;> <property name="acquireIncrement" value="3" /> <!&#8211; 缓存prepared statements的大小,默认值:0 &#8211;> <property name="statementsCacheSize" value="50" /> <!&#8211; 在做keep-alive的时候的SQL语句 &#8211;> <property name="connectionTestStatement" value="select 1 from dual" /> <!&#8211; 在每次到数据库取连接的时候执行的SQL语句,只执行一次 &#8211;> <property name="initSQL" value="select 1 from dual" /> <property name="closeConnectionWatch" value="false" /> <property name="logStatementsEnabled" value="true" /> <property name="transactionRecoveryEnabled" value="true" /> </bean> <bean id="masterDataSourceImpl" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${master.jdbc.url}" /> <property name="username" value="${master.jdbc.username}" /> <property name="password" value="${master.jdbc.password}" /> <!&#8211; 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 &#8211;> <property name="idleConnectionTestPeriodInMinutes" value="10" /> <!&#8211; 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 &#8211;> <property name="idleMaxAgeInMinutes" value="10" /> <!&#8211; 每个分区最大的连接数 &#8211;> <property name="maxConnectionsPerPartition" value="20" /> <!&#8211; 每个分区最小的连接数 &#8211;> <property name="minConnectionsPerPartition" value="10" /> <!&#8211; 分区数 ,默认值2,最小1,推荐3-4,视应用而定 &#8211;> <property name="partitionCount" value="3" /> <!&#8211; 每次去拿数据库连接的时候一次性要拿几个,默认值:2 &#8211;> <property name="acquireIncrement" value="3" /> <!&#8211; 缓存prepared statements的大小,默认值:0 &#8211;> <property name="statementsCacheSize" value="50" /> <!&#8211; 在做keep-alive的时候的SQL语句 &#8211;> <property name="connectionTestStatement" value="select 1 from dual" /> <!&#8211; 在每次到数据库取连接的时候执行的SQL语句,只执行一次 &#8211;> <property name="initSQL" value="select 1 from dual" /> <property name="closeConnectionWatch" value="false" /> <property name="logStatementsEnabled" value="true" /> <property name="transactionRecoveryEnabled" value="true" /> </bean> <!&#8211; DataSource/Master &#8211;> <bean id="masterDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <property name="targetDataSource" ref="masterDataSourceImpl" /> </bean> <bean id="masterTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="masterDataSource" /> </bean> <bean id="masterTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="masterTransactionManager" /> </bean> <!&#8211; DataSource/Slave &#8211;> <bean id="slaveDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <property name="targetDataSource" ref="slaveDataSourceImpl" /> </bean> <bean id="slaveTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="slaveDataSource" /> </bean> <bean id="slaveTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="slaveTransactionManager" /> </bean> <!&#8211; Mybatis/Master &#8211;> <bean id="masterSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="masterDataSource"></property> <property name="configLocation" value="classpath:mybatis.xml" /> <property name="typeAliasesPackage" value="cn.bridgeli.demo.entity" /> <property name="mapperLocations"> <list> <value>classpath:cn/bridgeli/demo/mapper/master/*.xml</value> </list> </property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.bridgeli.demo.mapper.master" /> <property name="sqlSessionFactoryBeanName" value="masterSqlSessionFactory" /> </bean> <!&#8211; Mybatis/Slave &#8211;> <bean id="slaveSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="slaveDataSource"></property> <property name="configLocation" value="classpath:mybatis.xml" /> <property name="typeAliasesPackage" value="cn.bridgeli.demo.entity" /> <property name="mapperLocations"> <list> <value>classpath:cn/bridgeli/demo/mapper/slave/*.xml</value> </list> </property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.bridgeli.demo.mapper.slave" /> <property name="sqlSessionFactoryBeanName" value="slaveSqlSessionFactory" /> </bean> <!&#8211; Configuration transaction advice &#8211;> <tx:advice id="txAdvice" transaction-manager="masterTransactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="get*" read-only="true" propagation="SUPPORTS" /> <tx:method name="list*" read-only="true" propagation="SUPPORTS" /> </tx:attributes> </tx:advice> <!&#8211; Configuration transaction aspect &#8211;> <aop:config> <aop:pointcut id="systemServicePointcut" expression="execution(\* cn.bridgeli.demo.service.\*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="systemServicePointcut" /> </aop:config> </beans> 这个配置文件老夫是完整的copy了下来,看起来也比较易懂,就不做解释了,需要说明的mybatis下那些dao的接口,分别对应cn.bridgeli.demo.mapper.master、cn.bridgeli.demo.mapper.slave,cn.bridgeli.demo.mapper.master下的这些dao接口是要写的,另一个是读的,这些接口对应的配置文件肯定就是他们对应的文件夹下面的xml文件了,在将来的项目中几乎可以照抄 ...

May 3, 2015 · 3 min · 502 words · Bridge Li

MyBatis下最好的分页实现:mybatis-paginator使用入门

前两天写一个项目,发现在MyBatis下一个最好的分页实现类库mybatis-paginator,今天就写一篇其入门教程供大家参考。 先引入maven依赖 <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>1.2.15</version> </dependency> 从这个依赖中,我们可以看到 1 他是mybatis的一个插件,2 其开源在GitHub上,感兴趣的可以去GitHub上搜源码看看,既然是mybatis的插件,下一步肯定就是和mybatis的集成了. 和mybatis集成 ①. 新建一个mybatis.xml的配置文件,其内容如下: <?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> <settings> <setting name="cacheEnabled" value="true" /> <setting name="lazyLoadingEnabled" value="true" /> </settings> <plugins> <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor"> <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect" /> <property name="asyncTotalCount" value="true" /> </plugin> </plugins> </configuration> ②. 和spring集成,即在spring-mybatis.xml中引入该文件 &#8230;&#8230; <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:mybatis.xml" /> <property name="typeAliasesPackage" value="cn.bridgeli.demo.entity" /> <property name="mapperLocations" value="classpath:cn/bridgeli/demo/mapper/*.xml" /> </bean> &#8230;&#8230; 因为这个文件太长,就不贴全文了,仅把位置这一块贴出来,当我们把这些配置工作做好之后,下一步就是如何使用了。 ...

April 26, 2015 · 2 min · 219 words · Bridge Li

Shell编程入门

一、Shell入门 我们先看一个小例子,永恒的经典:Hello World #!/bin/sh var="Hello World!" echo $var 保存,文件名为:hello 我们发现文件的第一行虽是一个注释,但是说明了文件的执行是由/bin/sh来执行,所以我们这么来执行这个文件: /bin/sh hello 就可以看到结果了,但我们知道在Linux下,一个文件是否可以执行是由文件属性来决定的,那么我们是否可以给他加上可执行权限,来执行这个文件呢? 先执行如下命令: chmod u+x hello 然后我们在直接敲命令:hello,看到什么现象? 所以一个文件被执行有这两个途径 二、Shell语法入门 输入/输出内部命令 ①. echo 输出命令 ②. read 输入命令 例如: #!/bin/sh echo Name: read NAME echo Phone: read PHONE echo SNAME,SPHONE > contact.txt if条件语句 在看if条件语句之前,我们先看一下:测试命令执行结果,在Linux下正确的命令执行结果为0,否则为其他值,我们可以用: echo $? 来看上一个命令的执行结果,懂了这些之后,我们在看那些常见语法 if 条件测试命令串 then 条件为真时执行的命令 else 条件为假时执行的命令 fi 注:if和then必须是两行,如果放一行,请在then前加“;” 例如: #!/bin/sh echo Input file name: read NAME if [ -d $NAME ] then echo Dir else echo Not Dir fi case条件语句 case 条件测试命令串 in 表达式1) 分支1执行的命令 ;; 表达式2) 分支2执行的命令 ;; *) 其他命令 ;; esac 例如: ...

April 19, 2015 · 2 min · 283 words · Bridge Li

Maven项目如何生成测试报告

刚工作的时候,当时公司对代码质量要求比较高,每一个人的代码都要写junit,而且要生成测试报告,项目经理要看行覆盖率和分支覆盖率,记得当时的项目是用ant编译的,生成测试报告那个复杂啊,不会写,现在用了maven,发现这在maven下根本不是事,只需要在pom.xml中配置一个插件即可,废话不多说,直接上代码: <build> <finalName>Demo</finalName> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>2.5.2</version> <configuration> <encoding>UTF-8</encoding> <formats> <format>html</format> <format>xml</format> </formats> </configuration> </plugin> </plugins> </build> 然后打开cmd切到pom.xml所在文件夹,运行命令: mvn cobertura:cobertura 即可,然后我们打开{project}targetsitecoberuraindex.html就可以看到测试报告了,这个测试报告里面不仅有行覆盖率还有分支覆盖率,例如: 相信不用我解释,看这篇文章的人一定能看懂是什么意思。 下面是一些cobertura插件的常用命令 mvn cobertura:help 查看cobertura插件的帮助 mvn cobertura:clean 清空cobertura插件运行结果 mvn cobertura:check 运行cobertura的检查任务 mvn cobertura:cobertura 运行cobertura的检查任务并生成报表,报表生成在target/site/cobertura目录下 cobertura:dump-datafile Cobertura Datafile Dump Mojo mvn cobertura:instrument Instrument the compiled classes 至于有什么效果,请大家自己写一个例子,跑一下就可以了。 最后多说一点,关于maven的插件其实非常多,用法也相对都比较简单,网上的资料也比较多,今天这篇文章算是抛砖引玉,所以推荐大家今后尽量用maven编译项目

April 12, 2015 · 1 min · 49 words · Bridge Li

正则表达式入门

今天讲讲正则表达式,正则表达式在编程中是非常常用的一项技术,也是非常行之有效的技术,有了他,很多复杂的问题就变得的非常简单了,常见的用途有:字符串匹配(或者叫字符匹配)、字符串查找、字符串替换,典型应用有:用户注册时用户名和密码的验证、检测IP地址是否正确,从网页中揪出链接等等,从常见用途中我们看到,一言以蔽之,正则表达式就是对字符串的处理,所以正则表达式牵涉到的类有三个:java.lang.String、java.util.regex.Pattern、java.util.regex.Matcher,其实正则的用途和功能非常强大,今天老夫就写一些最基本的用法,其实那些高级用法也是从这些基本用法来的,今后看看有没有机会写一下高级用法(主要是老夫现在也不会,,,),下面我们来看看这些最基本的语法: 字符类 [abc] a、b 或 c(简单类) [^abc] 任何字符,除了 a、b 或 c(否定) [a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围) [a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集) [a-z&&[def]] d、e 或 f(交集) [a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去) [a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去) 预定义字符类 . 任何字符(与行结束符可能匹配也可能不匹配) d 数字:[0-9] D 非数字: [^0-9] s 空白字符:[ tnx0Bfr] S 非空白字符:[^s] w 单词字符:[a-zA-Z_0-9] W 非单词字符:[^w] 边界匹配器 ^ 行的开头 $ 行的结尾 b 单词边界 B 非单词边界 A 输入的开头 G 上一个匹配的结尾 Z 输入的结尾,仅用于最后的结束符(如果有的话) z 输入的结尾 Greedy 数量词 X? X,一次或一次也没有 X* X,零次或多次 X+ X,一次或多次 X{n} X,恰好 n 次 X{n,} X,至少 n 次 X{n,m} X,至少 n 次,但是不超过 m 次 反斜线、转义和引用 反斜线字符 (&#8221;) 用于引用转义构造,如上表所定义的,同时还用于引用其他将被解释为非转义构造的字符。因此,表达式 \ 与单个反斜线匹配,而 { 与左括号匹配。 在不表示转义构造的任何字母字符前使用反斜线都是错误的;它们是为将来扩展正则表达式语言保留的。可以在非字母字符前使用反斜线,不管该字符是否非转义构造的一部分。 根据 Java Language Specification 的要求,Java 源代码的字符串中的反斜线被解释为 Unicode 转义或其他字符转义。因此必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被 Java 字节码编译器解释。例如,当解释为正则表达式时,字符串字面值 "b" 与单个退格字符匹配,而 "\b" 与单词边界匹配。字符串字面值 "(hello)" 是非法的,将导致编译时错误;要与字符串 (hello) 匹配,必须使用字符串字面值 "\(hello\)"。 其实正则表达式的用法说说难不难,但说简单一点也不简单,下面是一个例子对以上的这些语法进行测试,当我们想不起来的时候,可以把这些例子拷出来跑一下,看一下效果就知道了 ...

April 6, 2015 · 2 min · 416 words · Bridge Li

JAVA 性能调优

学习Java性能调优之前,我们必须得先了解Java中的内存分配:堆、栈、非堆 为了更好的说明这个问题,我们先看一个程序: package cn.bridgeli.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class Test { public void test() { List<Email> emails = new ArrayList<Email>(); Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName(""); String url = ""; conn = DriverManager.getConnection(url, "", ""); pstmt = conn.prepareStatement(""); rs = pstmt.executeQuery(); Email email = null; while (rs.next()) { email = new Email(); email.setSubject(""); emails.add(email); } } catch (Exception e) { e.printStackTrace(); } finally { // close conn } } } 在这段代码中,那些哪些数据放在堆上,哪些数据放在栈上,又有哪些数据放在方法去呢?一言以蔽之:在方法中,“=”左边的值,全部放在栈上,占4个字节,而“=”右边的肯定就是放在堆上了,所以该段代码中像:emails、conn的变量都是放在栈上的,而我们 new 出来的全部放在了堆上,而方法区是没有放东西的,既然new 出来的Email是放在堆上的,那么Email中的这些变量又是放在哪呢? ...

March 29, 2015 · 2 min · 320 words · Bridge Li

世界最大同性交友网站(GitHub)入门使用秘籍

作为一个程序猿,你一定听说过世界最大的同性交友网站:GitHub,但对于其怎么使用,可能会有一点陌生,今天老夫就把自己平时积累的一点经验记录一下,同时分享给大家,需要说明的是,老夫对于很多操作也不甚了了,希望高手能多多留言交流。要想在世界上最大的同性交友网站上畅游,第一步当然是注册啦,但怎么注册老夫就不说了,和其他的注册没有什么差别,下面我们就从Git的客户端下载、安装和配置说起。 一、Git客户端的下载与安装 Windows安装msysgit 选择Git-1.x.x.x-xxxx.exe Linux安装sudo apt-get install git 安装完成之后,桌面上会有一个“Git Bash”的快捷方式,双击打开,我们一下的操作,将主要在这里完成 二、Git客户端的配置 配置用户名 git config &#8211;global user.name username 配置邮箱 git config &#8211;global user.email email SSH Key配置 我们可以通过两种协议在这个世界上最大的同性交友网站里畅游,但我们一般都是通过SSH协议,所以我们下面要配置SSH Key,在配置SSH Key之前,我们可以先敲一下下面这个命令: ssh -T git@github.com 这个命令一方面可以测试我们与这个世界上最大的同性交友网站的通信是否顺畅,另外如果显示出了你在Githu上的用户名,则表示已经配置过了,不需要再生成SSH Key了; 如果没有配置过,那好下面我们就要生成SSH Key了,生成SSH Key的命令: ssh-keygen 使用该命令,一路Enter下去,就会在C:UsersAdministrator.ssh目录下,生成一对SSH key,生成SSH key之后就需要我们将公钥添加到Github上了,方法: 打开C:UsersAdministrator.ssh目录,使用Notepad++等现代文本编辑器(记事本就算了,而且还可能遇到问题)打开id_rsa.pub文件,将里面的内容全部拷贝下来,然后打开Github,打开个人设置页面,选中“SSH Key”选项,点击“Add SSH Key”按钮,然后在新新出现的表单中,填入标题,再将刚刚复制下来的内容,粘贴到“Key”栏,然后点击“Add Key”按钮,完成添加,此时我们可以再次敲一下: ssh -T git@github.com 测试是否配置成功,如果成功了,那么我们就真的可以再这个世界上最大的同性交友网站上畅游了 三、把本地项目放到GitHub上 既然是把本地项目放到GitHub上,那么我们先在Git上建一个仓库,例如:Demo,然后我们在本地的项目,也就是Demo下执行以下命令: git init git add README.md git commit -m "first commit" git remote add origin git@github.com:bridgeli/Demo.git git push -u origin master 如果是我们一个人在玩的话,当我们在做出一些修改之后,以后的操作就可以直接: git add README.md git commit -m "first commit" git push -u origin master 其中 add 后面跟的是文件名,如果提交所有也可以使用命令: ...

March 22, 2015 · 1 min · 211 words · Bridge Li

微信JS SDK Demo(Java版)

前几天在公司开发一个功能:微信分享,要求是分享的不是用户当前看到的这个页面,大家知道这在以前其实很简单的,但去年的最后一天,微信大力打击诱导分享、关注之后,以前的分享就不能用了,好在后来微信开放了JS SDK接口,可以满足这个需求,由于网上的例子写的都很简单,而且大多都是php,今天老夫就记录一下自己用Java如何实现的这个功能,窃以为比网上的很多Demo更具有实用性,大家在使用中如果有什么疑问,欢迎留言交流。废话到此为止,下面看看如何实现,当然了首先肯定要参考微信的文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html,其实这个文档上面说的已经比较详细了,但是距离真正使用当然还是有一定的距离的,在说老夫的代码之前,再多说一句,想调用微信的JS SDK,请确保你有一个经过微信认证的服务号,否则你是调用不了的,好,下面就看代码了: $(&#8216;.share&#8217;).tap(function(){ var urlCurrery = window.location.href.split(&#8216;#&#8217;)[0]; $.ajax({ type : "post", url : &#8216;share.do&#8217;, data : {&#8216;urlCurrery&#8217;:urlCurrery}, success : function(data) { var dataObj = eval(data)[0]; var url =dataObj.url; var jsapi_ticket =dataObj.jsapi_ticket; var nonce_str =dataObj.nonceStr; var timestamp =dataObj.timestamp; var signature =dataObj.signature; wx.config({ debug: true, appId: appId;, timestamp: timestamp, nonceStr: nonce_str, signature: signature, jsApiList: [ &#8216;checkJsApi&#8217;, &#8216;onMenuShareTimeline&#8217;, &#8216;onMenuShareAppMessage&#8217; ] }); wx.ready(function () { wx.onMenuShareAppMessage({ title: &#8216;分享测试&#8217;, desc: &#8216;分享测试&#8217;, link: &#8216;https://bridgeli.cn&#8217;, imgUrl: &#8221;, success: function (res) { alert(&#8216;已分享&#8217;); } }); wx.onMenuShareTimeline({ title: &#8216;分享测试&#8217;, link: &#8216;https://bridgeli.cn&#8217;, imgUrl: &#8221;, success: function (res) { alert(&#8216;已分享&#8217;); } }); alert(&#8216;已注册获取“发送给朋友”状态事件&#8217;); alert(&#8216;已注册获取“分享到朋友圈”状态事件&#8217;); }); } }); }); 经过分析微信的文档我们知道:如果想使用分享功能,那么请给分享注册事件,所以我们这里给文本中一个class为:share 的dom,绑定了分享事件,也就是说,我们想改变分享url,必须先点击一下该button,否则是不行的;另外通过文档里面的常见错误,我们可以知道,参与签名的url必须是动态获取的,如果不是,请通过ajax传到后台,为了强调这一点,微信专门用红色标注了,所以老夫在给class为share的button绑定事件的同时,将当前页面的 url (文中用:urlCurrery表示的)通用ajax传到后台 share.do 参与签名,我们一会再说后台怎么实现,接着分析前台代码,在经过后台签名之后,后台会传给前台一些数据,封装在data里面,这些就是我们需要的数据,相信通过微信的文档,所有人都能看得明白,就不多做解释了,在 wx.ready()方法里,老夫举了两个例子分别是分享给朋友和分享到朋友圈,其中的参数 link 就是你要分享的 url ,这一点很重要,这样就实现了我们分析的不是当前页面的 url 的需求,好了前台的说完了,下面就要看后台是怎么实现的了,这个其实很简单 ...

March 15, 2015 · 2 min · 350 words · Bridge Li