lightquant.com


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

  • 搜索

redis

发表于 2017-12-30 | 分类于 redis

安装、启动

安装

  1. 源码
    1 安装步骤
    第一步:安装gcc编译环境
    yum install gcc-c++
    第二步:把redis的源码上传到linux服务器。
    第三步:解压缩。
    tar -zxvf redis-3.0.0.tar.gz
    第四步:make
    第五步:make install PREFIX=/usr/local/redis

  2. yum 安装
    yum install redis -y

启动

启动redis
两种启动方式,前端启动、后台启动。
前端启动:./redis-server
后台启动:
1、复制redis.conf到redis的安装目录
2、修改redis.conf。修改daemonize yes
3、[root@bogon redis]# ./redis-server redis.conf

centos: service redis start/stop/restart
客户端
redis-cli -p 端口 -h ip地址 <-c>连接集群时使用此参数
默认端口:6379
Ip:localhost(127.0.0.1)

常用命令

1 PING 命令,该命令用于检测 redis 服务是否启动。

2 $ redis-cli -h host -p port -a password
在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。

3 设值:set key value
取值:get key
删除:del key

4 DUMP key
DUMP 命令用于序列化给定 key ,并返回被序列化的值。

5 exists key
EXISTS 命令用于检查给定 key 是否存在。

6 expire key 60
为 key 设置过期时间

7 expireat key 1293840000
Redis Expireat 命令用于以 UNIX 时间戳(unix timestamp)格式设置 key 的过期时间。key 过期后将不再可用。

8 pexpireat key 1555555555005
PEXPIREAT 命令用于设置 key 的过期时间,以毫秒计。key 过期后将不再可用。

9 keys s*
Keys 命令用于查找所有符合给定模式 pattern 的 key 。。

10 select 1 (数据库编号)
切换数据库

11 move key 1
MOVE 命令用于将当前数据库的 key 移动到给定的数据库 1 当中。

12 ttl key
TTL 命令以秒为单位返回 key 的剩余过期时间。

13 persist key
PERSIST 命令用于移除给定 key 的过期时间,使得 key 永不过期。

14 pttl key
Pttl 命令以毫秒为单位返回 key 的剩余过期时间。

15 randomkey
RANDOMKEY 命令从当前数据库中随机返回一个 key 。

16 flushdb
删除当前数据库所有 key

17 rename key newkey
Rename 命令用于修改 key 的名称 。(newkey 已存在时, RENAME 会覆盖旧 newkey)

18 renamenx key newkey
Renamenx 命令用于在新的 key 不存在时修改 key 的名称 。

19 type key
Type 命令用于返回 key 所储存的值的类型。

字符串处理:
1 getrange key start end
Getrange 命令用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
0 -1 表示获取所有

2 getset key “value”
Getset 命令用于设置指定 key 的新值,并返回 key 旧的值。

3 setbit key offset o/get bit key offset

4 mget key1 key2 …
Mget 命令返回所有(一个或多个)给定 key 的值。 没有返回空

5 setex key 30 “value”
Setex 命令为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。

6 setnx key “value”
Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。

7 setrange key 5 “value”
Setrange 命令用指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始。

8 strlen key
Strlen 命令用于获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。

9 mset key1 “va1” key2 “va2”
Mset 命令用于同时设置一个或多个 key-value 对。

10 msetnx key1 “va1” key2 “va2”
Msetnx 命令用于所有给定 key 都不存在时,同时设置一个或多个 key-value 对。

11 psetex key 1000 “value”
Psetex 命令以毫秒为单位设置 key 的生存时间。

12 incr key
Incr 命令将 key 中储存的数字值增一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

13 incrby key 30
Incrby 命令将 key 中储存的数字加上指定的增量值。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。

14 incrybyfloat key 1.2
Incrbyfloat 命令为 key 中所储存的值加上指定的浮点数增量值。

15 decr key
Decr 命令将 key 中储存的数字值减一。

16 decrby key 20
Decrby 命令将 key 所储存的值减去指定的减量值。

17 append key “value”
Append 命令用于为指定的 key 追加值。

redis.conf 配置项说明

1.Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize no
2.当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
3.指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4.绑定的主机地址
bind 127.0.0.1
5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300
6.指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
loglevel verbose
7.日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
8.设置数据库的数量,默认数据库为0,可以使用SELECT命令在连接上指定数据库id
databases 16
9.指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
save
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
10.指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
11.指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
12.指定本地数据库存放目录
dir ./
13.设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof
14.当master服务设置了密码保护时,slav服务连接master的密码
masterauth
15.设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭
requirepass foobared
16.设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxclients 128
17.指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory
18.指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
19.指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
20.指定更新日志条件,共有3个可选值:
no:表示等操作系统进行数据缓存同步到磁盘(快)
always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
21.指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
vm-enabled no
22.虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
23.将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0
24.Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
vm-page-size 32
25.设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728
26.设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
27.设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
28.指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
29.指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
activerehashing yes
30.指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
include /path/to/local.conf

查看
CONFIG GET CONFIG_SETTING_NAME
例如:CONFIG GET loglevel
查看所有:config get *

修改
CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
例如:CONFIG SET loglevel “notice”

高级操作

数据备份与恢复
1 save
备份

2 config get dir
获取 redis 安装目录

恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。

3 bgsave
后台执行 备份

安全
1 config get requirepass
查看密码(默认密码为空)

2 config set requirepass “password”
设置密码

3 auth password
Auth 命令用于检测给定的密码和配置文件中的密码是否相符。

4 ping
查看服务是否运行

reids 性能测试
1 redis-benchmark [option] [option value]
-h 指定服务器主机名 127.0.0.1
-p 指定服务器端口 6379
-s 指定服务器 socket
-c 指定并发连接数 50
-n 指定请求数 10000
-d 以字节的形式指定 SET/GET 值的数据大小 2
-k 1=keep alive 0=reconnect 1
-r SET/GET/INCR 使用随机 key, SADD 使用随机值
-P 通过管道传输 请求 1
-q 强制退出 redis。仅显示 query/sec 值
–csv 以 CSV 格式输出
-l 生成循环,永久执行测试
-t 仅运行以逗号分隔的测试命令列表。
-I Idle 模式。仅打开 N 个 idle 连接并等待。

例如:redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q

Redis 客户端连接

1 redis-server –maxclients 100000
设置最大连接数为 100000

2 config get maxclients
查看最大连接数

3 client setname
设置当前连接的名称

4 client pause 10
挂起客户端连接,指定挂起的时间以毫秒计

5 client kill
关闭客户端连接

数据类型

一、基本命令
启动:$ redis-serve
进入客户端测试:redis-cli
设值:set key value
取值:get key
二、数据类型
1.String(字符串)
2.Hash(哈希)
设值:hmset user:1 v1 v2 v3 v4 v5 200.. //貌似最后一个必须为数字?
取值:hmgetall user:1
3.List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
设置:lpush key value
lpush key value2
lpush key value3 ….
取值:lrange key 0 10
4.Set(集合)
添加一个string元素到,key对应的set集合中,成功返回1,如果元素已经在集合中返回0,key对应的set不存在返回错误。
设值:sadd key value
sadd key value2
sadd key value3
sadd key value
(该value已经在集合中存在,故应返回0)
根据集合内元素的唯一性,第二次插入的元素将被忽略。
取值:smembers key
5.zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型
的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。
设值:(zadd key score member)
zadd key 0 value
zadd key 1 value2
取值:zrangebyscore key 0 1000

JavaWeb

发表于 2017-01-16 | 分类于 JavaWeb

Servlet

Tomcat:Web 应用服务器,属于轻量级应用服务器,也叫Servlet容器

1. 生命周期

生命周期方法:

  • void init(ServletConfig):出生之后(1次);
  • void service(ServletRequest request, ServletResponse response):每次处理请求时都会被调用;
  • void destroy():临死之前(1次);

特性:
 单例,一个类只有一个对象;当然可能存在多个Servlet类!

2. 实现Servlet的方式

实现Servlet有三种方式:

  • 实现javax.servlet.Servlet接口;
  • 继承javax.servlet.GenericServlet类;
  • 继承javax.servlet.http.HttpServlet类;

通常我们会去继承HttpServlet类来完成我们的Servlet

3. 常用方法

1. HttpServletRequest方法:

  • String getParameter(String paramName):
    获取指定请求参数的值;
  • String getMethod():
    获取请求方法,例如GET或POST;
  • String getHeader(String name):
    获取指定请求头的值;
  • void setCharacterEncoding(String encoding):
    设置请求体的编码!因为GET请求没有请求体,所以这个方法只只对POST请求有效。当调用request.setCharacterEncoding(“utf-8”)之后,再通过getParameter()方法获取参数值时,那么参数值都已经通过了转码,即转换成了UTF-8编码。所以,这个方法必须在调用getParameter()方法之前调用!
  • request.getRequestDispatcher(“/Servlet
    Test”).forward(request,response)
    :转发

2. HttpServletResponse方法:

  • PrintWriter getWriter():获取字符响应流,使用该流可以向客户端输出响应信息。例如
    response.getWriter(). print(“<h1>Hello JavaWeb!</h1>”);
  • ServletOutputStream getOutputStream():获取字节响应流,当需要向客户端响应字节数据时,需要使用这个流,例如要向客户端响应图片;
  • void setCharacterEncoding(String encoding) :用来设置字符响应流的编码,例如在调用setCharacterEncoding(“utf-8”);之后,再response.getWriter()获取字符响应流对象,这时的响应流的编码为utf-8,使用response.getWriter()输出的中文都会转换成utf-8编码后发送给客户端;
  • void setHeader(String name, String value) :向客户端添加响应头信息,例如setHeader(“Refresh”, “3;url=http://www.itcast.cn”),表示3秒后自动刷新到http://www.itcast.cn;
  • void setContentType(String contentType) :该方法是setHeader(“content-type”, “xxx”)的简便方法,即用来添加名为content-type响应头的方法。content-type响应头用来设置响应数据的MIME类型,例如要向客户端响应jpg的图片,那么可以setContentType(“image/jepg”),如果响应数据为文本类型,那么还要台同时设置编码,例如setContentType(“text/html;chartset=utf-8”)表示响应数据类型为文本类型中的html类型,并且该方法会调用setCharacterEncoding(“utf-8”)方法;
  • void sendError(int code, String errorMsg) :向客户端发送状态码,以及错误消息。例如给客户端发送404:response(404, “您要查找的资源不存在!”)。
  • response.sendRedirect(“http:…..”):重定向某个地址
    3. ServletConfig方法:
    ServletConfig对象是由服务器创建的,然后传递给Servlet的init()方法,你可以在init()方法中使用它
  • String getServletName() :获取Servlet在web.xml文件中的配置名称,即<servlet-name>指定的名称;
  • ServletContext getServletContext() :用来获取ServletContext对象。
  • String getInitParameter(String name) :用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
  • Enumeration getInitParameterNames() :用来获取在web.xml中配置的所有初始化参数名称;
    在元素中还可以配置初始化参数:

4. Servlet与线程安全

因为一个类型的Servlet只有一个实例对象,那么就有可能会现时出一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明Servlet的工作效率很高,但也存在线程安全问题!
所以我们不应该在Servlet中便宜创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

5. ServletContext概述

服务器会为每个应用创建一个ServletContext对象:

  • ServletContext对象的创建是在服务器启动时完成的;
  • ServletContext对象的销毁是在服务器关闭时完成的。

ServletContext是JavaWeb四大域对象之一:

  • PageContext;
  • ServletRequest;
  • HttpSession;
  • ServletContext;
    所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据
    setAttribute()、getAttribute()、removeAttribute()

6. 请求转发与重定向比较

  • 请求转发是一个请求,而重定向是两个请求;
  • 请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求;
  • 请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用;
  • 请求转发对AServlet和BServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求;
  • 重定向的第二个请求一定是GET;

6. 其他

配置servlet初始化时间
<load-on-startup>3</load-on-startup>

通配符使用

  • <url-pattern>/servlet/*<url-patter>:/servlet/a、/servlet/b,都匹配/servlet/*;
  • <url-pattern>*.do</url-pattern>:/abc/def/ghi.do、/a.do,都匹配*.do;
  • <url-pattern>/*<url-pattern>:匹配所有URL;

配置默认参数

1
2
3
4
<context-param>
<param-name>paramName1</param-name>
<param-value>paramValue1</param-value>
</context-param>

获取值:
this.getServletContext(). getInitParameter("paramName1");

获取真实路径
servletContext.getRealPath(“/WEB-INF/b.txt”);

读文件
InputStream in = servletContext. getResourceAsStream(“/WEB-INF/b.txt”);

Class类的getResourceAsStream(String path)

  • 路径以“/”开头,相对classes路径;
  • 路径不以“/”开头,相对当前class文件所有路径,例如在cn.itcast.servlet.MyServlet中执行,那么相对/classes/cn/itcast/servlet/路径;

ClassLoader类的getResourceAsStream(String path)

  • 相对classes路径;

get请求乱码
name = new String(name.getBytes(“iso-8859-1”), “utf-8”);

post乱码
request.setCharacterEncoding(“utf-8”); String name = request.getParameter(“name”);

JSP

jsp其实就是一个servlet,jsp第一次被请求的时候,会编译成class文件,然后再去执行servlet

1. JSP脚本

  • <%…%>:Java语句;
  • <%=…%>:Java表达式;
  • <%!…%>:Java定义类成员;
    其中<%=…%>与out.print()功能是相同的!它们都是向客户端输出,例如:
    <%=s1%>等同于<% out.print(s1); %>

2. JSP指令

JSP中有三大指令:page、include、taglib,page最常用。
page指令

1
<%@page language=”java” contenType=”text/html;charset=gb2312” session=”true” buffer=”64kb” autoFlush=”true” isThreadSafe=”true” info=”text” errorPage=”error.jsp” isErrorPage=”true” isELIgnored=”true” pageEncoding=”gb2312” import=”java.sql.*”%>

web.xml也可以配置错误页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<error-page>

<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>

<error-code>500</error-code>

<location>/error500.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>

<location>/error.jsp</location>
</error-page>

其他指令
<%@include file="filename.jsp"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

九大内置对象

  • out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
  • config(ServletConfig):对应“真身”中的ServletConfig;
  • page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象;
  • pageContext(PageContext):页面上下文对象。
  • exception(Throwable):只有在错误页面中可以使用这个对象;
  • request(HttpServletRequest):即HttpServletRequest类的对象;
  • response(HttpServletResponse):即HttpServletResponse类的对象;
  • application(ServletContext):即ServletContext类的对象;
  • session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。

JSP动作标签

include指令是在编译级别完成的包含,即把当前JSP和被包含的JSP合并成一个JSP,然后再编译成一个Servlet。
include动作标签是在运行级别完成的包含,即当前JSP和被包含的JSP都会各自生成Servlet,然后在执行当前JSP的Servlet时完成包含另一个JSP的Servlet。它与RequestDispatcher的include()方法是相同的!


forward标签的作用是请求转发!forward标签的作用与RequestDispatcher.forward()方法相同

1
2
3
<jsp:include page="/b.jsp">
<jsp:param value="zhangSan" name="username"/>
</jsp:include>

EL表达式

判断字符串长度是否为0或者集合为0${empty “”}
集合对象:${map.key}、${map[‘key’]}

内置对象访问

  • pageScope:${pageScope.name}等同与pageContext.getAttribute(“name”);
  • requestScope:${requestScope.name}等同与request.getAttribute(“name”);
  • sessionScoep: ${sessionScope.name}等同与session.getAttribute(“name”);
  • applicationScope:${applicationScope.name}等同与application.getAttribute(“name”);

其他对象

  • ${header.Host}
  • ${initParam.par} //获取web.xml配的参数
  • ${cookie.}
  • ${pageContext.servletContext.serverInfo}
  • ${pageContext.session.id}
  • ${pageContext.request.requestURL}

JSTL表达式

  1. out和set
    <c:out value=”${aaa}” default=”xxx”/> 等于${aaa}
    c:set var=”a” value=”hello” scope=”session”/> 在session中添加name为a,value为hello的数据。

  2. remove
    <c:remove var="a"/> 删除所有域中name为a的数据!也可以指定:scope=”page”

  3. url
    c:url value="/"/> 输入当前项目路径 如:test/

  4. if

    1
    2
    3
    4
    <c:set var="a" value="hello"/>
    <c:if test="${not empty a }">
    <c:out value="${a }"/>
    </c:if>
  5. choose

    1
    2
    3
    4
    5
    6
    7
    <c:set var="score" value="${param.score }"/>
    <c:choose>
    <c:when test="${score > 100 || score < 0}">错误的分数:${score }</c:when>
    <c:when test="${score >= 90 }">A级</c:when>
    <c:when test="${score >= 60 }">D级</c:when>
    <c:otherwise>E级</c:otherwise>
    </c:choose>
  6. forEach

    1
    2
    3
    4
    <c:set var="sum" value="0" />
    <c:forEach var="i" begin="1" end="10" step="2">
    <c:set var="sum" value="${sum + i}" />
    </c:forEach>
1
2
3
<c:forEach var="item" items="${ns }">
<c:out value="name: ${item }"/><br/>
</c:forEach>
1
2
3
4
5
6
7
<c:forEach var="item" items="${ns }" varStatus="vs">
<c:if test="${vs.first }">第一行:</c:if>
<c:if test="${vs.last }">最后一行:</c:if>
<c:out value="第${vs.count }行: "/>
<c:out value="[${vs.index }]: "/>
<c:out value="name: ${vs.current }"/><br/>
</c:forEach>
  • count:int类型,当前以遍历元素的个数;
  • index:int类型,当前元素的下标;
  • first:boolean类型,是否为第一个元素;
  • last:boolean类型,是否为最后一个元素;
  • current:Object类型,表示当前项目。
    fmt标签库常用标签
    <fmt:formatDate value="${d }" pattern="yyyy-MM-dd HH:mm:ss"/>
    <fmt:formatNumber value="${d2 }" pattern="#.##"/>
    <fmt:formatNumber value="${d1 }" pattern="0.00"/>

其他

在请求url后加上sessionId
<%=response.encodeURL ("/test/index.jsp") %> href='/test/index.jsp;jsessionid=<%=session.getId() %>'

JDBC和数据库

1. JDBC

六大步骤

  1. 加载驱动类
    Class.forName ("oracle.jdbc.OracleDriver");
  2. 建立连接
    Connection conn = DriverManager. getConnection(url,name,password);
  3. 创建statement
    Statement state = conn.createStatement();
  4. 执行SQL语句
    String sql = "select id,name from s_emp"; ResultSet rs = state.executeQuery(sql);
  5. 处理结果集

    1
    2
    3
    4
    5
    6
    while(rs.next()){

    int id = rs.getInt("id");
    String name = rs.getString(2);
    System.out.println(id+" "+name);
    }
  6. 关闭连接
    rs.close(); state.close(); conn.close();

PreparedStatement与Statement区别
PreparedStatement叫预编译声明!
PreparedStatement是Statement的子接口,你可以使用PreparedStatement来替换Statement。
PreparedStatement的好处:

  • 防止SQL攻击;
  • 提高代码的可读性,以可维护性;
  • 提高效率。

预处理的原理
每个pstmt都与一个sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译。执行时只是把参数传递过去而已!
若二次执行时,就不用再次校验语法,也不用再次编译!直接执行!

JDBC中的事务
Connection的三个方法与事务相关:

  • setAutoCommit(boolean):设置是否为自动提交事务,如果true(默认值就是true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务,如果设置false,那么就相当于开启了事务了;con.setAutoCommit(false)表示开启事务!
  • commit():提交结束事务;
  • rollback():回滚结束事务。

2. 事务

事务的四大特性是:

  • 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
  • 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
  • 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

    开启事务:start transaction;
    结束事务:commit或rollback。

事务的并发读问题

  • 脏读:读取到另一个事务未提交数据;
  • 不可重复读:两次读取不一致(读取到了另一事务的更新;)
  • 幻读(虚读):读到另一事务已提交数据。

四大隔离级别

  1. SERIALIZABLE(串行化)
     不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;
     性能最差;三种问题都能处理

  2. REPEATABLE READ(可重复读)(MySQL)
     防止脏读和不可重复读,不能处理幻读问题;
     性能比SERIALIZABLE好

  3. READ COMMITTED(读已提交数据)(Oracle)
     防止脏读,没有处理不可重复读,也没有处理幻读;
     性能比REPEATABLE READ好

  4. READ UNCOMMITTED(读未提交数据)
     可能出现任何事务并发问题
     性能最好

MySQL的默认隔离级别为REPEATABLE READ。

3. 连接池

4. 监听器、过滤器、拦截器

  • 拦截器是基于java的反射机制的,而过滤器是基于函数回调
  • 过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
  • 拦截器是AOP的一种实现

过滤器的生命周期

  • init(FilterConfig):服务器启动创建Filter实例,并且每个类型的Filter只创建一个实例,创建完Filter实例后,这个方法只会被执行一次;
  • doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户每次访问就会执行。
  • destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
    配置过滤器拦截方式:REQUEST、FORWARD、INCLUDE、ERROR。
    1
    2
    3
    4
    5
    6
    <filter-mapping>
    <filter-name>myfilter</filter-name>
    <url-pattern>/b.jsp</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

iconfont使用教程

发表于 2017-01-06 | 分类于 前端

自己项目中用到了第三方登录的功能,来记录下怎么添加第三方登录的图标。

1.寻找合适的图标库

我这里是用阿里的iconfont矢量图标,官方网址:http://www.iconfont.cn/

2.添加图标,下载到本地,解压

这是解压后的目录:

3.将iconfont.css导入到你的css文件。

把url中的文件拷贝到CSS能访问到的路径

4.html代码中直接引用

<i class="iconfont icon-qq1"></i>

SSH框架

发表于 2016-12-30 | 分类于 java框架

web.xml配置

1. spring启动方式

三种方式:

  1. 本地文件
    ApplicationContext ac = new FileSystemXmlApplicationContext (“applicationContext.xml”);

  2. Classpath
    ApplicationContext ctx = new ClassPathXmlApplicationContext (“ApplicationContext.xml”);

  3. Web应用中依赖servlet或Listener
    (1)利用Listener接口来实现
    (2)利用Servlet接口来实现

(1)利用Listener接口来实现

1
2
3
4
5
6
7
8
9
10
<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>

<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
<!--<param-value>/WEB-INF/spring-context.xml</param-value> -->
</context-param>

(2)利用Servlet接口来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<context-param>

<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<Servlet>

<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
```
### 2. struts2配置
```xml
<filter>

<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

配置文件

1. hibernate.cfg.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<hibernate-configuration>

<session-factory>
<!-- 数据库驱动程序类 -->
<property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
<!-- 数据库连接字符串 -->
<property name="connection.url">jdbc:oracle:thin:@192.168.1.249:1522:oracle</property>
<!-- 数据库用户名 -->
<property name="connection.username">sc160501</property>
<!-- 数据库密码 -->
<property name="connection.password">sc160501</property>
<!-- Hibernate 使用数据方言 -->
<property name="dialect">org.hibernate.dialect.OracleDialect</property>
<!--
是否创建数据库表 create 每次启动都创建 update 如果数据库没有表就创建 validate
每次启动就校验数据库表和model是否匹配 create-drop 启动时创建,停止时删除
-->
<property name="hbm2ddl.auto">update</property>
<!-- 是否显示SQL语句 -->
<property name="show_sql">true</property>
<!-- 是否格式化SQL语句 -->
<property name="format_sql">true</property>

<mapping resource="com/gjd/model/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>

hbm.xml映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<hibernate-mapping package="com.hzcl.model">

<class name="User" table="t_user">
<id name="id" column="id" type="integer">
<generator class="sequence">
<param name="sequence">
seq_t_user
</param>
</generator>
</id>
<property name="name" column="user_name" type="string" />
<property name="pwd" column="pwd" type="string" />
<property name="createDate" column="create_date" type="date"
not-null="false" />
<property name="sex" column="sex" length="2" type="string" not-null="false" />
<property name="imgSrc" column="img_src" type="string"
not-null="false" />
<property name="loginTime" column="loginTime" type="date" />
<!-- 一对多
<set name="comm" table="t_com" cascade="all" lazy="false">
<key column="tid"></key>
<one-to-many class="Comment"/>
</set>
-->
<!-- 多对一
<many-to-one name="user" class="User" column="tid" lazy="false"></many-to-one>
-->
<!-- 多对多
<set name="projects" table="PROEMP">
<key column="RPROID"></key>
<many-to-many class="Project" column="REMPID">
</many-to-many>
</set>
-->

</class>
</hibernate-mapping>

User.hbm.xml常用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<hibernate-mapping
schema="schemaName" //模式的名字
catalog="catalogName" //目录的名称
default-cascade="cassade_style" //级联风格 @
default-access="field/property/CalssName" //访问策略 @
default-lazy="true/false" //加载策略 @
package="packagename" //默认包名
/>
<class
name="ClassName" //对应映射的类
table="tableName" //对应映射数据库的表
batch-size="N" //抓取策略,一次抓取多少记录
where="condition" //条件 eg:抓取条件
entity-name="EntiyName" //如果需要映射多张表
/>
<id //表的主键
name="propertyName" //对应的属性
type="typeName" //对应类型
column="column_nam" //映射数据库中表当中字段名的名称
length="length" //指定长度
<generator class="generatorClass"/> //主键生成策略 @
/>

关联操作

  1. 关联查询

    1)延迟加载
    对于关联属性,Hibernate默认采用延迟记载的机制。
    lazy=”true”:采用延迟记载(默认)
    lazy=”false”:不采用延迟加载
    2)采用连接查询
    fetch=”select”
    不采用连接查询(默认)
    fetch=”join”
    采用连接查询,此时lazy属性失效

  2. 级联操作
    1)什么叫级联操作

    在Hibernate里,在对一方进行增、删、改时要自动的对另一方也进行增、删、改,这样的行为称之为级联操作。
    2)如何实现级联添加、修改、删除
    在要操作的对象的映射关系文件中,在关联
    属性上追加cascade属性,用这个属性的值
    来指定级联方式:
    cascade=”none”
    不支持级联(默认)
    cascade=”save-update”
    支持级联添加、修改
    cascade=”delete”
    支持级联删除
    cascade=”all”
    支持级联添加、修改、删除
    //级联删除时,需要在配置文件的关联属性上追加inverse=”true”。

单一主键
(1)assigned 由java应用程序负责生成(手工赋值)
(2)native 由底层数据库自动生成标示符,如果是MySQL就是increment,如果是Oracle就是sequence,等等

2. applicationContext.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!-- 引入资源文件 -->

<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置druid连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 数据库基本信息配置 -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driverClass}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="10" />

</bean>


<!-- 配置Hibernate的相关属性 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/model/User.hbm.xml</value>
<value>com/model/News.hbm.xml</value>
<value>com/model/Comment.hbm.xml</value>
</list>
</property>
</bean>

<!-- 配置事务管理器: -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager" />

<!-- 注入 dao -->
<bean id="userDao" class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 注入 service -->
<bean id="userService" class="com.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 注入 action -->
<bean id="userAction" class="com.action.UserAction">
<property name="userService" ref="userService"></property>
</bean>

3. struts.xml配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<struts>

<!-- 让Spring 来创建Action对象 -->
<constant name="struts.objectFactory" value="spring"/>
<constant name="struts.action.extension" value="html,"></constant>
<constant name="struts.custom.i18n.resources" value="message"></constant>
<package name="user" extends="struts-default" namespace="/">
<interceptors>
<interceptor name="login" class="com.interceptor.LoginInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="login"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="myStack"></default-interceptor-ref>
<global-results>
<result name="error" type="redirect">/login.jsp</result>
</global-results>
<action name="user_*" class="userAction" method="{1}">
<result type="redirectAction">news_list</result>
<result name="login">/login.jsp</result>
<result name="info">/userInfo.jsp</result>
<result name="logout">/login.jsp</result>
<result name="input">/register.jsp</result>
<result name="lang">/register.jsp</result>
</action>
<action name="news_*" class="newsAction" method="{1}">
<result name="del" type="redirectAction">news_list</result>
<result>/news.jsp</result>
<result name="modify">/addnews.jsp</result>
<result name="new">/new.jsp</result>
</action>
<action name="comm_*" class="commentAction" method="{1}">
<result name="newComm" type="chain">news_newCom</result>
</action>
<action name="file" class="fileAction">
<result>/login.jsp</result>
</action>
</package>
</struts>

struts.xml中包含的内容:

1、全局属性
2、用户请求和相应Action之间的对应关系
3、Action可能会用到的参数和返回结果
4、各种拦截器的配置

配置详解


package提供了将多个Action组织成为一个模块的方式
package的名字必须是唯一的,可以在这个包上加一些拓展的包

为拦截器
可以为拦截器定义name(名称)和class(类路径)

拦截器栈

定义默认的拦截器,每个Action都会自动引用

包含其他配置文件


注意:
1.被include的标签一定要符合struts的dtd规范。也就是说被include的xml文件的内部格式要符合struts的xml文件规范。
2.xml文件的编码格式要相同,如果是utf-8,那么都是utf-8。
配置编码:

工作原理:

用户的请求HttpServletRequest—>过滤器filter—>ActionMapper(.action)请求—->过滤器—->ActionProxy—->
通过ConfigurationManager读取struts.xml中的ActionInvocation具体的Action类—->
通过ActionProxy创建Action反向实例—->拦截器—>action,返回result(字符串对象)对应的视图—->
拦截器—->HttpServletResponse返回请求

action搜索顺序

例子:
localhost:8080/product_one/hellowworld.jsp可以进入result.jsp页面
localhost:8080/product_one/aaa/ddd/ccc/
hellowworld.jsp也可以进入result.jsp页面
Action搜索顺序:
localhost:8080/struts2/path1/path2/path3/
student.action
第一步:判断package是否存在,如:path1/path2/path3/

如果package存在
第二步:则判断该package中action是否存在,如果不存在则去默认namespace的package里面寻找action
第三步:如果没有,则报错

如果package不存在:
第二步:检查上一级路径的package是否存在(直到默认namespace),重复第一步
第三步:如果没有则报错

如果请求为/login.action,系统会根据根命名空间(”/“)中查找名为login的Action,如果在根命名空间中找到了名为login的Action,则该Action处理用户的请求;否则系统将转为在默认命名空间中寻找名为login的Action,如果默认的命名空间中有名为login的Action,则由该Action处理用户的请求。如果两个命名空间中都找不到名为login的Action,那么系统将出现错误。

注意:命名空间只有一个级别。如果请求的URL是/bookservice/search/get.action系统将先在/bookservice/search的命名空间下查找名为get的Action,如果在该系统命名空间内找到名为get的Action,则由该Action处理该用户的请求;如果在该命名空间中没有找到名为get的Action,系统将直接进入默认的命名空间中查找名为get的Action,而不会在bookservice的命名空间下查找名为get的Action。
可以多个包使用同一个命名空间,但是相同的命名空间相当于同一个模块,也就是同一个包。
一个包中可以有name值相同的action,但是后面的action会把前面同名的action覆盖掉

动态方法调用:

动态方法调用是为了解决一个Action对应多个请求的处理,以免Action太多。
三种方式:指定method属性、感叹号方式、通配符方式(这种方式较方便)

  1. method属性
  1. 感叹号
1
2
3
4
5
6
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<action name="hellowword" class="com.Action.hellowAction">
<result >/result.jsp</result>
<result name="add">/add.jsp</result>
<result name="update">/update.jsp</result>
</action>

localhost:8080/struts_hellowworld/
aaa/hellowworld!.action

  1. 通配符
    1
    2
    3
    4
    5
    <action name="*_*" method="{2}" class="com.Action.{1}Action">
    <result >/{2}.jsp</result>
    <result name="add">/{2}.jsp</result>
    <result name="update">/{2}.jsp</result>
    </action>

localhost:8080/struts_hellowworld
/aaa/hellow_add.action

默认的action

1
2
3
4
5
<default-action-ref name="index"></default-action-ref>

<action name="index">
<result>/error.jsp</result><br>
</action>

结果类型input的效果

  • 1.当参数类型转换错误时,如age输入框中的类型是字母等情况,方法自动返回input
  • 2.当action中存在addFiledError时:
  • 1)addFileError放在一般执行方法,addFieldError(“”, “”);语句后面有返回input的语句
  • 2)addFileError放在validate()中
    *3.FileError的表现形式:
  • 在jsp页面中使用标签,该标签name属性为addFieldError方法中的参数fieldName,在jsp页面中使用struts标签,
  • 需要导入标签库 语句:<%@ taglib prefix=”s” uri=”/struts-tags” %>

【Structs2处理流程】

用户请求Structs框架控制器(Action)Structs框架视图资源
返回String,提供代码复用性,有利于框架分离。
【Action中五种内置属性(com.opensymphony.xwork2.Action)】
(1) SUCCESS Action正确的执行完成,返回相应的视图,success是name属性的默认值。
(2) NONE 表示Action正确的执行完成,但并不返回任何事视图。
(3) ERROR 表示Action执行失效,返回错误处理视图。
(4) LOGIN Action因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户进行登录验证
(5) INPUT Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入界面,一般在应用中,会对这些 参数进行验证,如果验证没有通过,将自动返回该视图。
返回

1.在result里面最重要的属性是type类型,type的默认值为dispatcher(转发),这个类型支持JSP视图技术。
2.Struts2支持多种视图技术,例如JSP、Valocity(模板引擎)、FreeMaker(模板引擎)等。
3.常用三个:chain,redirect,plaintext。
1)、chain:将action和另外一个action链接起来,必须是一个action不能是jsp页面。
2)、redirect:重定向(会丢失请求参数)。
3)、plaintext:返回网页源代码。
4)、stream:返回inputstream用于文件下载。
5)、默认”dispatcher” jsp传值 请求转发

客户端通过httpservletrequest向servlet容器,也就是tomcat提交一个请求,这个请求会经过一些列的过滤器,如ActionContentClearUp过滤器,最终被struts核心过滤器过滤,也就是FilterDispatcher.从struts2.1.3版本以后struts的核心控制器发生了变化,变成了PrepqreAndExecuteFiletr,核心过滤器过滤以后,调用访问ActionMapping,决定是否调用某一action,如果用户请求的是jsp页面或者是其他资源,不会调用某一action,如果决定调用某一action,ActionMapping会将控制权委派给ActionProxy,也叫action代理,此时action代理会通过一个Configuration Manager也就是配置管理器对象加载struts核心配置文件,也就是struts.xml.如果在struts.xml找到需要创建的action,ActionProxy会创建一个Action Invocation实例,action Invocation包括一些列的拦截器和action,先顺序执行一些列的拦截器,然后执行action处理,返回一个结果,通过result返回一个视图或者调用另外某个action.当返回这个视图以后,将之前执行过的拦截器反向执行一遍,然后通过response响应客户端的请求.

1
2
3
4
5
6
7
8
<!-- 注册拦截器 -->

<interceptors>
<interceptor name="auth" class="com.imooc.interceptor.AuthInterceptor">
</interceptor>
<!-- 引用拦截器 -->

<interceptor-ref name="mytimer"></interceptor-ref>

默认拦截器栈

  1. 在struts-default.xml中定义一个defaulStack拦截器栈,并将其指定为默认拦截器.
  2. 只要在定义包的过程中继承struts-default包,那么defaultStack将是默认的拦截器.
  3. 当为包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用.
  4. 拦截器栈中的各个拦截器的顺序很重要.

引用默认的拦截器栈
<interceptor-ref name="defaultStack"></interceptor-ref>
在引用拦截器的时候一般先引用默认的拦截器。
WEB-INF里的文件默认情况下是不允许被外部直接访问的,可以通过action间接来访问
如果action的class不写,则默认是ActionSupport这个类

struts.xml 定义顺序

result-types
interceptors
interceptor-stack
default-interceptor-ref 默认拦截器
default-action-ref 默认action
default-class-ref Action默认处理的类
global-results 全局返回
global-exception-mappings 全局异常
action

核心代码编写

1. hibernate

一级缓存

  1. 什么是一级缓存
    Hibernate在创建Session时,会给每一个Session
    分配一块内存空间,用于缓存Session查询到的
    对象数据,这块内存空间称之为一级缓存。由于
    该空间是给Session使用的,也称Session级缓存。
    重点:
    –一级缓存又称Session级缓存
    –一级缓存是Session独享的

  2. 为什么用一级缓存
    1)作用:
    一级缓存可以降低数据库访问次数,提高
    代码执行效率。
    2)步骤:
    –Session取值时会优先向它的一级缓存取值
    –如果缓存中没有数据,它会向数据库取值,
    并将取到的值放入一级缓存,然后Session
    从缓存中取出数据
    –当再次查询相同的数据时,由于一级缓存中
    已经存在了该数据,则直接返回,不需要重新
    访问数据库

  3. 如何使用一级缓存
    1)一级缓存是默认开启的,自动使用。
    2)规则:
     --一级缓存是Session独享的,即一个Session
     不能访问另一个Session缓存的数据。
     --每次查询,Session仅仅是把本次查询结果
     放到一级缓存中
     --如果查询的结果是多条数据,Session会将
     这些数据拆开,以单个对象的形式存入一级缓存。
     --在执行save、update、delete时,会自动触发
     缓存的更新。
    3)一级缓存是给Session使用的,并且是由Session
         负责管理,Session管理一级缓存的方式如下:
         a、session.evict(obj);
             evict可以将obj对象从当前session的缓存区
             移除。
         b、session.clear();
             clear可以将当前session的缓存区清空。
         c、session.close();
             session关闭时,它会释放自己的缓存区域,
             从而缓存数据也释放了。
    

二、对象持久性
1、Hibernate下,可以把对象看做具有3种状态,分别
为临时态、持久态、游离态,对象持久性是值对象
在这三种状态之间的转换规则。
2、3种状态的转换及规则
1)临时态
a、转换
–new出来的对象是临时态的
–delete持久态的对象,它将转变为临时态
b、规则
–临时态的对象可以被垃圾回收
–临时态的对象没有被持久化过,
并且没有与session建立关联。
2)持久态()
a、转换
–通过save/update操作过的对象,
是持久态的。
–经过get/load/list/iterate方法查询得到的
对象是持久态的。
b、规则
–持久态的对象不能被垃圾回收
–持久态的对象被持久化了,并且与
session建立起了关联。
–(
)持久态的对象存在于一级缓存中。
–(*)持久态的对象可以自动与数据库同步,
同步的时机是在调用session.flush()时,
实际上事务提交时也可以同步,原因是
ts.comit() = session.flush() + commit;
3)游离态
a、转换
–通过evict/clear/close操作过的对象,
是游离态的。
b、规则
–游离态的对象可以被垃圾回收
–游离态的对象被持久化过,
但是已经与session解除了关联。
3、问题
当大批量插入数据时,每次插入都会导致对象存在
于一级缓存中,如果数据量太大,可能导致缓存
溢出,如何解决?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

public void batchDdd(List<Emp> emps) {
if(emps == null
|| emps.size() == 0) {
return;
}
Session session = HibernateUtil.getSession();
Transaction ts = session.beginTransaction();
try {
for(int i=0;i<emps.size();i++) {
//循环添加Emp
session.save(emps.get(i));
//每100批次,要同步并清理缓存
if(i%100 == 0) {
//每隔100次触发同步,但不提交事务
session.flush();
//清理缓存
session.clear();
}
}
//统一的提交事务
ts.commit();
} catch(HibernateException e) {
ts.rollback();
}
}
```
**三、延迟加载**
1、什么是延迟加载
Hibernate中存在一些查询方法,在查询时并没有
立刻访问数据库查询数据,而是返回了空对象(
对象并不是null,而是经过new的对象,但对象中
除ID外其他属性都为null),当程序使用此对象
时,Hibernate才真正去查询数据库,将数据填充
到返回的对象中。这种将查询推迟到使用对象时的
机制,称之为延迟加载。
2、为什么用延迟加载
1)推迟的时间内,由于数据没有加载,可以节约
内存空间,可以提升内存使用率。
2)如果有对象查询后并没有使用,那么在延迟加载
的方法中实际上没有访问数据库,可以减少一定
数量的数据库访问次数。
3、如何使用延迟加载
1)有一些方法本身自动支持延迟加载,只要调用
这些方法就可以使用延迟加载。
2)具有延迟加载的方法如下
a、session.load()
b、query.iterate()
c、关联映射中的关联属性加载
**四、二级缓存**
1、什么是二级缓存,二级缓存就是SessionFactory缓存
比Session作用范围更广
2、先查一级缓存,如果查询不到再查二级缓存,如果二级缓存也查询不到,就直接查数据库
查询到数据以后保持到一级缓存和二级缓存中
如果一级缓存查询不到数据 就从二级缓存中查询

一级缓存和二级缓存的区别
1、作用范围不一样一个属于session的一个属于sessionFactory
2、一级缓存默认开启 二级缓存必须手动开启
3、一级缓存数据缓存在内存中 二级缓存数据缓存在磁盘中

使用二级缓存步骤
1、导入ehcache.jar
2、编写ehcache.xml缓存配置文件
3、在hibernate.cfg.xml中开启二级缓存的支持
```xml
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">
true
</property>
<!-- 配置二级缓存驱动类 -->
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<!-- 开启查询缓存 -->
<property name="cache.use_query_cache">
true
</property>

4、开启二级缓存
持久化对象映射文件添加

持久层增删改查
dao层继承 该类:HibernateDaoSupport
this.getHibernateTemplate().save(); //增删改查

2. struts

获取request、response
采用耦合IOC方式注入属性
三个接口
ServletRequestAware
ServletresponseAware
ServletContextAware
ServletSessionAware
ActionContext struts2自己封装了Servlet的方法
ServletActionContext 可以获取原生态的Servlet的方法
表单验证方法
validate() //支持表单验证的方法

国际化

1
2
3
4
5
6
7
8
9
10
11
12
国际化:
第一步:struts.xml中加入
<constant name="struts.custom.i18n.resources" value="message"></constant>
第二步:在与struts.xml文件同目录下创建一下两个文件.

message_en_US.properties(配置英文信息)
message_zh_CN.properties(配置中文信息)
切换:
<a href="changeLanguage.action?request_locale=zh_CN" >中文</a>
<a href = "changeLanguage.action?request_locale=en_US">英文</a>
jsp中使用:(必须用ognl标签)
<s:text name="m_name"/>

新建拦截器的步骤

1 建立一个拦截器类继承自Abstractlnertceptor类,并实现inertcept方法。invocation.invoke()方法调用下一个拦截器,如果已经是最后一个拦截器,则执行目标action

1
2
3
4
5
6
7
8
9
10
11
public String intercept(ActionInvocation invoaction) throws Exception {

//1.执行action之前
long start = System.currentTimeMillis();
//2.执行下一个拦截器,如果已经是最后一个拦截器,则执行目标Action
String result = invoaction.invoke();
//3.执行action之后
long end = System.currentTimeMillis();
System.out.println(end-start);
return result;
}

自定义拦截器:

  1. 方法一:实现Interceptor接口
    -void init():初始化拦截器所需资源
    -void destroy() :释放在init()中分配的资源
    -String intercept(ActionInvocation ai)throws Exception 实现拦截器功能,利用ActionInvocation参数获取Action状态,返回result字符串作为逻辑视图。

  2. 方式二:继承AbstractInterceptor类
    -提供了init()和destroy() 方法的空实现
    -只需要实现intercept方法即可

实际开发当中一般会去继承AbstractInterceptor这个父类

2 在strut的配置文件的package中注册拦截器,注册拦截器在action调用之前,在相应的action配置中个,通过intercepor-ref标签中来引用拦截器

接收参数

1,使用Action的属性接受参数,在Action中定义需要接受的属性,并写它的set/get方法。
2,使用DomainModel接受参数,创建实体类定义需要接受的属性,并set/get方法,在Action中创建实体类名属性。并在界面进行指定。
3,使用ModelDriver接受参数,在Action中实现ModelDriver<实体类名>接口,并实现方法返回当前需要转换的对象,删除set/get方法,并对 对象 进行实例化,并取消指定。
4,request
5,获取List集合中的参数。获取多个参数。

字段驱动方式
第一种接收参数的方法:直接在action类中创建相应的属性和getter和setter,和前端的name名字相同。eg:前端的username,在action类中就要建立一个private String username; Struts会自动映射为这个属性赋值

模型驱动方式
第二种接受参数的方法:使用DomainModel,将username 和password两个属性封装为一个类User(必须是标准的JavaBean),在action中声明这个属性:private User user; 同时为user设置getter和setter;在前端中的name需要设置为user.name和user.password,才能映射成功

第三种接收参数的方法:使用ModelDriven接口,这个action必须实现这个接口的public T getModel()方法。此时声明的属性必须实例化,eg: private User user = new User(); 同时不需要getter和setter。前端的name也只需要写username和password就可以,不需要再加域了。这种方法时最推荐的方法,因为可以减少前后端的耦合

怎么绑定域名

发表于 2016-07-11 | 分类于 建站相关

购买域名

我是在godaddy上面买的,一个国外的网站,在国内买需要备案,所以选择国外,而且这个还支持支付宝。

1.查找你想要的域名

godaddy

2.查到适合自己的域名选择,然后点击「continue to Cart」

这里都是些附加的服务,不用管,继续点击「continue to Cart」

3.确认购买

这里可以修改购买年限,我们还可以上网搜 godaddy 的优惠码,可以优惠一点点,土豪请忽略。
godaddy

4.结算。

登录或注册界面,填完必要的信息之后,选择用支付宝结算。

将域名与 GitHub Pages 的空间绑定

1.DNS 设置

注册DNSpod,添加域名,如下图设置。
DNSpod
其中A的两条记录指向的ip地址是github Pages的提供的ip

* 192.30.252.153
* 192.30.252.154

如博客不能登录,有可能是 github 更改了空间服务的 ip 地址,只需要修改即可。
www 指定的记录是你在 github 注册的仓库。(gaojindeng.github.io.)

去 Godaddy 修改 DNS 地址

godaddy
godaddy
将域名服务器更改成 f1g1ns1.dnspod.net 和 f1g1ns2.dnspod.net

过几分钟你就可以访问你的域名了。

用hexo在github上搭建免费个人博客

发表于 2016-07-09 | 分类于 建站相关

GitHub

首先登陆GitHub网站,在github上建立一个repository,名字必须为xxx.github.io,xxx为你的账户名,如下图所示
picture

安装软件

依次下载并安装下面两个软件,一直点击下一步即可:

  • Node.js
  • Git

配置 SSH keys

我们用SSH keys让本地git项目与远程的github建立联系,请看我博客git命令教程

Hexo

在本地新建一个文件夹来存放hexo项目,进入该文件夹右击打开Git Bash here
安装命令:

1
npm i -g hexo

初始化hexo:

1
hexo init

安装插件:

1
hexo install

1
npm install --save hexo-deployer-git

安装后会出现以下目录:
picture
然后生成web项目:

1
hexo g

启动服务器预览效果(http://localhost:4000):

1
hexo s

这还只是本地项目,现在要发布到github上面去,我们需要配置项目目录下的_config.yml文件,打开它找到最后一行,我们把github的配置信息填上去。这里gaojindeng是我的登录名,你只需要将它改成你github的登录名,原封不动地配置好就行了。
我看到好多教程是第二张图那样配置,新版本是不能那样配的。
picture
picture
我们开始发布博客吧!

1
hexo d

稍等一会就可以输入网址xxx.github.io访问你的博客啦~~~

新建博文

1
hexo new "文章题目"

新建页面

1
hexo new page "页面名称"

快捷命令全称

1
2
3
4
hexo g == hexo generate
hexo d == hexo deploy
hexo s == hexo server
hexo n == hexo new

发博文

1
2
3
hexo g

hexo d

其他

头像存放路径: 主题的source 文件夹下 直接/*.jpg 就行

1…34
lightquant

lightquant

你得拼命奔跑,才能留在原地!

36 日志
16 分类
27 标签
GitHub E-Mail
© 2018 lightquant
由 Hexo 强力驱动
|
主题 — NexT.Gemini v6.0.0