forked from saysky/ForestBlog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
forest_blog.sql
276 lines (251 loc) · 226 KB
/
forest_blog.sql
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
Navicat Premium Data Transfer
Source Server : mysql-localhost
Source Server Type : MySQL
Source Server Version : 50719
Source Host : localhost
Source Database : forest_blog
Target Server Type : MySQL
Target Server Version : 50719
File Encoding : utf-8
Date: 10/10/2017 14:59:18 PM
*/
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for `article`
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`article_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`article_user_id` int(10) unsigned DEFAULT '1',
`article_title` varchar(255) DEFAULT NULL,
`article_content` mediumtext,
`article_parent_category_id` int(10) DEFAULT NULL,
`article_child_category_id` int(10) DEFAULT NULL,
`article_tag_ids` varchar(50) DEFAULT NULL,
`article_view_count` int(10) DEFAULT '0',
`article_comment_count` int(5) DEFAULT '0',
`article_like_count` int(5) DEFAULT '0',
`article_post_time` datetime DEFAULT NULL,
`article_update_time` datetime DEFAULT NULL,
`article_is_comment` int(2) unsigned DEFAULT NULL,
`article_status` int(2) unsigned DEFAULT '1',
`article_order` int(2) unsigned DEFAULT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=MyISAM AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `article`
-- ----------------------------
BEGIN;
INSERT INTO `article` VALUES ('1', '1', '[转载]SpringMVC中使用Interceptor拦截器', '<p>SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间。</p><p><br></p><p>一、定义Interceptor实现类</p><p>SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。</p><p><br></p><p>(一)实现HandlerInterceptor接口</p><p>HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。</p><p><br></p><p>(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。</p><p><br></p><p>(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。</p><p><br></p><p>(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。</p><p><br></p><p>下面是一个简单的代码说明:</p><p><br></p><p>import javax.servlet.http.HttpServletRequest;</p><p>import javax.servlet.http.HttpServletResponse;</p><p>import org.springframework.web.servlet.HandlerInterceptor;</p><p>import org.springframework.web.servlet.ModelAndView;</p><p>public class SpringMVCInterceptor implements HandlerInterceptor {</p><p> /** </p><p> * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在 </p><p> * 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在 </p><p> * Controller方法调用之前调用。SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返 </p><p> * 回值为false,当preHandle的返回值为false的时候整个请求就结束了。 </p><p> */</p><p> @Override</p><p> public boolean preHandle(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> return false;</p><p> }</p><p> /** </p><p> * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之 </p><p> * 后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操 </p><p> * 作。这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,这跟Struts2里面的拦截器的执行过程有点像, </p><p> * 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法,Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor </p><p> * 或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。 </p><p> */</p><p> @Override</p><p> public void postHandle(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler,</p><p> ModelAndView modelAndView) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> }</p><p> /** </p><p> * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行, </p><p> * 这个方法的主要作用是用于清理资源的,当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。 </p><p> */</p><p> @Override</p><p> public void afterCompletion(HttpServletRequest request,</p><p> HttpServletResponse response, Object handler, Exception ex)</p><p> throws Exception {</p><p> // TODO Auto-generated method stub </p><p> }</p><p>}</p><p>(二)实现WebRequestInterceptor 接口</p><p>WebRequestInterceptor 中也定义了三个方法,我们也是通过这三个方法来实现拦截的。这三个方法都传递了同一个参数WebRequest ,那么这个WebRequest 是什么呢?这个WebRequest 是Spring 定义的一个接口,它里面的方法定义都基本跟HttpServletRequest 一样,在WebRequestInterceptor 中对WebRequest 进行的所有操作都将同步到HttpServletRequest 中,然后在当前请求中一直传递。</p><p><br></p><p>(1 )preHandle(WebRequest request) 方法。该方法将在请求处理之前进行调用,也就是说会在Controller 方法调用之前被调用。这个方法跟HandlerInterceptor 中的preHandle 是不同的,主要区别在于该方法的返回值是void ,也就是没有返回值,所以我们一般主要用它来进行资源的准备工作,比如我们在使用Hibernate 的时候可以在这个方法中准备一个Hibernate 的Session 对象,然后利用WebRequest 的setAttribute(name, value, scope) 把它放到WebRequest 的属性中。这里可以说说这个setAttribute 方法的第三个参数scope ,该参数是一个Integer 类型的。在WebRequest 的父层接口RequestAttributes 中对它定义了三个常量:</p><p><br></p><p>SCOPE_REQUEST :它的值是0 ,代表只有在request 中可以访问。</p><p><br></p><p>SCOPE_SESSION :它的值是1 ,如果环境允许的话它代表的是一个局部的隔离的session,否则就代表普通的session,并且在该session范围内可以访问。</p><p><br></p><p>SCOPE_GLOBAL_SESSION :它的值是2 ,如果环境允许的话,它代表的是一个全局共享的session,否则就代表普通的session,并且在该session 范围内可以访问。</p><p><br></p><p>(2 )postHandle(WebRequest request, ModelMap model) 方法。该方法将在请求处理之后,也就是在Controller 方法调用之后被调用,但是会在视图返回被渲染之前被调用,所以可以在这个方法里面通过改变数据模型ModelMap 来改变数据的展示。该方法有两个参数,WebRequest 对象是用于传递整个请求数据的,比如在preHandle 中准备的数据都可以通过WebRequest 来传递和访问;ModelMap 就是Controller 处理之后返回的Model 对象,我们可以通过改变它的属性来改变返回的Model 模型。</p><p><br></p><p>(3 )afterCompletion(WebRequest request, Exception ex) 方法。该方法会在整个请求处理完成,也就是在视图返回并被渲染之后执行。所以在该方法中可以进行资源的释放操作。而WebRequest 参数就可以把我们在preHandle 中准备的资源传递到这里进行释放。Exception 参数表示的是当前请求的异常对象,如果在Controller中抛出的异常已经被Spring 的异常处理器给处理了的话,那么这个异常对象就是是null 。</p><p><br></p><p> </p><p><br></p><p>下面是一个简单的代码说明:</p><p><br></p><p>import org.springframework.ui.ModelMap;</p><p>import org.springframework.web.context.request.WebRequest;</p><p>import org.springframework.web.context.request.WebRequestInterceptor;</p><p>public class AllInterceptor implements WebRequestInterceptor {</p><p> /** </p><p> * 在请求处理之前执行,该方法主要是用于准备资源数据的,然后可以把它们当做请求属性放到WebRequest中 </p><p> */</p><p> @Override</p><p> public void preHandle(WebRequest request) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> System.out.println(\"AllInterceptor...............................\");</p><p> request.setAttribute(\"request\", \"request\", WebRequest.SCOPE_REQUEST);//这个是放到request范围内的,所以只能在当前请求中的request中获取到 </p><p> request.setAttribute(\"session\", \"session\", WebRequest.SCOPE_SESSION);//这个是放到session范围内的,如果环境允许的话它只能在局部的隔离的会话中访问,否则就是在普通的当前会话中可以访问 </p><p> request.setAttribute(\"globalSession\", \"globalSession\", WebRequest.SCOPE_GLOBAL_SESSION);//如果环境允许的话,它能在全局共享的会话中访问,否则就是在普通的当前会话中访问 </p><p> }</p><p> /** </p><p> * 该方法将在Controller执行之后,返回视图之前执行,ModelMap表示请求Controller处理之后返回的Model对象,所以可以在 </p><p> * 这个方法中修改ModelMap的属性,从而达到改变返回的模型的效果。 </p><p> */</p><p> @Override</p><p> public void postHandle(WebRequest request, ModelMap map) throws Exception {</p><p> // TODO Auto-generated method stub </p><p> for (String key:map.keySet())</p><p> System.out.println(key + \"-------------------------\");;</p><p> map.put(\"name3\", \"value3\");</p><p> map.put(\"name1\", \"name1\");</p><p> }</p><p> /** </p><p> * 该方法将在整个请求完成之后,也就是说在视图渲染之后进行调用,主要用于进行一些资源的释放 </p><p> */</p><p> @Override</p><p> public void afterCompletion(WebRequest request, Exception exception)</p><p> throws Exception {</p><p> // TODO Auto-generated method stub </p><p> System.out.println(exception + \"-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=\");</p><p> }</p><p>}</p><p><br></p><p> 二、把定义的拦截器类加到SpringMVC的拦截体系中</p><p>1.在SpringMVC的配置文件中加上支持MVC的schema</p><p><br></p><p>xmlns:mvc=\"http://www.springframework.org/schema/mvc\"</p><p>xsi:schemaLocation=\" http://www.springframework.org/schema/mvc</p><p> http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd\"</p><p>下面是我的声明示例:</p><p><br></p><p><br></p><p><br></p><p>这样在SpringMVC的配置文件中就可以使用mvc标签了,mvc标签中有一个mvc:interceptors是用于声明SpringMVC的拦截器的。</p><p><br></p><p> </p><p><br></p><p>(二)使用mvc:interceptors标签来声明需要加入到SpringMVC拦截器链中的拦截器</p><p><br></p><p><br></p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p><br></p><p><br></p><p>由上面的示例可以看出可以利用mvc:interceptors标签声明一系列的拦截器,然后它们就可以形成一个拦截器链,拦截器的执行顺序是按声明的先后顺序执行的,先声明的拦截器中的preHandle方法会先执行,然而它的postHandle方法和afterCompletion方法却会后执行。</p><p><br></p><p>在mvc:interceptors标签下声明interceptor主要有两种方式:</p><p><br></p><p>(1)直接定义一个Interceptor实现类的bean对象。使用这种方式声明的Interceptor拦截器将会对所有的请求进行拦截。</p><p><br></p><p>(2)使用mvc:interceptor标签进行声明。使用这种方式进行声明的Interceptor可以通过mvc:mapping子标签来定义需要进行拦截的请求路径。</p><p><br></p><p>经过上述两步之后,定义的拦截器就会发生作用对特定的请求进行拦截了。</p><p><br></p><p><br></p><p><br></p>', '1', '9', '12', '2', '0', '0', '2017-10-06 23:54:18', '2017-10-07 15:31:36', '1', '1', '1'), ('2', '1', 'springmvc 表单中文乱码解决方案', '<p>基本上通过在 web.xml 了配置拦截器就可以解决。</p><p>这里需要注意的是,最好把这段代码放在web.xml中开头的位置,因为拦截有顺序,如果放在后面的话容易拦截不到。</p><p>拦截器代码如下</p><p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span><span class=\"comments\"><!--post乱码过滤器--></span><span> </span></span></li><li class=\"\"><span><span class=\"comments\"><!-- 配置springMVC编码过滤器 --></span><span> </span></span></li><li class=\"alt\"><span><span class=\"tag\"><</span><span class=\"tag-name\">filter</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span>CharacterEncodingFilter</span><span class=\"tag\"></</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-class</span><span class=\"tag\">></span><span>org.springframework.web.filter.CharacterEncodingFilter</span><span class=\"tag\"></</span><span class=\"tag-name\">filter-class</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"comments\"><!-- 设置过滤器中的属性值 --></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span>encoding</span><span class=\"tag\"></</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span>UTF-8</span><span class=\"tag\"></</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"></</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"comments\"><!-- 启动过滤器 --></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span>forceEncoding</span><span class=\"tag\"></</span><span class=\"tag-name\">param-name</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span>true</span><span class=\"tag\"></</span><span class=\"tag-name\">param-value</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"></</span><span class=\"tag-name\">init-param</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span><span class=\"tag\"></</span><span class=\"tag-name\">filter</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span><span class=\"comments\"><!-- 过滤所有请求 --></span><span> </span></span></li><li class=\"\"><span><span class=\"tag\"><</span><span class=\"tag-name\">filter-mapping</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span>CharacterEncodingFilter</span><span class=\"tag\"></</span><span class=\"tag-name\">filter-name</span><span class=\"tag\">></span><span> </span></span></li><li class=\"\"><span> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span><span>/*</span><span class=\"tag\"></</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span><span> </span></span></li><li class=\"alt\"><span><span class=\"tag\"></</span><span class=\"tag-name\">filter-mapping</span><span class=\"tag\">></span><span> </span></span></li></ol></div></div><p><br></p><p>顺便再补充其他的几个可能原因。</p></p><p>1、数据库和数据表不是 utf-8 编码</p><p>就在前几天,我遇到的问题正是这个。当时是刚从 windows 搬到 mac。也是在提交 post 表单的时候,中文一直是乱码,后台百度发现,原来是 navicat 的原因。就是在新建 数据库连接(注意是连接),不能选择 utf-8,应该选择默认的自动。这个地方很坑人。</p><p>数据库和数据表当然是 utf-8,一般这种情况很少出错。</p><p> </p><p>2、修改 Tomcat 的 server.xml 文件,添加 utf-8 编码</p><p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span><Connector port=</span><span class=\"string\">\"8080\"</span><span> protocol=</span><span class=\"string\">\"HTTP/1.1\"</span><span> </span></span></li><li class=\"\"><span> connectionTimeout=<span class=\"string\">\"20000\"</span><span> </span></span></li><li class=\"alt\"><span> redirectPort=<span class=\"string\">\"8443\"</span><span> URIEncoding=</span><span class=\"string\">\"UTF-8\"</span><span> </span></span></li><li class=\"\"><span> useBodyEncodingForURI=<span class=\"string\">\"true\"</span><span> /> </span></span></li></ol></div></div><br></p><p>3、注意你的 IDE (如Eclipse,IntelliJ IDEA)的 jsp 文件编码,一般在右下角可以看出来,通常我们也要把默认的编码设置为 utf-8。</p><p> </p><p>4、还有一种方法就是 直接对接收到的数据编码转换,我感觉有点麻烦,所以不是很喜欢</p><p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span>String name=</span><span class=\"keyword\">new</span><span> String((user.getUname()).getBytes(</span><span class=\"string\">\"ISO-8859-1\"</span><span>),</span><span class=\"string\">\"utf8\"</span><span>); </span></span></li></ol></div></div><p><span>总结:一般来说,第一种拦截器方法是可用的,要注意的是要把拦截器代码放到 web.xml 头部,防止拦截不到,还有表单一定要 post 方式提交。</span></p></p>', '1', '9', '12', '2', '0', '0', '2017-10-07 12:12:42', '2017-10-07 15:34:10', '1', '1', '1'), ('4', '1', '[转载]HTTP的幂等性', '<div id=\"header\"><h2>理解HTTP幂等性</h2></div><div id=\"post_detail\"><div class=\"post\"><div class=\"postText\"><div id=\"cnblogs_post_body\"><p>基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API。为什么Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看与 Java 相关的文章\" target=\"_blank\">Java</a>script、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看与 Java 相关的文章\" target=\"_blank\">Java</a>语言并不意味着高质量的<a href=\"https://liuyanzhao.com/tag/java/\" title=\"查看与 Java 相关的文章\" target=\"_blank\">Java</a>程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。</p><h2>幂等性定义</h2><p>本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:</p><blockquote><p>Methods can also have the property of \"idempotence\" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.</p></blockquote><p>从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。</p><h2>分布式事务 vs 幂等设计</h2><p>为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:</p><pre><code>bool withdraw(account_id, amount)\r\n</code></pre><p>withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:</p><p><img src=\"/uploads/2017/10/20171007153621950.png\" alt=\"20171007153621950.png\"><br></p><p>图1</p><p>这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。</p><p>另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:</p><pre><code>int create_ticket() \r\nbool idempotent_withdraw(ticket_id, account_id, amount)\r\n</code></pre><p>create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。</p><p>基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图2所示:</p><p><img src=\"/uploads/2017/10/20171007153648208.png\" alt=\"20171007153648208.png\"><br></p><div id=\"cnblogs_post_body\"><p>图2</p><p>和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。</p><h2>HTTP的幂等性</h2><p>HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。</p><p>HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。</p><p>HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。</p><p>比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:</p><blockquote><p>The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.</p><p>The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.</p></blockquote><p>POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。</p><p>在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。</p><h2>总结</h2><p>上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,如果要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者可以从Wikipedia上进一步了解。</p><h2>参考</h2><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html\">RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions</a></p><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://devhawk.net/2007/11/09/the-importance-of-idempotence/\">The Importance of Idempotence</a></p><p><a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://stackoverflow.com/questions/630453/put-vs-post-in-rest\">Stackoverflow - PUT vs POST in REST</a></p></div><p> </p><p> </p><p>原文地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html</a></p></div></div></div></div>', '10', '14', '6', '0', '0', '0', '2017-10-07 15:37:20', '2017-10-07 15:37:20', '1', '1', '1'), ('3', '1', '使用rapid-framework继承jsp页面', '<p>对于多张网页页面,许多部分都是相同的,应该继承同一个页面,该页面是所有页面的父页面。<br></p><p>后来搜了一下找到一个<code>rapid-framework</code>的东西,由于我使用的是<code>maven</code>,所以引入很简单。</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">dependency</span><span class=\"tag\">></span> </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">groupId</span><span class=\"tag\">></span>com.googlecode.rapid-framework<span class=\"tag\"><!--</span--><span class=\"tag-name\">groupId</span><span class=\"tag\">></span> </span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span>rapid-core<span class=\"tag\"><!--</span--><span class=\"tag-name\">artifactId</span><span class=\"tag\">></span> </span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">version</span><span class=\"tag\">></span>4.0.5<span class=\"tag\"><!--</span--><span class=\"tag-name\">version</span><span class=\"tag\">></span> </span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">dependency</span><span class=\"tag\">></span> </span></li></ol></div></div><p>父页面</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\">... </li><li class=\"\"><span class=\"tag\"><</span>%@ taglib <span class=\"attribute\">prefix</span>=<span class=\"attribute-value\">\"rapid\"</span> <span class=\"attribute\">uri</span>=<span class=\"attribute-value\">\"http://www.rapid-framework.org.cn/rapid\"</span> %<span class=\"tag\">></span> </li><li class=\"alt\">... </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">body</span><span class=\"tag\">></span> </li><li class=\"alt\"> <span class=\"comments\"><!-- 正文 --></span> </li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">rapid:block</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"content\"</span><span class=\"tag\">></span> </li><li class=\"alt\"> 123 </li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">rapid:block</span><span class=\"tag\">></span> </span></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">body</span><span class=\"tag\">></span> </span></li></ol></div></div><p></p><p></p><ul></ul><p> <code><rapid:block name=\"content\"></rapid:block></code>定义叫做<code>content</code>的一块,该部分可以让子页面重写。</p><p></p><p>子页面</p><p></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-xml\"><li class=\"alt\"><span class=\"tag\"><</span>%@ page <span class=\"attribute\">contentType</span>=<span class=\"attribute-value\">\"text/html;charset=UTF-8\"</span> <span class=\"attribute\">language</span>=<span class=\"attribute-value\">\"java\"</span> %<span class=\"tag\">></span> </li><li class=\"\"><span class=\"tag\"><</span>%@ taglib <span class=\"attribute\">prefix</span>=<span class=\"attribute-value\">\"rapid\"</span> <span class=\"attribute\">uri</span>=<span class=\"attribute-value\">\"http://www.rapid-framework.org.cn/rapid\"</span> %<span class=\"tag\">></span> </li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">rapid:override</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"content\"</span><span class=\"tag\">></span> </li><li class=\"\"> 这是内容 </li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">rapid:override</span><span class=\"tag\">></span> </span></li><li class=\"\"><span class=\"tag\"><</span>%@ include <span class=\"attribute\">file</span>=<span class=\"attribute-value\">\"base.jsp\"</span>%<span class=\"tag\">></span> </li></ol></div></div><p></p><p></p><li> <%@ include file=\"base.jsp\"%>引入父页面</li><p></p><li>重写父页面中叫做content的部分。</li><p></p><li>访问子页面,父页面内部的元素不会显示,代替的是子页面重写的内容。</li>', '1', '8', '18', '0', '0', '0', '2017-10-07 15:30:17', '2017-10-07 15:34:45', '1', '1', '1'), ('5', '1', 'JDBC常用API和使用', '<h2>一、JDBC 常用 API</h2><p><strong>1、Connection 接口</strong></p><table width=\"695\" class=\"layui-table\"><tbody><tr><td>方法名称</td><td>功能描述</td></tr><tr><td>getMetaData()</td><td>该方法用于返回数据库的元数据的 DatabaseMetaData 对象</td></tr><tr><td>createStatement</td><td>用于创建一个 Statement 对象来将 SQL 语句发送到数据库</td></tr><tr><td>preparedStatement(String sql)</td><td>用于创建一个 PreparedStatement 对象来将参数化的SQL语句发送到数据库</td></tr><tr><td>prepareCall(String sql)</td><td>用于创建一个 CallableStatement 对象来调用数据库存储过程</td></tr></tbody></table><p><strong>2、Statement 接口</strong></p><table width=\"696\" class=\"layui-table\"><tbody><tr><td>方法名称</td><td>功能描述</td></tr><tr><td>boolean execute(String sql)</td><td>用于执行各种 SQL 语句,该方法返回一个 boolean 类型的值。如果为 true,表示所执行的 SQL 语句具备查询结果,可通过 Statement 的getResultSet() 方法查询结果</td></tr><tr><td>int executeUpdate(String sql)</td><td>用于执行 SQL 中的 insert、update 和 delete 语句,该方法返回一个 int 类型的值,表示影响数据库中的行数</td></tr><tr><td>ResultSet executeQuery(String sql)</td><td>用于执行 SQL 中的 select 语句(查询,遍历),该方法返回一个表示查询结果的 ResultSet 对象</td></tr></tbody></table><p><strong> <span>execute是executeQuery和executeUpdate的综合.</span></strong></p><p><strong><span>通常我们没有必要使用execute方法来执行SQL语句,而是使用 executeQuery 或 executeUpdate 更适合。</span></strong></p><p>具体可参考:<a href=\"https://liuyanzhao.com/5278.html\" target=\"_blank\" rel=\"noopener noreferrer\">execute、executeUpdate、executeQuery三者的区别</a></p><p><strong>3、PreparedStatement 接口</strong></p><table width=\"695\" class=\"layui-table\"><tbody><tr><td>方法名称</td><td>功能描述</td></tr><tr><td>executeUpdate()</td><td>在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 DML 语句,或者无返回内容的 SQL 语句,比如 DDL 语句</td></tr><tr><td>executeQuery()</td><td>在此 PreparedStatement 对象中执行 SQL 语句,该方法返回的是 ResultSet 对象</td></tr><tr><td>setInt(int parameterIndex, int x)</td><td>将指定的参数设置为 int 值</td></tr><tr><td>setFloat(int parameterIndex, float x)</td><td>将指定的参数设置为 Float 值</td></tr><tr><td>setString(int parameterIndex, String x)</td><td>将指定参数设置的给定的 Date 值</td></tr><tr><td>setDate(int parameterIndex, Date x)</td><td>将指定参数设置给定的 Date 值</td></tr><tr><td>addBatch()</td><td>将一组参数添加到此 PreparedStatement 对象的批处理命令中</td></tr><tr><td>setCharacterStream(parameterIndex, reader, length)</td><td>将指定的输入流写入数据库的文本字段</td></tr><tr><td>setBinaryStream(parameterIndex, x, length)</td><td>将二进制的输入流数据写入到二进制的字段中</td></tr></tbody></table><p>DML 语句:SELECT、UPDATE、INSERT、DELETE</p><p>DLL 语句:CREATE DROP ALERT</p><p>具体参考: <a href=\"https://liuyanzhao.com/5283.html\" target=\"_blank\" rel=\"noopener noreferrer\">sql语句分为三类(DML,DDL,DCL)-介绍</a></p><p>4、ResultSet 接口</p><table class=\"layui-table\"><tbody><tr><td>getString(int columnIndex)</td><td>用于获取 指定字段的 String 类型的值,参数 columnIndex 代表字段的索引</td></tr><tr><td>getString(String columnName)</td><td> 用于获取指定字段的 String 类型的值,参数 columnIndex 代表字段名称</td></tr><tr><td>getInt(int columnIndex)</td><td> 用于获取指定字段的 int 类型的值,参数 columnIndex 代表字段的索引</td></tr><tr><td>getInt(String columnName)</td><td> 用于获取指定字段的 int 类型的值,参数 columnIndex 代表字段名称</td></tr><tr><td>getDate(int columnIndex)</td><td> 用于获取指定字段的 Date类型的值,参数 columnIndex 代表字段索引</td></tr><tr><td>getDate(String columnName)</td><td> 用于获取指定字段的 Date类型的值,参数 columnIndex 代表字段名称</td></tr><tr><td>next()</td><td> 将游标从当前位置移到下一位置</td></tr><tr><td>absolute(int row)</td><td>将游标移到此 ResultSet 对象的指定行</td></tr><tr><td>afterLast()</td><td>将游标移动到此 ResultSet 对象的末尾,即最后一行之后</td></tr><tr><td>beforeFirst()</td><td>将游标移动到此 ResultSet 对象开头,即第一行之前</td></tr><tr><td>previous()</td><td>将游标移动到此 ResultSet 对象的上一行</td></tr><tr><td>last()</td><td>将游标移动到此 Result 对象的最后一行</td></tr></tbody></table><h2>二、案例</h2><p><strong>1、往数据库里添加数据</strong></p><p>① 数据表结构如下</p><p><img src=\"/uploads/2017/10/2017100715402014.png\" alt=\"2017100715402014.png\"><br></p><p><span>② 代码如下</span></p><p><span></span></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span class=\"keyword\">package</span><span> com.liuyanzhao; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.Connection; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.Date; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.DriverManager; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.PreparedStatement; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.SQLException; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.text.ParseException; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.text.SimpleDateFormat; </span></span></li><li class=\"alt\"><span><span class=\"comment\">/*</span> </span></li><li class=\"\"><span><span class=\"comment\"> * @author LiuYanzhao</span> </span></li><li class=\"alt\"><span><span class=\"comment\"> */</span><span> </span></span></li><li class=\"\"><span><span class=\"keyword\">public</span><span> </span><span class=\"keyword\">class</span><span> Demo1 { </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String URL = </span><span class=\"string\">\"jdbc:mysql://127.0.0.1:3306/jdbc_study?useUnicode=true&characterEncoding=utf8\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String USER = </span><span class=\"string\">\"root\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String PASSWORD = </span><span class=\"string\">\"\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> Connection conn = </span><span class=\"keyword\">null</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">void</span><span> main(String[] args) </span><span class=\"keyword\">throws</span><span> ClassNotFoundException, SQLException, ParseException { </span></span></li><li class=\"\"><span> <span class=\"comment\">//1、加载驱动,需要提前把 jar 包添加到 classpath 中</span><span> </span></span></li><li class=\"alt\"><span> Class.forName(<span class=\"string\">\"com.mysql.jdbc.Driver\"</span><span>); </span></span></li><li class=\"\"><span> <span class=\"comment\">//2、创建应用程序与数据库连接的 Connection 对象</span><span> </span></span></li><li class=\"alt\"><span> conn = DriverManager.getConnection(URL, USER, PASSWORD); </span></li><li class=\"\"><span> <span class=\"comment\">//3、要执行的 sql 语句:name,password,email,status通过占位符填数,create_date 自动为当前时间</span><span> </span></span></li><li class=\"alt\"><span> String sql = <span class=\"string\">\" INSERT INTO users\"</span><span>+ </span></span></li><li class=\"\"><span> <span class=\"string\">\"(name,password,birthday,email,create_date,status) \"</span><span>+ </span></span></li><li class=\"alt\"><span> <span class=\"string\">\"VALUES(\"</span><span>+ </span></span></li><li class=\"\"><span> <span class=\"string\">\"?,?,?,?,current_date(),?)\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//4、创建执行 SQL 语句的 PreparedStatement 对象</span><span> </span></span></li><li class=\"\"><span> PreparedStatement ptmt = conn.prepareStatement(sql); </span></li><li class=\"alt\"><span> ptmt.setString(<span class=\"number\">1</span><span>, </span><span class=\"string\">\"小美\"</span><span>); </span></span></li><li class=\"\"><span> ptmt.setString(<span class=\"number\">2</span><span>, </span><span class=\"string\">\"123456\"</span><span>); </span></span></li><li class=\"alt\"><span> ptmt.setDate(<span class=\"number\">3</span><span>,</span><span class=\"keyword\">new</span><span> Date((</span><span class=\"keyword\">new</span><span> SimpleDateFormat(</span><span class=\"string\">\"yyyy-MM-dd\"</span><span>).parse(</span><span class=\"string\">\"2011-10-1\"</span><span>)).getTime()) ); </span></span></li><li class=\"\"><span> ptmt.setString(<span class=\"number\">4</span><span>, </span><span class=\"string\">\"xiaomei@126.com\"</span><span>); </span></span></li><li class=\"alt\"><span> ptmt.setInt(<span class=\"number\">5</span><span>, </span><span class=\"number\">1</span><span>); </span></span></li><li class=\"\"><span> <span class=\"comment\">//5、真正执行 sql 语句,并返回影响的行数</span><span> </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">int</span><span> x = ptmt.executeUpdate(); </span></span></li><li class=\"\"><span> System.out.println(<span class=\"string\">\"影响行数:\"</span><span> + x); </span><span class=\"comment\">//返回1</span><span> </span></span></li><li class=\"alt\"><span> } </span></li><li class=\"\"><span>} </span></li></ol></div></div><br><p></p><p>③运行结果</p><p>上面的操作,将在 jdbc_study 数据库的 users 表中添加一条记录,终端显示 1</p><p><strong>2、查询(打印)数据库信息</strong></p><p>①数据表如下</p><p><img src=\"/uploads/2017/10/20171007154127663.png\" alt=\"20171007154127663.png\"><br></p><p><span>②代码如下</span></p><p><span></span></p><div><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol start=\"1\" class=\"dp-j\"><li class=\"alt\"><span><span class=\"keyword\">package</span><span> com.liuyanzhao; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.Connection; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.Date; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.DriverManager; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.PreparedStatement; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.sql.ResultSet; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.sql.SQLException; </span></span></li><li class=\"\"><span><span class=\"keyword\">import</span><span> java.text.ParseException; </span></span></li><li class=\"alt\"><span><span class=\"keyword\">import</span><span> java.text.SimpleDateFormat; </span></span></li><li class=\"\"><span><span class=\"comment\">/*</span> </span></li><li class=\"alt\"><span><span class=\"comment\"> * @author LiuYanzhao</span> </span></li><li class=\"\"><span><span class=\"comment\"> */</span><span> </span></span></li><li class=\"alt\"><span><span class=\"keyword\">public</span><span> </span><span class=\"keyword\">class</span><span> Demo2 { </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String URL = </span><span class=\"string\">\"jdbc:mysql://127.0.0.1:3306/jdbc_study?useUnicode=true&characterEncoding=utf8\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String USER = </span><span class=\"string\">\"root\"</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">private</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">final</span><span> String PASSWORD = </span><span class=\"string\">\"\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> Connection conn = </span><span class=\"keyword\">null</span><span>; </span></span></li><li class=\"\"><span> <span class=\"keyword\">public</span><span> </span><span class=\"keyword\">static</span><span> </span><span class=\"keyword\">void</span><span> main(String[] args) </span><span class=\"keyword\">throws</span><span> ClassNotFoundException, SQLException, ParseException { </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//1、加载驱动,需要提前把 jar 包添加到 classpath 中</span><span> </span></span></li><li class=\"\"><span> Class.forName(<span class=\"string\">\"com.mysql.jdbc.Driver\"</span><span>); </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//2、创建应用程序与数据库连接的 Connection 对象</span><span> </span></span></li><li class=\"\"><span> conn = DriverManager.getConnection(URL, USER, PASSWORD); </span></li><li class=\"alt\"><span> <span class=\"comment\">//3、要执行的 sql 语句:name,password,email,satic 通过占位符填数,create_date 自动为当前时间</span><span> </span></span></li><li class=\"\"><span> String sql = <span class=\"string\">\" SELECT * FROM users\"</span><span>; </span></span></li><li class=\"alt\"><span> <span class=\"comment\">//4、创建执行 SQL 语句的 PreparedStatement 对象</span><span> </span></span></li><li class=\"\"><span> PreparedStatement ptmt = conn.prepareStatement(sql); </span></li><li class=\"alt\"><span> <span class=\"comment\">//5、真正执行 sql 语句,并返回影响的 ResultSet</span><span> </span></span></li><li class=\"\"><span> ResultSet rs = ptmt.executeQuery(); </span></li><li class=\"alt\"><span> <span class=\"comment\">//6、打印 ResultSet 数据集</span><span> </span></span></li><li class=\"\"><span> <span class=\"keyword\">while</span><span>(rs.next()) { </span></span></li><li class=\"alt\"><span> System.out.print(rs.getInt(<span class=\"string\">\"id\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getString(<span class=\"string\">\"name\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getString(<span class=\"string\">\"password\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getDate(<span class=\"string\">\"birthday\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getString(<span class=\"string\">\"email\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.print(rs.getDate(<span class=\"string\">\"create_date\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"alt\"><span> System.out.print(rs.getInt(<span class=\"string\">\"status\"</span><span>)+</span><span class=\"string\">\" \"</span><span>); </span></span></li><li class=\"\"><span> System.out.println(); </span></li><li class=\"alt\"><span> } </span></li><li class=\"\"><span> } </span></li><li class=\"alt\"><span>} </span></li></ol></div></div><p>③ 运行结果</p><p></p><p>控制台上可以看到如下界面</p><p><img src=\"/uploads/2017/10/20171007154222212.jpg\" alt=\"20171007154222212.jpg\"><br></p>', '1', '8', '20', '0', '0', '0', '2017-10-07 15:42:43', '2017-10-07 15:43:46', '1', '1', '1'), ('6', '1', 'Hibernate 简单的CURD操作', '<h2>一、单表操作 CURD 实例</h2><ul><li>save</li><li>update</li><li>delete</li><li>get/load (查询单个记录)</li></ul><p> </p><h2>二、代码实现</h2><p><strong>StudentTest.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testSaveStudnets() {</li><li class=\"alt\"> <span class=\"comment\">//生成学生对象</span></li><li class=\"\"> Student s = <span class=\"keyword\">new</span> Student();</li><li class=\"alt\"> s.setName(<span class=\"string\">\"陶渊明\"</span>);</li><li class=\"\"> s.setSex(<span class=\"number\">1</span>);</li><li class=\"alt\"> s.setBirthday(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> Address address = <span class=\"keyword\">new</span> Address(<span class=\"string\">\"332000\"</span>,<span class=\"string\">\"13512345678\"</span>,<span class=\"string\">\"江西九江\"</span>);</li><li class=\"alt\"> s.setAddress(address);</li><li class=\"\"> session.save(s);<span class=\"comment\">//保存对象进入数据库</span></li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testGetStudents() {</li><li class=\"alt\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> System.out.println(s);</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testLoadStudents() {</li><li class=\"alt\"> Student s = (Student) session.load(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> System.out.println(s);</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testUpdateStudents() {</li><li class=\"alt\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> s.setName(<span class=\"string\">\"五柳先生\"</span>);</li><li class=\"alt\"> session.update(s);</li><li class=\"\">}</li><li class=\"alt\"></li><li class=\"\"><span class=\"annotation\">@Test</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testDeleteStudents() {</li><li class=\"\"> Student s = (Student) session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"alt\"> session.delete(s);</li><li class=\"\">}</li></ol></div><p> </p><h2>三、get 和 load 的区别</h2><p><strong>区别一、</strong></p><ul><li>不考虑缓存的情况下,get 方法会在调用之后,立即向数据库发送 sql 语句,返回持久化对象。</li><li>load 方法会在调用后返回一个持久化对象。该代理对象只保留了实体对象的 id,直到使用实体对象的非主键属性时才发出 sql 语句。</li></ul><p><strong>区别二、</strong></p><ul><li>查询数据库中不存在的数据时,get 方法返回 null 。</li><li>load 方法返回异常 org.hibernate.ObjectNotFoundException</li></ul><p>p</p><div><br></div>', '1', '9', '21', '0', '0', '0', '2017-10-07 15:49:54', '2017-10-07 15:49:54', '1', '1', '1'), ('7', '1', 'Hibernate 基本类型', '<p>这里介绍几个特殊的 <a href=\"https://liuyanzhao.com/tag/hibernate/\" title=\"查看与 Hibernate 相关的文章\" target=\"_blank\">Hibernate</a> 类型和属性</p><h2>一、日期类型</h2><p>我们的 Student 类有一个成员变量 birthday</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li></ol></div><p>在我们的 Studnet.hbm.xml 对应的是自动生成的 属性</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"birthday\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"java.util.Date\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">column</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"BIRTHDAY\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">property</span><span class=\"tag\">></span></li></ol></div><p>type 表示该字段的类型,不同的类型,会让数据表的字段类型也不同</p><table class=\"layui-table\"><tbody><tr><td>type(映射类型)</td><td>描述</td></tr><tr><td>java.util.Date</td><td>年月日时分秒(2017-07-25 18:20:12)</td></tr><tr><td>date</td><td>年月日(2017-07-25)</td></tr><tr><td>time</td><td>时分秒(18:20:12)</td></tr><tr><td>timestamp</td><td>年月日时分秒(2017-07-25 18:20:12)</td></tr></tbody></table><h2>二、对象类型</h2><p>我们这里使用使用 Blob 类型存照片</p><p>1、Student 类中 成员变量如下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sid;<span class=\"comment\">//学号</span></li><li class=\"\"><span class=\"keyword\">private</span> String name;<span class=\"comment\">//姓名</span></li><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sex;<span class=\"comment\">//性别</span></li><li class=\"\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li><li class=\"alt\"><span class=\"keyword\">private</span> String address;<span class=\"comment\">//地址</span></li><li class=\"\"><span class=\"keyword\">private</span> Blob picture;<span class=\"comment\">//照片 </span></li></ol></div><p>2、然后删除原来的 Student.hbm.xml 文件,重新生成</p><p>3、在测试类添加 testWriteBlob方法</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testWriteBlob() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> Student s = <span class=\"keyword\">new</span> Student(<span class=\"number\">1</span>,<span class=\"string\">\"杜甫\"</span>,<span class=\"number\">1</span>,<span class=\"keyword\">new</span> Date(),<span class=\"string\">\"四川\"</span>);</li><li class=\"\"> <span class=\"comment\">//先获得照片文件</span></li><li class=\"alt\"> File f = <span class=\"keyword\">new</span> File(<span class=\"string\">\"d:\"</span>+File.separator+<span class=\"string\">\"boy.jpg\"</span>);</li><li class=\"\"> <span class=\"comment\">//获得照片文件的输入流</span></li><li class=\"alt\"> InputStream input = <span class=\"keyword\">new</span> FileInputStream(f);</li><li class=\"\"> <span class=\"comment\">//创建Blob对象</span></li><li class=\"alt\"> Blob image = <a href=\"https://liuyanzhao.com/tag/hibernate/\" title=\"查看与 Hibernate 相关的文章\" target=\"_blank\">Hibernate</a>.getLobCreator(session).createBlob(input,input.available());</li><li class=\"\"> <span class=\"comment\">//设置照片属性</span></li><li class=\"alt\"> s.setPicture(image);</li><li class=\"\"> session.save(s);</li><li class=\"alt\">}</li></ol></div><p>注意:这里 Blob 是 java.sql.Blob 包下</p><p>4、然后使用 Junit Test 运行 testWriteBlob 方法</p><p><img src=\"/uploads/2017/10/2017100715505630.png\" alt=\"2017100715505630.png\"><br></p><p>5、为了证明是否真的是写入数据库中,我们重新把照片读出来</p><p>在测试类中添加 testReadBlob 方法</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testReadBlob() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> Student s = (Student)session.get(Student.<span class=\"keyword\">class</span>, <span class=\"number\">1</span>);</li><li class=\"\"> <span class=\"comment\">//获得Blob对象</span></li><li class=\"alt\"> Blob image = s.getPicture();</li><li class=\"\"> <span class=\"comment\">//获得照片的输入流</span></li><li class=\"alt\"> InputStream input = image.getBinaryStream();</li><li class=\"\"> <span class=\"comment\">//创建输出流</span></li><li class=\"alt\"> File f = <span class=\"keyword\">new</span> File(<span class=\"string\">\"d:\"</span>+File.separator+<span class=\"string\">\"dest.jpg\"</span>);</li><li class=\"\"> <span class=\"comment\">//获得输出流</span></li><li class=\"alt\"> OutputStream output = <span class=\"keyword\">new</span> FileOutputStream(f);</li><li class=\"\"> <span class=\"comment\">//创建缓冲区</span></li><li class=\"alt\"> <span class=\"keyword\">byte</span>[] buff = <span class=\"keyword\">new</span> <span class=\"keyword\">byte</span>[input.available()];</li><li class=\"\"> input.read(buff);</li><li class=\"alt\"> output.write(buff);</li><li class=\"\"> input.close();</li><li class=\"alt\"> output.close();</li><li class=\"\">}</li></ol></div><p>6、使用 Junit Test 运行 testReadBlob 方法</p><p>我们可以看到 D 盘,已经生成了一张新照片,dest.jpg</p><p> </p><p><img src=\"/uploads/2017/10/20171007155038568.png\" alt=\"20171007155038568.png\"><br></p><h2>三、组件属性</h2><p>实体类中某个属性属于用户自定义的类的对象,下面我们通过一个例子来解释</p><p>1、实体类 Student.java 成员变量如下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sid;<span class=\"comment\">//学号</span></li><li class=\"\"><span class=\"keyword\">private</span> String name;<span class=\"comment\">//姓名</span></li><li class=\"alt\"><span class=\"keyword\">private</span> <span class=\"keyword\">int</span> sex;<span class=\"comment\">//性别</span></li><li class=\"\"><span class=\"keyword\">private</span> Date birthday;<span class=\"comment\">//出生日期</span></li><li class=\"alt\"><span class=\"comment\">//private String address;//地址</span></li><li class=\"\"><span class=\"keyword\">private</span> Blob picture;<span class=\"comment\">//照片 </span></li><li class=\"alt\"><span class=\"keyword\">private</span> Address address; <span class=\"comment\">//地址</span></li></ol></div><p>我们这里把之前的 String 类型的 address 改成 Address 类型</p><p>2、Address 类 部分代码如下</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">private</span> String postcode;<span class=\"comment\">//邮编</span></li><li class=\"\"><span class=\"keyword\">private</span> String phone;<span class=\"comment\">//手机</span></li><li class=\"alt\"><span class=\"keyword\">private</span> String address;<span class=\"comment\">//地址</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> Address(String postcode, String phone, String address) {</li><li class=\"\"> <span class=\"keyword\">this</span>.postcode = postcode;</li><li class=\"alt\"> <span class=\"keyword\">this</span>.phone = phone;</li><li class=\"\"> <span class=\"keyword\">this</span>.address = address;</li><li class=\"alt\">}</li></ol></div><p>3、修改 Student.hbm.xml</p><p>将之前的</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"java.lang.String\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">column</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"ADDRESS\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">property</span><span class=\"tag\">></span></li></ol></div><p>改成</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">component</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">class</span>=<span class=\"attribute-value\">\"Address\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"postcode\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"POSTCODE\"</span><span class=\"tag\">/></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"phone\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"PHONE\"</span><span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">property</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"ADDRESS\"</span><span class=\"tag\">/></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">component</span><span class=\"tag\">></span></li></ol></div><p>注意:单词不要打错</p><p>4、修改 测试类 testSaveStudent 代码</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testSaveStudnets() {</li><li class=\"alt\"> <span class=\"comment\">//生成学生对象</span></li><li class=\"\"> Student s = <span class=\"keyword\">new</span> Student();</li><li class=\"alt\"> s.setName(<span class=\"string\">\"陶渊明\"</span>);</li><li class=\"\"> s.setSex(<span class=\"number\">1</span>);</li><li class=\"alt\"> s.setBirthday(<span class=\"keyword\">new</span> Date());</li><li class=\"\"> <span class=\"comment\">//s.setAddress(\"江西九江\");</span></li><li class=\"alt\"> Address address = <span class=\"keyword\">new</span> Address(<span class=\"string\">\"332000\"</span>,<span class=\"string\">\"13512345678\"</span>,<span class=\"string\">\"江西九江\"</span>);</li><li class=\"\"> s.setAddress(address);</li><li class=\"alt\"> session.save(s);<span class=\"comment\">//保存对象进入数据库</span></li><li class=\"\"> }</li></ol></div><p>5、修改 hibernate.cfg.xml 里的创建表的策略</p><p>因为要修改表结构,暂且把 update 改成 create</p><p>6、用 Junit Test 运行 testSaveStudent 方法</p><p>运行成功,查看数据表</p><p><img src=\"/uploads/2017/10/2017100715512437.jpg\" alt=\"2017100715512437.jpg\"><br></p><p>查看 表结构</p><p><img src=\"/uploads/2017/10/20171007155135604.jpg\" alt=\"20171007155135604.jpg\"><br></p><p> </p>', '1', '9', '21', '0', '0', '0', '2017-10-07 15:51:57', '2017-10-07 15:51:57', '1', '1', '1'), ('8', '1', 'Mybatis高级映射多对多查询', '<p>紧接着上一篇文章:<a href=\"https://liuyanzhao.com/5847.html\" target=\"_blank\" rel=\"noopener noreferrer\">Mybatis高级映射一对多查询</a> 写</p><h2>一、开发准备</h2><p><strong>1、新建数据表(四张表)和添加测试数据</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-sql\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `items`;</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `orders`;</li><li class=\"alt\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `<span class=\"func\">user</span>`;</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS `orderdetail`;</li><li class=\"alt\"></li><li class=\"\">/*items是商品表*/</li><li class=\"alt\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `items` (</li><li class=\"\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"alt\"> `<span class=\"keyword\">name</span>` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品名称\',</li><li class=\"\"> `price` <span class=\"keyword\">FLOAT</span>(10,1) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品定价\',</li><li class=\"alt\"> `detail` TEXT COMMENT \'商品描述\',</li><li class=\"\"> `pic` <span class=\"keyword\">VARCHAR</span>(64) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'商品图片\',</li><li class=\"alt\"> `createtime` DATETIME <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'生产日期\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`)</li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=4 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*<span class=\"func\">user</span>是用户表*/</li><li class=\"\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `<span class=\"func\">user</span>` (</li><li class=\"alt\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"\"> `username` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'用户名称\',</li><li class=\"alt\"> `birthday` <span class=\"keyword\">DATE</span> <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'生日\',</li><li class=\"\"> `gender` <span class=\"keyword\">CHAR</span>(1) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'性别\',</li><li class=\"alt\"> `address` <span class=\"keyword\">VARCHAR</span>(256) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'地址\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`)</li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=27 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*orders是订单表*/</li><li class=\"\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `orders` (</li><li class=\"alt\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"\"> `user_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'下单用户id\',</li><li class=\"alt\"> `number` <span class=\"keyword\">VARCHAR</span>(32) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'订单号\',</li><li class=\"\"> `createtime` DATETIME <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'创建订单时间\',</li><li class=\"alt\"> `note` <span class=\"keyword\">VARCHAR</span>(100) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'备注\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`),</li><li class=\"alt\"> <span class=\"keyword\">KEY</span> `FK_orders_1` (`user_id`),</li><li class=\"\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orders_id` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`user_id`) <span class=\"keyword\">REFERENCES</span> `<span class=\"func\">user</span>` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span></li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=6 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li><li class=\"\"></li><li class=\"alt\">/*orderdetail是订单明细表*/</li><li class=\"\"><span class=\"keyword\">DROP</span> <span class=\"keyword\">TABLE</span> IF EXISTS orderdetail;</li><li class=\"alt\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">TABLE</span> `orderdetail` (</li><li class=\"\"> `id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> AUTO_INCREMENT,</li><li class=\"alt\"> `orders_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'订单id\',</li><li class=\"\"> `items_id` <span class=\"keyword\">INT</span>(11) <span class=\"op\">NOT</span> <span class=\"op\">NULL</span> COMMENT \'商品id\',</li><li class=\"alt\"> `items_num` <span class=\"keyword\">INT</span>(11) <span class=\"keyword\">DEFAULT</span> <span class=\"op\">NULL</span> COMMENT \'商品购买数量\',</li><li class=\"\"> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (`id`),</li><li class=\"alt\"> <span class=\"keyword\">KEY</span> `FK_orderdetail_1` (`orders_id`),</li><li class=\"\"> <span class=\"keyword\">KEY</span> `FK_orderdetail_2` (`items_id`),</li><li class=\"alt\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orderdetail_1` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`orders_id`) <span class=\"keyword\">REFERENCES</span> `orders` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span>,</li><li class=\"\"> <span class=\"keyword\">CONSTRAINT</span> `FK_orderdetail_2` <span class=\"keyword\">FOREIGN</span> <span class=\"keyword\">KEY</span> (`items_id`) <span class=\"keyword\">REFERENCES</span> `items` (`id`) <span class=\"keyword\">ON</span> <span class=\"keyword\">DELETE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span> <span class=\"keyword\">ON</span> <span class=\"keyword\">UPDATE</span> <span class=\"keyword\">NO</span> <span class=\"keyword\">ACTION</span></li><li class=\"alt\">) ENGINE=INNODB AUTO_INCREMENT=5 <span class=\"keyword\">DEFAULT</span> CHARSET=utf8;</li></ol></div><p>为了测试,我这里随便填了些数据</p><p><img src=\"/uploads/2017/10/20171007155334244.png\" alt=\"20171007155334244.png\"><br></p><p><img src=\"/uploads/2017/10/20171007155349805.png\" alt=\"20171007155349805.png\"><br></p><p><br></p><p><img src=\"/uploads/2017/10/20171007155410485.png\" alt=\"20171007155410485.png\"><br></p><p><br></p><p><strong><img src=\"/uploads/2017/10/20171007155450773.png\" alt=\"20171007155450773.png\"></strong></p><p><strong>2、思路分析</strong></p><p><img src=\"/uploads/2017/10/20171007155545742.png\" alt=\"20171007155545742.png\"><br></p><p>订单项和订单明细是一对多的关系,所以本文主要来查询订单表,然后关联订单明细表,这样就有一对多的问题出来了。</p><p><span>因为多对多比较复杂,总公共有四张表,我们先来分析一下思路:</span></p><blockquote><p><span>1、将用户信息映射到User中;</span></p><p><span>2、在User类中添加订单列表属性<code>List<orders>ordersList</orders></code>,将用户创建的订单映射到ordersList中;</span></p><p><span>3、在Orders中添加订单明细列表属性<code>List<orderdetail>orderDetails</orderdetail></code>,将订单的明细映射到orderDetails中;</span></p><p><span>4、在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items中。</span></p></blockquote><p>经过这样分析后,感觉虽然有点复杂,但是好像不是很难的样子,映射的方法也跟前面的一样,只不过这里表有点多,关系有点复杂。下面来写映射文件:</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-sql\" start=\"1\"><li class=\"alt\"><<span class=\"keyword\">select</span> id=<span class=\"string\">\"findUserAndItemsResultMap\"</span> resultMap=<span class=\"string\">\"UserAndItemsResultMap\"</span>></li><li class=\"\"> <span class=\"keyword\">SELECT</span></li><li class=\"alt\"> orders.*,</li><li class=\"\"> <span class=\"func\">user</span>.`username`,</li><li class=\"alt\"> <span class=\"func\">user</span>.`sex`,</li><li class=\"\"> <span class=\"func\">user</span>.`address`,</li><li class=\"alt\"> orderdetail.`id` orderdetail_id,</li><li class=\"\"> orderdetail.`items_id`,</li><li class=\"alt\"> orderdetail.`items_num`,</li><li class=\"\"> orderdetail.`orders_id`,</li><li class=\"alt\"> items.`<span class=\"keyword\">name</span>` items_name,</li><li class=\"\"> items.`detail` items_detail,</li><li class=\"alt\"> items.`price` items_price</li><li class=\"\"> <span class=\"keyword\">FROM</span></li><li class=\"alt\"> orders,</li><li class=\"\"> <span class=\"func\">USER</span>,</li><li class=\"alt\"> orderdetail,</li><li class=\"\"> items</li><li class=\"alt\"> <span class=\"keyword\">WHERE</span> orders.`user_id`=<span class=\"func\">user</span>.`id` <span class=\"op\">AND</span> orders.`id` = orderdetail.`orders_id` <span class=\"op\">AND</span> orderdetail.`items_id`=items.`id`</li><li class=\"\"><!--<span class=\"keyword\"-->select></li></ol></div><p>我们先看一下查询结果:</p><p><img src=\"/uploads/2017/10/2017100717420134.png\" alt=\"2017100717420134.png\"><br></p><p><br></p><h2>二、代码实现</h2><p><strong>1、四个持久化类</strong></p><p>① User.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 用户的持久类</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> User {</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id; <span class=\"comment\">//编号</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> String username; <span class=\"comment\">//用户名</span></li><li class=\"\"> <span class=\"keyword\">private</span> String gender; <span class=\"comment\">//性别</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Date birthday; <span class=\"comment\">//生日</span></li><li class=\"\"> <span class=\"keyword\">private</span> String address; <span class=\"comment\">//地址</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> List<orders> getOrdersList() {</orders></li><li class=\"alt\"> <span class=\"keyword\">return</span> ordersList;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrdersList(List<orders> ordersList) {</orders></li><li class=\"alt\"> <span class=\"keyword\">this</span>.ordersList = ordersList;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//用户创建的订单列表</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> List<orders> ordersList;</orders></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getUsername() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> username;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUsername(String username) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.username = username;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getGender() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> gender;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setGender(String gender) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.gender = gender;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getBirthday() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> birthday;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setBirthday(Date birthday) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.birthday = birthday;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getAddress() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> address;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setAddress(String address) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.address = address;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\">}</li></ol></div><p>注意:需要在用户表中加入 订单列表</p><p> </p><p>② Items.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 商品的持久类</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Items {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"\"> <span class=\"keyword\">private</span> String name;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">double</span> price;</li><li class=\"\"> <span class=\"keyword\">private</span> String detail;</li><li class=\"alt\"> <span class=\"keyword\">private</span> String pic;</li><li class=\"\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getName() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> name;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setName(String name) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.name = name;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">double</span> getPrice() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> price;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setPrice(<span class=\"keyword\">double</span> price) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.price = price;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getDetail() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> detail;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setDetail(String detail) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.detail = detail;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getPic() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> pic;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setPic(String pic) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.pic = pic;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getCreateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setCreateTime(Date createTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.createTime = createTime;</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p> </p><p>③ Orders.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Date;</li><li class=\"\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/**</span></li><li class=\"alt\"><span class=\"comment\"> * 订单的持久类和扩展类</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Orders {</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> userId;</li><li class=\"\"> <span class=\"keyword\">private</span> String number;</li><li class=\"alt\"> <span class=\"keyword\">private</span> Date createTime;</li><li class=\"\"> <span class=\"keyword\">private</span> String note;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//订单明细</span></li><li class=\"\"> <span class=\"keyword\">private</span> List<orderdetail> orderdetails;</orderdetail></li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> List<orderdetail> getOrderdetails() {</orderdetail></li><li class=\"alt\"> <span class=\"keyword\">return</span> orderdetails;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrderdetails(List<orderdetail> orderdetails) {</orderdetail></li><li class=\"alt\"> <span class=\"keyword\">this</span>.orderdetails = orderdetails;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getUserId() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> userId;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUserId(<span class=\"keyword\">int</span> userId) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.userId = userId;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getNumber() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> number;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setNumber(String number) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.number = number;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Date getCreateTime() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setCreateTime(Date createTime) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.createTime = createTime;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> String getNote() {</li><li class=\"alt\"> <span class=\"keyword\">return</span> note;</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setNote(String note) {</li><li class=\"alt\"> <span class=\"keyword\">this</span>.note = note;</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p>注意:订单列表中,需要订单的详细信息,不需要用户信息</p><p> </p><p>④ Orderdetail.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.po;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 订单明细的持久类</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Orderdetail {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> id;</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> ordersId;</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> itemsId;</li><li class=\"\"> <span class=\"keyword\">private</span> <span class=\"keyword\">int</span> itemsNum;</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//明细对应的商品信息</span></li><li class=\"alt\"> <span class=\"keyword\">private</span> Items items;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> Items getItems() {</li><li class=\"\"> <span class=\"keyword\">return</span> items;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItems(Items items) {</li><li class=\"\"> <span class=\"keyword\">this</span>.items = items;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getId() {</li><li class=\"\"> <span class=\"keyword\">return</span> id;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setId(<span class=\"keyword\">int</span> id) {</li><li class=\"\"> <span class=\"keyword\">this</span>.id = id;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getOrdersId() {</li><li class=\"\"> <span class=\"keyword\">return</span> ordersId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setOrdersId(<span class=\"keyword\">int</span> ordersId) {</li><li class=\"\"> <span class=\"keyword\">this</span>.ordersId = ordersId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getItemsId() {</li><li class=\"\"> <span class=\"keyword\">return</span> itemsId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItemsId(<span class=\"keyword\">int</span> itemsId) {</li><li class=\"\"> <span class=\"keyword\">this</span>.itemsId = itemsId;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">int</span> getItemsNum() {</li><li class=\"\"> <span class=\"keyword\">return</span> itemsNum;</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setItemsNum(<span class=\"keyword\">int</span> itemsNum) {</li><li class=\"\"> <span class=\"keyword\">this</span>.itemsNum = itemsNum;</li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p>注意:订单明细里,需要 商品信息</p><p> </p><p><strong>2、订单代理 即mapper.java</strong></p><p>OrdersMapperCustom.java</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.mapper;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.po.User;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * 订单 mapper</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">interface</span> OrdersMapperCustom {</li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//查询用户购买的商品信息</span></li><li class=\"alt\"> <span class=\"keyword\">public</span> List<user> findUserAndItemsResultMap() <span class=\"keyword\">throws</span> Exception;</user></li><li class=\"\">}</li></ol></div><p> </p><p><span><strong>3、OrdersMapperCustom.xml 映射文件</strong></span></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><!--?</span--><span class=\"tag-name\">xml</span> <span class=\"attribute\">version</span>=<span class=\"attribute-value\">\"1.0\"</span> <span class=\"attribute\">encoding</span>=<span class=\"attribute-value\">\"UTF-8\"</span> <span class=\"tag\">?></span></span></li><li class=\"\"></li><li class=\"alt\"> PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"</li><li class=\"\"> \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"<span class=\"tag\">></span></li><li class=\"alt\"></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">mapper</span> <span class=\"attribute\">namespace</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.mapper.OrdersMapperCustom\"</span><span class=\"tag\">></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--查询用户购买的商品--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">resultMap</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"UserAndItemsResultMap\"</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.User\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!--用户信息--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"user_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"username\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"username\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"gender\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"gender\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"address\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"address\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comments\"><!--订单信息--></span></li><li class=\"\"> <span class=\"comments\"><!--一个用户可以对应多个订单,故使用collection映射--></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">collection</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"ordersList\"</span> <span class=\"attribute\">ofType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Orders\"</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"user_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"userId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"number\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"number\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"createtime\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"createTime\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"node\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"node\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--订单明细--></span></li><li class=\"alt\"> <span class=\"comments\"><!--一个订单包括多个明细,故使用collection--></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">collection</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"orderdetails\"</span> <span class=\"attribute\">ofType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Orderdetail\"</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"orderdetail_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"itemsId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_num\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"itemsNum\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"orders_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"ordersId\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comments\"><!--商品信息--></span></li><li class=\"alt\"> <span class=\"comments\"><!--一个订单明细对应一个商品--></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">association</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"items\"</span> <span class=\"attribute\">javaType</span>=<span class=\"attribute-value\">\"com.liuyanzhao.mybatis.po.Items\"</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">id</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_id\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"id\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">id</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_name\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"name\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_price\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"price\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">result</span> <span class=\"attribute\">column</span>=<span class=\"attribute-value\">\"items_detail\"</span> <span class=\"attribute\">property</span>=<span class=\"attribute-value\">\"detail\"</span><span class=\"tag\">></span><span class=\"tag\"><!--</span--><span class=\"tag-name\">result</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">association</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">collection</span><span class=\"tag\">></span></span></li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">collection</span><span class=\"tag\">></span></span></li><li class=\"\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">resultMap</span><span class=\"tag\">></span></span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">select</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"findUserAndItemsResultMap\"</span> <span class=\"attribute\">resultMap</span>=<span class=\"attribute-value\">\"UserAndItemsResultMap\"</span><span class=\"tag\">></span></li><li class=\"alt\"> SELECT</li><li class=\"\"> orders.*,</li><li class=\"alt\"> user.username,</li><li class=\"\"> user.gender,</li><li class=\"alt\"> user.address,</li><li class=\"\"> orderdetail.id orderdetail_id,</li><li class=\"alt\"> orderdetail.items_id,</li><li class=\"\"> orderdetail.items_num,</li><li class=\"alt\"> orderdetail.orders_id,</li><li class=\"\"> items.name items_name,</li><li class=\"alt\"> items.detail items_detail,</li><li class=\"\"> items.price items_price</li><li class=\"alt\"> FROM</li><li class=\"\"> orders,</li><li class=\"alt\"> user,</li><li class=\"\"> orderdetail,</li><li class=\"alt\"> items</li><li class=\"\"> WHERE <span class=\"attribute\">orders.user_id</span>=user.id AND <span class=\"attribute\">orders.id</span> = <span class=\"attribute-value\">orderdetail</span>.orders_id AND <span class=\"attribute\">orderdetail.items_id</span>=items.id</li><li class=\"alt\"> <span class=\"tag\"><!--</span--><span class=\"tag-name\">select</span><span class=\"tag\">></span></span></li><li class=\"\"></li><li class=\"alt\"><span class=\"tag\"><!--</span--><span class=\"tag-name\">mapper</span><span class=\"tag\">></span></span></li></ol></div><p> </p><p><span>4、测试类 OrderMapperCustomTest.java</span></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao.mybatis.test;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.mapper.OrdersMapperCustom;</li><li class=\"\"><span class=\"keyword\">import</span> com.liuyanzhao.mybatis.po.User;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.apache.ibatis.io.Resources;</li><li class=\"\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSession;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSessionFactory;</li><li class=\"\"><span class=\"keyword\">import</span> org.apache.ibatis.session.SqlSessionFactoryBuilder;</li><li class=\"alt\"><span class=\"keyword\">import</span> org.junit.Before;</li><li class=\"\"><span class=\"keyword\">import</span> org.junit.Test;</li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">import</span> java.io.InputStream;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.List;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/**</span></li><li class=\"\"><span class=\"comment\"> * Created by Liu_Yanzhao on 2017/8/12.</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> OrderMapperCustomTest {</li><li class=\"alt\"> SqlSessionFactory sqlSessionFactory;</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Before</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> setUp() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> String resource = <span class=\"string\">\"Configuration.xml\"</span>;</li><li class=\"\"> InputStream inputStream = Resources.getResourceAsStream(resource);</li><li class=\"alt\"> sqlSessionFactory = <span class=\"keyword\">new</span> SqlSessionFactoryBuilder()</li><li class=\"\"> .build(inputStream);</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"annotation\">@Test</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> testFindUserAndItemsResultMap() <span class=\"keyword\">throws</span> Exception {</li><li class=\"alt\"> SqlSession sqlSession = sqlSessionFactory.openSession();</li><li class=\"\"> <span class=\"comment\">//创建代理对象</span></li><li class=\"alt\"> OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.<span class=\"keyword\">class</span>);</li><li class=\"\"> <span class=\"comment\">//调用mapper对象</span></li><li class=\"alt\"> List<user> list = ordersMapperCustom.findUserAndItemsResultMap();</user></li><li class=\"\"> System.out.println(list);</li><li class=\"alt\"> <span class=\"comment\">//释放资源</span></li><li class=\"\"> sqlSession.close();</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p>还有其他文件就不补充了,如 mybatis 全局配置文件</p><p> </p><h2>小结</h2><p><span>这样多对多的映射就搞定了。不过还有个问题,就是这里多对多的查询会把所有关联的表的信息都查询出来,然后放到pojo中的对应的List或者某个类中,所以即使我只查了个用户信息,但是这个用户里包含了订单,订单项,商品等信息,感觉装的有点多,好像有时候并不需要这么多冗余的数据出来,但是如果用resultType的话查询出来的字段必须对应pojo中的属性,如果有List等,需要手动装入才行。所以下面总结一下对于这种查询数据比较多的时候,resultType和resultMap各有什么作用?</span></p><blockquote><ol><li>比如我们只需要将查询用户购买的商品信息明细清单(如用户名、用户地址、购买商品名称、购买商品时间、购买商品数量),那么我们完全不需要其他的信息,这个时候就没必要使用resultMap将所有的信息都搞出来,我们可以自己定义一个pojo,包含我们需要的字段即可,然后查询语句只查询我们需要的字段,这样使用resultType会方便很多。</li><li>如果我们需要查询该用户的所有详细信息,比如用户点击该用户或者鼠标放上去,会出来跟该用户相关的订单啊,订单明细啊,商品啊之类的,然后我们要点进去看下详细情况的时候,那就需要使用resultMap了,必须将所有信息都装到这个User中,然后具体啥信息再从User中取,很好理解。</li><li>总结一点:使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括多个list。否则使用resultType比较直接。</li></ol></blockquote><p><span>到这里,mybatis的多对多映射就总结完了。 </span></p>', '1', '9', '13', '6', '2', '0', '2017-10-07 15:56:00', '2017-10-07 17:42:03', '1', '1', '1');
INSERT INTO `article` VALUES ('9', '1', 'Servlet 实现验证码', '<h2>分析</h2><p><strong>生成图片实现类</strong></p><p>Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a> 类</p><p>① 定义BufferedImage 对象</p><p>② 获得 Graphics 对象</p><p>③ 通过 Random 产生随机验证码信息</p><p>④ 使用 Graphics 绘制图片</p><p>⑤ 记录验证码信息到 session 中</p><p>⑥ 使用 ImageIO 输出图片</p><h2>代码实现</h2><p>1、新建 web 项目 CheckCode,在 WebContent 下新建 index.jsp</p><p><strong>index.jsp</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span>%@ page <span class=\"attribute\">language</span>=<span class=\"attribute-value\">\"java\"</span> <span class=\"attribute\">contentType</span>=<span class=\"attribute-value\">\"text/html; charset=UTF-8\"</span></li><li class=\"\"> <span class=\"attribute\">pageEncoding</span>=<span class=\"attribute-value\">\"UTF-8\"</span>%<span class=\"tag\">></span></li><li class=\"alt\"><!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"<span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">html</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">head</span><span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">meta</span> <span class=\"attribute\">http-equiv</span>=<span class=\"attribute-value\">\"Content-Type\"</span> <span class=\"attribute\">content</span>=<span class=\"attribute-value\">\"text/html; charset=UTF-8\"</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">title</span><span class=\"tag\">></span>Insert title here<span class=\"tag\"></</span><span class=\"tag-name\">title</span><span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">script</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"text/javascript\"</span><span class=\"tag\">></span></li><li class=\"alt\"> function reloadCode() {</li><li class=\"\"> //传个时间参数,防止缓存</li><li class=\"alt\"> var <span class=\"attribute\">time</span> = <span class=\"attribute-value\">new</span> Date().getTime();</li><li class=\"\"> document.getElementById(\"imageCode\")<span class=\"attribute\">.src</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>?d=\"</span>+time;</li><li class=\"alt\"> }</li><li class=\"\"><span class=\"tag\"></</span><span class=\"tag-name\">script</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">head</span><span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"><</span><span class=\"tag-name\">body</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">form</span> <span class=\"attribute\">action</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Login<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>\"</span> <span class=\"attribute\">method</span>=<span class=\"attribute-value\">\"post\"</span><span class=\"tag\">></span></li><li class=\"\"> 验证码:<span class=\"tag\"><</span><span class=\"tag-name\">input</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"text\"</span> <span class=\"attribute\">name</span>=<span class=\"attribute-value\">\"checkcode\"</span> <span class=\"tag\">/></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">img</span> <span class=\"attribute\">id</span>=<span class=\"attribute-value\">\"imageCode\"</span> <span class=\"attribute\">src</span>=<span class=\"attribute-value\">\"<%=request.getContextPath()%>/Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>\"</span> <span class=\"attribute\">alt</span>=<span class=\"attribute-value\">\"验证码\"</span> <span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">a</span> <span class=\"attribute\">href</span>=<span class=\"attribute-value\">\"javascript:reloadCode();\"</span><span class=\"tag\">></span>看不清楚<span class=\"tag\"></</span><span class=\"tag-name\">a</span><span class=\"tag\">></span> <span class=\"tag\"><</span><span class=\"tag-name\">br</span> <span class=\"tag\">/></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">input</span> <span class=\"attribute\">type</span>=<span class=\"attribute-value\">\"submit\"</span> <span class=\"attribute\">value</span>=<span class=\"attribute-value\">\"提交\"</span><span class=\"tag\">/></span></li><li class=\"\"> <span class=\"tag\"></</span><span class=\"tag-name\">form</span><span class=\"tag\">></span></li><li class=\"alt\"><span class=\"tag\"></</span><span class=\"tag-name\">body</span><span class=\"tag\">></span></li><li class=\"\"><span class=\"tag\"></</span><span class=\"tag-name\">html</span><span class=\"tag\">></span></li></ol></div><p>2、在 src 下新建 com.liuyanzhao 包,然后分别新建用于动态画图的 Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a> 类和用于判断验证码是否正确的 Login<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a> 类</p><p><strong>Image<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.awt.Color;</li><li class=\"\"><span class=\"keyword\">import</span> java.awt.Graphics;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.awt.image.BufferedImage;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Random;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> javax.imageio.ImageIO;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>Exception;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.Http<a href=\"https://liuyanzhao.com/tag/servlet/\" title=\"查看与 Servlet 相关的文章\" target=\"_blank\">Servlet</a>;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletResponse;</li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> ImageServlet <span class=\"keyword\">extends</span> HttpServlet {</li><li class=\"\"> <span class=\"annotation\">@Override</span></li><li class=\"alt\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"\"> BufferedImage bi = <span class=\"keyword\">new</span> BufferedImage(<span class=\"number\">68</span>, <span class=\"number\">22</span>, BufferedImage.TYPE_INT_RGB);</li><li class=\"alt\"> Graphics g = bi.getGraphics();</li><li class=\"\"> Color c = <span class=\"keyword\">new</span> Color(<span class=\"number\">200</span>,<span class=\"number\">155</span>,<span class=\"number\">255</span>);</li><li class=\"alt\"> g.setColor(c);</li><li class=\"\"> g.fillRect(<span class=\"number\">0</span>, <span class=\"number\">0</span>, <span class=\"number\">68</span>, <span class=\"number\">22</span>);</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">char</span>[] ch = <span class=\"string\">\"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"</span>.toCharArray();</li><li class=\"alt\"> Random r = <span class=\"keyword\">new</span> Random();</li><li class=\"\"> <span class=\"keyword\">int</span> len = ch.length,index;</li><li class=\"alt\"> StringBuffer sb = <span class=\"keyword\">new</span> StringBuffer();</li><li class=\"\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">int</span> i=<span class=\"number\">0</span>;i<<span class=\"number\">4</span>;i++) {</li><li class=\"alt\"> index = r.nextInt(len);</li><li class=\"\"> g.setColor(<span class=\"keyword\">new</span> Color(r.nextInt(<span class=\"number\">88</span>),r.nextInt(<span class=\"number\">188</span>),r.nextInt(<span class=\"number\">255</span>)));</li><li class=\"alt\"> g.drawString(ch[index]+<span class=\"string\">\"\"</span>, (i*<span class=\"number\">15</span>)+<span class=\"number\">3</span>, <span class=\"number\">18</span>);</li><li class=\"\"> sb.append(ch[index]);</li><li class=\"alt\"> }</li><li class=\"\"> request.getSession().setAttribute(<span class=\"string\">\"piccode\"</span>, sb.toString());</li><li class=\"alt\"> ImageIO.write(bi, <span class=\"string\">\"JPG\"</span>, response.getOutputStream());</li><li class=\"\"> }</li><li class=\"alt\"> <span class=\"annotation\">@Override</span></li><li class=\"\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"alt\"> doGet(request, response);</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div><p><strong>LoginServlet.java</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.PrintWriter;</li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.ServletException;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServlet;</li><li class=\"\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</li><li class=\"alt\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletResponse;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> LoginServlet <span class=\"keyword\">extends</span> HttpServlet{</li><li class=\"alt\"> <span class=\"annotation\">@Override</span></li><li class=\"\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doPost(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"alt\"> String piccode = (String)request.getSession().getAttribute(<span class=\"string\">\"piccode\"</span>);</li><li class=\"\"> String checkcode = request.getParameter(<span class=\"string\">\"checkcode\"</span>);</li><li class=\"alt\"> checkcode = checkcode.toUpperCase();<span class=\"comment\">//不区分大小写</span></li><li class=\"\"> response.setContentType(<span class=\"string\">\"text/html;charset=utf-8\"</span>);</li><li class=\"alt\"> PrintWriter out = response.getWriter();</li><li class=\"\"> <span class=\"keyword\">if</span>(piccode.equals(checkcode)) {</li><li class=\"alt\"> out.println(<span class=\"string\">\"验证码输入正确\"</span>);</li><li class=\"\"> } <span class=\"keyword\">else</span> {</li><li class=\"alt\"> out.println(<span class=\"string\">\"验证码输入错误\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"> out.flush();</li><li class=\"\"> out.close();</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"annotation\">@Override</span></li><li class=\"alt\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span class=\"keyword\">throws</span> ServletException, IOException {</li><li class=\"\"> doPost(request, response);</li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p>3、在 web.xml 里添加 Servlet 映射</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-xml\" start=\"1\"><li class=\"alt\"><span class=\"tag\"><</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>ImageServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span>com.liuyanzhao.ImageServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"></</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!-- 映射为 ImageServlet --></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>ImageServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span>/ImageServlet<span class=\"tag\"></</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"></</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>LoginServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span>com.liuyanzhao.LoginServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-class</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"></</span><span class=\"tag-name\">servlet</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"comments\"><!-- 映射为 IndexServlet --></span></li><li class=\"alt\"> <span class=\"tag\"><</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span>LoginServlet<span class=\"tag\"></</span><span class=\"tag-name\">servlet-name</span><span class=\"tag\">></span></li><li class=\"\"> <span class=\"tag\"><</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span>/LoginServlet<span class=\"tag\"></</span><span class=\"tag-name\">url-pattern</span><span class=\"tag\">></span></li><li class=\"alt\"> <span class=\"tag\"></</span><span class=\"tag-name\">servlet-mapping</span><span class=\"tag\">></span></li></ol></div><p>4、运行 Tomcat 服务器,打开浏览器,访问 http://localhost:8080/CheckCode</p><p>效果如下</p><p><img src=\"/uploads/2017/10/20171007155723341.png\" alt=\"20171007155723341.png\"><br></p><p>验证码不区分大小写,点击 “看不清楚”可以更换</p>', '1', '8', '19', '2', '2', '0', '2017-10-07 15:57:38', '2017-10-07 15:57:38', '1', '1', '1'), ('10', '1', 'Integer与int的种种比较你知道多少?', '<p>如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null。但是如果面试官再问一下Integer a = 1;int b = 1; a==b为true还是为false?估计就有一部分人答不出来了,如果再问一下其他的,估计更多的人会头脑一片混乱。所以我对它们进行了总结,希望对大家有帮助。</p><p><strong>首先看代码:</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/* </span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">int</span> i = <span class=\"number\">128</span>;</li><li class=\"\"> Integer i2 = <span class=\"number\">128</span>;</li><li class=\"alt\"> Integer i3 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">128</span>);</li><li class=\"\"> <span class=\"comment\">//Integer会自动拆箱为int,所以为true</span></li><li class=\"alt\"> System.out.println(i == i2);<span class=\"comment\">//true</span></li><li class=\"\"> System.out.println(i == i3);<span class=\"comment\">//true</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//java在编译的时候,被翻译成-> Integer i5 = Integer.valueOf(127);</span></li><li class=\"alt\"> Integer i5 = <span class=\"number\">127</span>;</li><li class=\"\"> Integer i6 = <span class=\"number\">127</span>;</li><li class=\"alt\"> System.out.println(i5 == i6);<span class=\"comment\">//true</span></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> Integer i7 = <span class=\"number\">128</span>;</li><li class=\"alt\"> Integer i8 = <span class=\"number\">128</span>;</li><li class=\"\"> System.out.println(i7 == i8);<span class=\"comment\">//false</span></li><li class=\"alt\"></li><li class=\"\"></li><li class=\"alt\"> Integer i9 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">127</span>);</li><li class=\"\"> Integer i10 = <span class=\"number\">127</span>;</li><li class=\"alt\"> System.out.println(i9 == i10); <span class=\"comment\">//false</span></li><li class=\"\"></li><li class=\"alt\"></li><li class=\"\"> Integer i11 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">128</span>);</li><li class=\"alt\"> Integer i12 = <span class=\"keyword\">new</span> Integer(<span class=\"number\">123</span>);</li><li class=\"\"> System.out.println(i11 == i12); <span class=\"comment\">//false</span></li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\">}</li></ol></div><p><strong>详解如下:</strong></p><p>首先,13行和14行输出结果都为true,因为Integer和int比都会自动拆箱(jdk1.5以上)。</p><p>19行的结果为true,而24行则为false,很多人都不懂为什么。其实java在编译Integer i5 = 127的时候,被翻译成-> Integer i5 = Integer.valueOf(127);所以关键就是看valueOf()函数了。只要看看valueOf()函数的源码就会明白了。JDK源码的valueOf函数式这样的:</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Integer valueOf(<span class=\"keyword\">int</span> i) {</li><li class=\"\"> <span class=\"keyword\">assert</span> IntegerCache.high >= <span class=\"number\">127</span>;</li><li class=\"alt\"> <span class=\"keyword\">if</span> (i >= IntegerCache.low && i <= IntegerCache.high)</li><li class=\"\"> <span class=\"keyword\">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</li><li class=\"alt\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> Integer(i);</li><li class=\"\">}</li></ol></div><p>看一下源码大家都会明白,对于-128到127之间的数,会进行缓存,Integer i5 = 127时,会将127进行缓存,下次再写Integer i6 = 127时,就会直接从缓存中取,就不会new了。所以22行的结果为true,而25行为false。</p><p>对于29行和34行,因为对象不一样,所以为false。</p><p>我对于以上的情况总结如下:</p><p>① 无论如何,<span><strong>Integer与new Integer不会相等</strong></span>。不会经历拆箱过程,i3的引用指向堆,而i4指向专门存放他的内存(常量池),他们的内存地址不一样,所以为false</p><p>② <strong><span>两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false</span></strong></p><p>java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存</p><p>③ <strong><span>两</span><span>个都是new出来的,都为false</span></strong></p><p>④ <strong><span>int和Integer(无论new否)比,都为true</span></strong>,因为会把Integer自动拆箱为int再去比</p><p> </p><p>参考:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html\" target=\"_blank\" rel=\"noopener noreferrer\">http://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html</a></p><div><br></div>', '1', '2', '1', '0', '1', '1', '2017-10-07 15:58:51', '2017-10-07 15:58:51', '1', '1', '1'), ('11', '1', 'Java如何让程序一直运行,不停止', '<p>如何让程序一直运行,很容易实现,只需要一直等待输出即可啦</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">import</span> java.util.Scanner;</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\"> * @author LiuYanzhao</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"alt\"> <span class=\"keyword\">private</span> <span class=\"keyword\">static</span> <span class=\"keyword\">final</span> String OPERATION_EXIT = <span class=\"string\">\"EXIT\"</span>;</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"请开始您的输入,EXIT/E 退出\"</span>);</li><li class=\"\"> <span class=\"comment\">//怎么让程序一直运行</span></li><li class=\"alt\"> Scanner scan = <span class=\"keyword\">new</span> Scanner(System.in);</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">while</span>(scan.hasNext()) {</li><li class=\"\"> String in = scan.next().toString();</li><li class=\"alt\"> <span class=\"keyword\">if</span>(OPERATION_EXIT.equals(in.toUpperCase())</li><li class=\"\"> || OPERATION_EXIT.substring(<span class=\"number\">0</span>, <span class=\"number\">1</span>).equals(in.toUpperCase())) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"您成功已退出!\"</span>);</li><li class=\"\"> <span class=\"keyword\">break</span>;</li><li class=\"alt\"> }</li><li class=\"\"> System.out.println(<span class=\"string\">\"您输入的值:\"</span>+in);</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\"> }</li><li class=\"\">}</li><li></li></ol></div>', '1', '2', '1', '1', '2', '0', '2017-10-07 15:59:33', '2017-10-07 15:59:33', '1', '1', '1'), ('12', '1', 'Java中静态代码块、构造代码块的区别', '<p>直接在类中定义且没有加static关键字的代码块称为{}构造代码块。</p><p><strong><span>构造代码块在创建对象时被调用,每次创建对象都会被调用</span></strong>,并且构造代码块的执行次序优先于类构造函数。</p><p>静态代码块:在java中使用static关键字声明的代码块。<span><strong>静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行</strong></span>。</p><p>注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。</p><p>静态代码块、构造代码块、构造函数同时存在时的执行顺序:<strong><span>静态代码块 > 构造代码块 > 构造函数</span></strong>;</p><p> </p><p>下面我们来举几个例子说明一切</p><p><strong>demo1:构造方法</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"静态块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"构造块,在类中定义\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"构造方法执行\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\"><span class=\"comment\">/*</span></li><li class=\"\"><span class=\"comment\">静态块</span></li><li class=\"alt\"><span class=\"comment\">构造块,在类中定义</span></li><li class=\"\"><span class=\"comment\">构造方法执行</span></li><li class=\"alt\"><span class=\"comment\">构造块,在类中定义</span></li><li class=\"\"><span class=\"comment\">构造方法执行</span></li><li class=\"alt\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo2:普通代码块</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*普通代码块:在方法或语句中出现的{}就称为普通代码块。</span></li><li class=\"\"><span class=\"comment\">普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”*/</span></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> <span class=\"keyword\">int</span> x = <span class=\"number\">3</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"1,普通代码块内的变量x=\"</span> + x);</li><li class=\"alt\"> }</li><li class=\"\"></li><li class=\"alt\"> <span class=\"keyword\">int</span> x = <span class=\"number\">1</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"主方法内的变量x=\"</span> + x);</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> <span class=\"keyword\">int</span> y = <span class=\"number\">7</span>;</li><li class=\"\"> System.out.println(<span class=\"string\">\"2,普通代码块内的变量y=\"</span> + y);</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"comment\">/* </span></li><li class=\"\"><span class=\"comment\">1,普通代码块内的变量x=3</span></li><li class=\"alt\"><span class=\"comment\">主方法内的变量x=1</span></li><li class=\"\"><span class=\"comment\">2,普通代码块内的变量y=7</span></li><li class=\"alt\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo3:构造代码块</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*构造块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。</span></li><li class=\"\"><span class=\"comment\">构造代码块在创建对象时被调用,每次创建对象都会被调用,</span></li><li class=\"alt\"><span class=\"comment\">并且构造代码块的执行次序优先于类构造函数。*/</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"第一代码块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"构造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"第二构造块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\">第一代码块</span></li><li class=\"\"><span class=\"comment\">第二构造块</span></li><li class=\"alt\"><span class=\"comment\">构造方法</span></li><li class=\"\"><span class=\"comment\">第一代码块</span></li><li class=\"alt\"><span class=\"comment\">第二构造块</span></li><li class=\"\"><span class=\"comment\">构造方法</span></li><li class=\"alt\"><span class=\"comment\">第一代码块</span></li><li class=\"\"><span class=\"comment\">第二构造块</span></li><li class=\"alt\"><span class=\"comment\">构造方法</span></li><li class=\"\"><span class=\"comment\">*/</span></li></ol></div><p><strong>demo4:静态代码块</strong></p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"comment\">/*静态代码块:在java中使用static关键字声明的代码块。</span></li><li class=\"\"><span class=\"comment\">静态块用于初始化类,为类的属性初始化。</span></li><li class=\"alt\"><span class=\"comment\">每个静态代码块只会执行一次。</span></li><li class=\"\"><span class=\"comment\">由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。</span></li><li class=\"alt\"><span class=\"comment\">如果类中包含多个静态代码块,那么将按照\"先定义的代码先执行,后定义的代码后执行\"。</span></li><li class=\"\"><span class=\"comment\">注意:1 静态代码块不能存在于任何方法体内。</span></li><li class=\"alt\"><span class=\"comment\"> 2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。*/</span></li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">class</span> Code {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的构造块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的静态代码块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Code() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Code的构造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"\"> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的构造块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">static</span> {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的静态代码块\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> Test() {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的构造方法\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"alt\"> System.out.println(<span class=\"string\">\"Test的主方法\"</span>);</li><li class=\"\"> <span class=\"keyword\">new</span> Code();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Code();</li><li class=\"\"> <span class=\"keyword\">new</span> Test();</li><li class=\"alt\"> <span class=\"keyword\">new</span> Test();</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\">Test的静态代码块</span></li><li class=\"\"><span class=\"comment\">Test的主方法</span></li><li class=\"alt\"><span class=\"comment\">Code的静态代码块</span></li><li class=\"\"><span class=\"comment\">Code的构造块</span></li><li class=\"alt\"><span class=\"comment\">Code的构造方法</span></li><li class=\"\"><span class=\"comment\">Code的构造块</span></li><li class=\"alt\"><span class=\"comment\">Code的构造方法</span></li><li class=\"\"><span class=\"comment\">Test的构造块</span></li><li class=\"alt\"><span class=\"comment\">Test的构造方法</span></li><li class=\"\"><span class=\"comment\">Test的构造块</span></li><li class=\"alt\"><span class=\"comment\">Test的构造方法</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li></li></ol></div>', '1', '2', '1', '1', '0', '0', '2017-10-07 16:00:06', '2017-10-07 16:00:06', '1', '1', '1'), ('13', '1', 'sql语句分为三类(DML,DDL,DCL)-介绍', '<p><span>DML(data manipulation language):数据库操作语言</span><br><span>它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样</span></p><p> </p><p><span>DDL(data definition language):的数据库定义语言</span><br><span>主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用</span></p><p> </p><p><span>DCL(Data Control Language): 数据库控制语言</span><br><span>是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL</span></p><p> </p><p><strong>详细解释:</strong></p><h2>一、DDL is Data Definition Language statements</h2><p>数据定义语言,用于定义和管理 <a href=\"https://liuyanzhao.com/tag/sql/\" title=\"查看与 SQL 相关的文章\" target=\"_blank\">SQL</a> 数据库中的所有对象的语言</p><p>1.CREATE - to create objects in the database 创建</p><p>2.ALTER - alters the structure of the database 修改</p><p>3.DROP - delete objects from the database 删除</p><p>4.TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed</p><p>TRUNCATE TABLE [Table Name]。</p><p>下面是对Truncate语句在MS<a href=\"https://liuyanzhao.com/tag/sql/\" title=\"查看与 SQL 相关的文章\" target=\"_blank\">SQL</a>Server2000中用法和原理的说明:</p><p>Truncate table 表名 速度快,而且效率高,因为:</p><p>TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但</p><p>TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。</p><p>DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存</p><p>储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。</p><p>TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。</p><p>对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。</p><p>TRUNCATE TABLE 不能用于参与了索引视图的表。</p><p>5.COMMENT - add comments to the data dictionary 注释</p><p>6.GRANT - gives user\'s access privileges to database 授权</p><p>7.REVOKE - withdraw access privileges given with the GRANT command 收回已经授予的权限</p><p> </p><h2>二、DML is Data Manipulation Language statements</h2><p>数据操作语言,SQL中处理数据等操作统称为数据操纵语言</p><p>1.SELECT - retrieve data from the a database 查询</p><p>2.INSERT - insert data into a table 添加</p><p>3.UPDATE - updates existing data within a table 更新</p><p>4.DELETE - deletes all records from a table, the space for the records remain 删除</p><p>5.CALL - call a PL/SQL or Java subprogram</p><p>6.EXPLAIN PLAN - explain access path to data</p><p>Oracle RDBMS执行每一条SQL语句,都必须经过Oracle优化器的评估。所以,了解优化器是如何选择(搜索)路径以及索引是如何被使用的,对优化SQL语句有很大的帮助。Explain可以用来迅速方便地查出对于给定SQL语句中的查询数据是如何得到的即搜索路径(我们通常称为Access Path)。从而使我们选择最优的查询方式达到最大的优化效果。</p><p>7.LOCK TABLE - control concurrency 锁,用于控制并发</p><p> </p><h2>三、DCL is Data Control Language statements</h2><p>数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等</p><p>1.COMMIT - save work done 提交</p><p>2.SAVEPOINT - identify a point in a transaction to which you can later roll back 保存点</p><p>3.ROLLBACK - restore database to original since the last COMMIT 回滚</p><p>4.SET TRANSACTION - Change transaction options like what rollback segment to use 设置当前事务的特性,它对后面的事务没有影响</p><div><br></div>', '10', '13', '9,22', '1', '3', '1', '2017-10-07 16:00:50', '2017-10-07 16:01:07', '1', '1', '1'), ('14', '1', 'execute、executeUpdate、executeQuery三者的区别', '<p>1. ResultSet executeQuery(String sql); 执行SQL查询,并返回 ResultSet 对象。</p><p>例如:被执行最多的 SELECT 语句。</p><p>2.int executeUpdate(String sql); 可执行增,删,改,返回执行受到影响的行数。</p><p>例如: INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句</p><p>3. boolean execute(String sql); 可执行任何SQL语句,返回一个布尔值,表示是否返回 ResultSet 。</p><p><strong> <span> execute是executeQuery和executeUpdate的综合.</span></strong></p><p><strong><span>通常我们没有必要使用execute方法来执行SQL语句,而是使用 executeQuery 或 executeUpdate 更适合。</span></strong></p><p>-----</p><p> </p><p>executeUpdate() 这是 PreparedStatement 接口中的方法</p><p>executeUpdate(String sql) 这是 PreparedStatement 从父接口 Statement 中继承过来的方法</p><p>executeUpdate() 中执行 SQL 语句需要在创建 PerparedStatement 时通过 Connection 的 prepareStatement(String sql) 方法中写出,因为 PerparedStatement 中的 SQL 语句数据库需要进行预编译和缓存,因此要在创建 PerparedStatement 对象时给出 SQL 语句。</p><p>而 executeUpdate(String sql) 是 Statement 中的方法,参数中的 SQL 语句只是提交给数据库去执行,并不需要预编译。</p><p><strong>如果 SQL 语句中有 ? 占位符,那么在设置好占位符中的值后,必须使用 executeUpdate() 执行。而 executeUpdate(String sql) 只是提交一个 SQL 语句,且这个语句中不能带有 ? 占位符。</strong></p><p>当然,我们最好不要用 Statement 接口<br>参考:http://www.cnblogs.com/bukudekong/archive/2011/06/22/2086531.html</p>', '1', '8', '20,22', '1', '3', '0', '2017-10-07 16:02:12', '2017-10-07 16:02:12', '1', '1', '1'), ('15', '1', 'JSP 中 forward 转发 和 sendRedirect 重定向的区别', '<h2>本质区别:</h2><div> <b>一句话概括:</b>重定向是客户端行为,转发是服务器行为.</div><div><b> 1.请求次数:</b></div><div> 重定向:重定向行为是做了两次请求,及产生了两个request对象,重定向会导致request对象信息丢失。</div><div> 请求转发:转发做了一次请求, 浏览器的地址栏一直是第一次请求的地址。转发是服务器内部request/response控制权的移交。</div><div> <b>2.请求资源地址:</b></div><p><strong>重定向</strong>:web组件可以将请求重定向到任意一个url,而不仅仅是同一个应用。</p><p>重定向的源组件与目标组件不共用同一个HttpServletRequest对象,因此不能在request范围内共享数据。</p><p><strong>请求转发</strong>:转发的源组件与目标组件必须在同一个应用中,两者可以在request范围内共享数据。</p><div><strong> 3.一种解释:</strong></div><div><p>假设你去办理某个执照</p><p><strong>重定向</strong>:你先去了A局,A局的人说:“这个事情不归我们管,去B局”,然后,你就从A退了出来,自己乘车去了B局。</p><p><strong>请求转发</strong>:你先去了A局,A局看了以后,知道这个事情其实应该B局来管,但是他没有把你退回来,而是让你坐一会儿,自己到后面办公室联系了B的人,让他们办好后,送了过来。</p></div><div><h2><b>工作流程:</b></h2></div><p><strong>1.重定向</strong></p><p>浏览器发出http请求 <b>>></b> 服务器接受请求并发送302状态码和新的对应的url到浏览器 <b>>></b></p><p>浏览器接收响应并自动请求新的url <b>>></b> 服务器接收请求并寻找客户所需的资源响应到浏览器</p><p><strong>2.转发</strong></p><p>浏览器发出http求其 <b>>></b> 服务器接收请求 <b>>></b> 服务器调用内部的一个方法在容器内完成请求处理和转发动作 <b>>></b></p><p>将客户所需资源发送到浏览</p><p> </p><h2><b>调用方式:</b></h2><p>我们知道,在servlet中调用转发、重定向的语句如下:</p><p>request.getRequestDispatcher(\"new.jsp\").forward(request, response); //转发到new.jsp</p><p>response.sendRedirect(\"new.jsp\"); //重定向到new.jsp</p><p>在jsp页面中你也会看到通过下面的方式实现转发:</p><p><jsp:forward page=\"apage.jsp\" /></p><p>当然也可以在jsp页面中实现重定向:</p><p><%response.sendRedirect(\"new.jsp\"); %> //重定向到new.jsp</p><p> </p><div> <strong> 1.重定向:</strong></div><div> 1).response.sendRedirect(url);</div><div> 2).response.setState(302);</div><div> response.setHeader(\"location\",url);</div><div><strong> 2.转发:</strong></div><div> 1).request.getRequestDispatcher(url).forward(request,response);</div><div> 2).request.getRequestDispatcher(url).include(request,response);</div><div> 3).<jsp:forward page=url /></div>', '1', '8', '18', '0', '0', '0', '2017-10-07 16:03:08', '2017-10-07 16:03:08', '1', '1', '1'), ('16', '1', 'Java中File类的使用', '<h2>一、File类常用API介绍</h2><p>内容见代码和注释</p><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.File;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> * @author WellsLiu</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test {</li><li class=\"alt\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) {</li><li class=\"\"> <span class=\"comment\">//1.创建一个文件夹对象</span></li><li class=\"alt\"> File file = <span class=\"keyword\">new</span> File(<span class=\"string\">\"F:\\\\桌面\\\\music\"</span>);</li><li class=\"\"> <span class=\"comment\">//判断文件是否存在</span></li><li class=\"alt\"> System.out.println(file.exists());<span class=\"comment\">//true</span></li><li class=\"\"> <span class=\"comment\">//如果文件夹不存在创建之,否则删除之</span></li><li class=\"alt\"> <span class=\"keyword\">if</span>(!file.exists())</li><li class=\"\"> file.mkdir();<span class=\"comment\">//创建文件夹</span></li><li class=\"alt\"> <span class=\"comment\">//else </span></li><li class=\"\"> <span class=\"comment\">//file.delete();</span></li><li class=\"alt\"> <span class=\"comment\">//是否是一个目录</span></li><li class=\"\"> System.out.println(file.isDirectory());<span class=\"comment\">//true</span></li><li class=\"alt\"> <span class=\"comment\">//是否是一个文件</span></li><li class=\"\"> System.out.println(file.isFile());<span class=\"comment\">//false</span></li><li class=\"alt\"></li><li class=\"\"> <span class=\"comment\">//2.创建一个文件对象</span></li><li class=\"alt\"> File file2 = <span class=\"keyword\">new</span> File(<span class=\"string\">\"F:\\\\桌面\\\\music\\\\1.mp3\"</span>);</li><li class=\"\"> System.out.println(file.exists());</li><li class=\"alt\"> <span class=\"comment\">//如果文件不存在创建之,否则删除 之</span></li><li class=\"\"> <span class=\"keyword\">if</span>(file2.exists())</li><li class=\"alt\"> <span class=\"keyword\">try</span> {</li><li class=\"\"> file2.createNewFile();</li><li class=\"alt\"> } <span class=\"keyword\">catch</span> (IOException e) {</li><li class=\"\"> e.printStackTrace();</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"comment\">//else </span></li><li class=\"alt\"> <span class=\"comment\">//file2.delete();</span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//3.常用的File对象API</span></li><li class=\"\"> System.out.println(file);<span class=\"comment\">//file.toString()的内容,F:\\桌面\\music</span></li><li class=\"alt\"> System.out.println(file.getAbsolutePath());<span class=\"comment\">//file的绝对路径F:\\桌面\\music</span></li><li class=\"\"> System.out.println(file.getName());<span class=\"comment\">//music</span></li><li class=\"alt\"> System.out.println(file2.getName());<span class=\"comment\">//1.mp3</span></li><li class=\"\"> System.out.println(file.getParent());<span class=\"comment\">//F:\\桌面</span></li><li class=\"alt\"> }</li><li class=\"\">}</li></ol></div><p> </p><h2>二、遍历目录</h2><div class=\"dp-highlighter\"><div class=\"bar\"></div><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><span class=\"keyword\">package</span> com.liuyanzhao;</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">import</span> java.io.File;</li><li class=\"\"><span class=\"keyword\">import</span> java.io.IOException;</li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">/*</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> * @author WellsLiu</span></li><li class=\"alt\"><span class=\"comment\"> *</span></li><li class=\"\"><span class=\"comment\"> */</span></li><li class=\"alt\"></li><li class=\"\"><span class=\"comment\">//列出File类一些常用操作比如过滤、遍历等操作</span></li><li class=\"alt\"><span class=\"keyword\">class</span> FileUtils {</li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//列出指定目录下(包括子目录)的所有文件</span></li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> listDirectory(File dir) <span class=\"keyword\">throws</span> IOException{</li><li class=\"alt\"> <span class=\"keyword\">if</span>(!dir.exists()) {</li><li class=\"\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> IllegalArgumentException(<span class=\"string\">\"目录\"</span>+dir+<span class=\"string\">\"不存在\"</span>);</li><li class=\"alt\"> }</li><li class=\"\"> <span class=\"keyword\">if</span>(!dir.isDirectory()) { <span class=\"comment\">//判断File类的对象是否为文件夹</span></li><li class=\"alt\"> <span class=\"keyword\">throw</span> <span class=\"keyword\">new</span> IllegalArgumentException(dir+<span class=\"string\">\"不是目录\"</span>);</li><li class=\"\"> }</li><li class=\"alt\"> <span>/*</span></li><li class=\"\"><span class=\"comment\"> //1.输出dir目录下的一级文件夹和文件</span></li><li class=\"alt\"><span class=\"comment\"> String [] filenames = dir.list();//返回的是字符串数组 直接子名称</span></li><li class=\"\"><span class=\"comment\"> for (String string : filenames) {</span></li><li class=\"alt\"><span class=\"comment\"> System.out.println(dir+\"\\\\\"+string);//dirstring是文件或文件夹名</span></li><li class=\"\"><span class=\"comment\"> }</span></li><li class=\"alt\"><span class=\"comment\"> */</span></li><li class=\"\"></li><li class=\"alt\"> <span class=\"comment\">//2.如果要遍历子目录下的目录及所有文件,就需要构造File对象做递归操作</span></li><li class=\"\"> File[] files = dir.listFiles();<span class=\"comment\">//返回的是直接子目录(文件)的抽象</span></li><li class=\"alt\"> <span class=\"keyword\">if</span>(files!=<span class=\"keyword\">null</span>&&files.length><span class=\"number\">0</span>) {</li><li class=\"\"> <span class=\"keyword\">for</span>(File file:files) {</li><li class=\"alt\"> <span class=\"keyword\">if</span>(file.isDirectory()) {</li><li class=\"\"> <span class=\"comment\">//递归</span></li><li class=\"alt\"> listDirectory(file);</li><li class=\"\"> } <span class=\"keyword\">else</span> {</li><li class=\"alt\"> System.out.println(file);</li><li class=\"\"> }</li><li class=\"alt\"></li><li class=\"\"> }</li><li class=\"alt\"> }</li><li class=\"\"> }</li><li class=\"alt\">}</li><li class=\"\"></li><li class=\"alt\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> Test1 {</li><li class=\"\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> main(String[] args) <span class=\"keyword\">throws</span> IOException{</li><li class=\"alt\"> FileUtils.listDirectory(<span class=\"keyword\">new</span> File(\"C:\\\\Users\\\\Liu_Yanzhao\"));</li><li class=\"\"> }</li><li class=\"alt\">}</li></ol></div>', '1', '2', '1,17', '3', '0', '0', '2017-10-07 16:04:25', '2017-10-07 16:04:33', '1', '1', '1'), ('17', '1', 'java中ImageIcon路径问题', '<h2><strong>一、问题</strong></h2><p>ImageIcon icon = new ImageIcon(\"logo.jpg\");</p><p>执行结果是icon无法显示</p><p> </p><h2><strong>二、解决</strong></h2><p>类中有如下调用:</p><p><span>ImageIcon icon = new ImageIcon(\"1.jpg\");</span></p><p> </p><p>很自然地认为当前类文件和图片在同一路径下即可。</p><p><span><strong>其实所谓的相对路径起点是工程的根目录,即project。</strong></span></p><p>这行代码执行时在project目录下查找名为a.gif的文件,结果当然是找不到。</p><p>要得到工程的相对路径可通过System.getProperty(\"user.dir\")得到。</p><p>对图片和对文件的查找应该是一致的,如new File()。</p><p> </p><p>1、假如你的工程根目录为:Project1</p><p>你的图片文件放在:Project1/src/images/1.jpg</p><p>所以正确的调用是(不要加Project1):</p><p>ImageIcon icon = new ImageIcon(\"src/images/1.jpg\");</p><p> </p><p>2、假如你的工程根目录为:Project1</p><p>你的图片文件在:Project1/src/com.liuyanzhao/1.jpg</p><p>所以正确的调用是(<strong>com.liuyanzhao</strong>是包名)</p><p>ImageIcon icon = new ImageIcon(\"src/com/liuyanzhao/1.jpg\");</p><p>这行代码执行时在project/test目录下查找到了文件</p><p> </p><p><strong>总结起来就是一句话:所谓相对路径就是相对于工程根目录的位置^_^</strong></p><p> </p><h2>三、其他</h2><p>查看了一下ImageIcon的构造函数。</p><p>Public ImageIcon(String filename)//参数可以是绝对路径也可以是相对路径</p><p>Public ImageIcon(URL url)</p><p> </p><p>第一种构造不在赘述。</p><p>第二种通过URL来得到图片</p><p>URL url = getClass().getResource(\"a.gif\"); //当前编译后class文件所在目录查找</p><p>ImageIcon icon = new ImageIcon(url);</p><p> </p><p>ImageIcon支持GIF、JPG、PNG等格式。</p>', '1', '2', '1', '7', '2', '0', '2017-10-07 16:05:55', '2017-10-07 16:05:55', '1', '1', '1');
COMMIT;
-- ----------------------------
-- Table structure for `category`
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`category_id` int(5) unsigned NOT NULL AUTO_INCREMENT,
`category_pid` int(5) DEFAULT NULL,
`category_name` varchar(50) DEFAULT NULL,
`category_description` varchar(255) DEFAULT NULL,
`category_order` int(2) unsigned DEFAULT '1',
`category_icon` varchar(20) DEFAULT NULL,
`category_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`category_id`),
UNIQUE KEY `category_name` (`category_name`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `category`
-- ----------------------------
BEGIN;
INSERT INTO `category` VALUES ('1', '0', 'Java', 'Java语言', '1', 'fa fa-coffee', '1'), ('2', '1', 'Java基础', '', '1', '', '1'), ('3', '1', 'Core Java', '', '1', '', '1'), ('4', '1', '多线程并发编程', '', '1', '', '1'), ('5', '1', 'Sockets和IO', '', '1', '', '1'), ('6', '1', '设计模式和反射', '', '1', '', '1'), ('7', '1', 'JVM', '', '1', '', '1'), ('8', '1', 'JavaWeb', '', '1', '', '1'), ('9', '1', 'Java框架', '', '1', '', '1'), ('10', '0', '计算机科学', '', '1', 'fa fa-cubes', '1'), ('11', '10', '数据结构和算法', '', '1', '', '1'), ('12', '10', '操作系统', '', '1', '', '1'), ('13', '10', '数据库', '', '1', '', '1'), ('14', '10', '计算机网络', '', '1', '', '1'), ('15', '0', '其他技术', '', '1', 'fa-snowflake-o fa', '1'), ('16', '15', '消息服务', '', '1', '', '1'), ('17', '15', '缓存服务', '', '1', '', '1'), ('18', '15', '负载均衡', '', '1', '', '1');
COMMIT;
-- ----------------------------
-- Table structure for `comment`
-- ----------------------------
DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
`comment_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`comment_pid` int(10) unsigned DEFAULT '0',
`comment_pname` varchar(255) DEFAULT NULL,
`comment_article_id` int(10) unsigned DEFAULT NULL,
`comment_author_name` varchar(50) DEFAULT NULL,
`comment_author_email` varchar(50) DEFAULT NULL,
`comment_author_url` varchar(50) DEFAULT NULL,
`comment_content` varchar(1000) DEFAULT NULL,
`comment_agent` varchar(200) DEFAULT NULL,
`comment_ip` varchar(50) DEFAULT NULL,
`comment_create_time` datetime DEFAULT NULL,
`comment_role` int(2) DEFAULT NULL,
`comment_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`comment_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `comment`
-- ----------------------------
BEGIN;
INSERT INTO `comment` VALUES ('1', '0', '', '17', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '评论测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:06:34', '1', '1'), ('2', '1', '言曌', '17', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '再次测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:06:43', '1', '1'), ('3', '0', '', '8', '张三', '123@qq.com', '', '评论测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:08:06', '0', '1'), ('4', '0', '', '8', 'Tom', '123@126.com', '', 'Tom来测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:08:46', '0', '1'), ('5', '0', '', '14', 'Jack', '666@qq.com', '', 'Jack来此一游', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:09:27', '0', '1'), ('6', '5', 'Jack', '14', 'Jack', '666@qq.com', '', 'Jack回复Jack测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:10:10', '0', '1'), ('7', '5', 'Jack', '14', '娜美', '123456@sina.com', '', '娜美回复Jack测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:10:53', '0', '1'), ('8', '0', '', '9', '苏珊', '1212@sina.com', '', '苏珊来过', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:11:36', '0', '1'), ('9', '8', '苏珊', '9', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '欢迎苏珊', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:12:00', '1', '1'), ('10', '0', '', '10', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '博主测试', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:12:15', '1', '1'), ('11', '0', '', '13', '多伦', 'duolun@gmail.com', '', '多伦路过', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:13:09', '0', '1'), ('12', '0', '', '13', '贾克斯', 'jax@sohu.com', '', '我是贾克斯', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:13:44', '0', '1'), ('13', '12', '贾克斯', '13', '瑞克斯', 'ruikou@126.com', '', '贾克斯你好,我是瑞克斯', null, '0:0:0:0:0:0:0:1', '2017-10-07 16:14:32', '0', '1'), ('14', '0', '', '11', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '评论测试', null, '0:0:0:0:0:0:0:1', '2017-10-10 11:44:28', '1', '1'), ('15', '14', '言曌', '11', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '再次测试', null, '0:0:0:0:0:0:0:1', '2017-10-10 11:44:36', '1', '1');
COMMIT;
-- ----------------------------
-- Table structure for `link`
-- ----------------------------
DROP TABLE IF EXISTS `link`;
CREATE TABLE `link` (
`link_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`link_url` varchar(255) DEFAULT NULL,
`link_name` varchar(255) DEFAULT NULL,
`link_image` varchar(255) DEFAULT NULL,
`link_description` varchar(255) DEFAULT NULL,
`link_owner_nickname` varchar(40) DEFAULT NULL,
`link_owner_contact` varchar(255) DEFAULT NULL,
`link_update_time` datetime DEFAULT NULL,
`link_create_time` datetime DEFAULT NULL,
`link_order` int(2) unsigned DEFAULT '1',
`link_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`link_id`),
UNIQUE KEY `link_name` (`link_name`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `link`
-- ----------------------------
BEGIN;
INSERT INTO `link` VALUES ('1', 'http://liuyanzhao.com', '言曌博客', null, '一个码农的成长之路', null, '你好,我的丘丘是847064370', '2017-10-07 16:51:03', '2017-10-07 16:29:35', '1', '1'), ('6', 'http://liuyanzhao.com', '测试', null, '测试', null, '测试', '2017-10-07 16:51:49', '2017-10-07 16:51:49', '1', '0');
COMMIT;
-- ----------------------------
-- Table structure for `menu`
-- ----------------------------
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`menu_id` int(5) NOT NULL AUTO_INCREMENT,
`menu_name` varchar(255) DEFAULT NULL,
`menu_url` varchar(255) DEFAULT NULL,
`menu_level` int(2) DEFAULT NULL,
`menu_icon` varchar(255) DEFAULT NULL,
`menu_order` int(2) DEFAULT NULL,
`menu_status` int(2) DEFAULT '1',
PRIMARY KEY (`menu_id`),
UNIQUE KEY `menu_name` (`menu_name`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `menu`
-- ----------------------------
BEGIN;
INSERT INTO `menu` VALUES ('1', '留言板', '/message', '2', 'fa fa-comment', '1', '1'), ('2', 'LeetCode', 'https://leetcode.com/problemset/all', '2', '', '2', '1'), ('3', '关于本站', '/aboutSite', '1', 'fa fa-info', '1', '1'), ('4', '文章归档', '/articleFile', '1', 'fa-list-alt fa', '2', '1'), ('5', '申请友链', '/applyLink', '1', 'fa fa-link', '3', '1');
COMMIT;
-- ----------------------------
-- Table structure for `notice`
-- ----------------------------
DROP TABLE IF EXISTS `notice`;
CREATE TABLE `notice` (
`notice_id` int(10) NOT NULL AUTO_INCREMENT,
`notice_title` varchar(255) DEFAULT NULL,
`notice_content` varchar(10000) DEFAULT NULL,
`notice_create_time` datetime DEFAULT NULL,
`notice_update_time` datetime DEFAULT NULL,
`notice_status` int(2) unsigned DEFAULT '1',
`notice_order` int(2) DEFAULT NULL,
PRIMARY KEY (`notice_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `notice`
-- ----------------------------
BEGIN;
INSERT INTO `notice` VALUES ('1', '本站下载地址', '<p><span>本站后端基于 Spring+SpringMVC+Mybatis+JSP实现,对于初学SSM的小伙伴可以参考。</span></p><p><span>下载地址:</span><a target=\"_blank\" href=\"https://github.com/saysky/ForestBlog\">https://github.com/saysky/ForestBlog</a></p>', '2017-10-06 23:44:35', '2017-10-10 11:23:28', '1', '1');
COMMIT;
-- ----------------------------
-- Table structure for `options`
-- ----------------------------
DROP TABLE IF EXISTS `options`;
CREATE TABLE `options` (
`option_id` int(11) NOT NULL,
`option_site_title` varchar(255) DEFAULT NULL,
`option_site_descrption` varchar(255) DEFAULT NULL,
`option_meta_descrption` varchar(255) DEFAULT NULL,
`option_meta_keyword` varchar(255) DEFAULT NULL,
`option_aboutsite_avatar` varchar(255) DEFAULT NULL,
`option_aboutsite_title` varchar(255) DEFAULT NULL,
`option_aboutsite_content` varchar(255) DEFAULT NULL,
`option_aboutsite_wechat` varchar(255) DEFAULT NULL,
`option_aboutsite_qq` varchar(255) DEFAULT NULL,
`option_aboutsite_github` varchar(255) DEFAULT NULL,
`option_aboutsite_weibo` varchar(255) DEFAULT NULL,
`option_tongji` varchar(255) DEFAULT NULL,
`option_status` int(2) DEFAULT '1',
PRIMARY KEY (`option_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `options`
-- ----------------------------
BEGIN;
INSERT INTO `options` VALUES ('1', '风吟博客', '莫问收获,但问耕耘。', '风吟博客,一个简洁的Java博客,言曌程序学习的一个新起点。', '风吟,风吟博客,Java博客,SSM博客,言曌,言曌博客', '/uploads/2017/10/2017100622490186.png', '博客初心', '言曌程序学习的新起点,大学最后两年的成长记录。珍惜时间,保持努力的惯性。', '/uploads/2017/10/20171006224906122.jpg', '847064370', 'saysky', '5936412667', null, '1');
COMMIT;
-- ----------------------------
-- Table structure for `page`
-- ----------------------------
DROP TABLE IF EXISTS `page`;
CREATE TABLE `page` (
`page_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`page_key` varchar(50) DEFAULT NULL,
`page_title` varchar(50) DEFAULT NULL,
`page_content` mediumtext,
`page_create_time` datetime DEFAULT NULL,
`page_update_time` datetime DEFAULT NULL,
`page_view_count` int(10) unsigned DEFAULT '0',
`page_comment_count` int(5) unsigned DEFAULT '0',
`page_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`page_id`),
UNIQUE KEY `page_key` (`page_key`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `page`
-- ----------------------------
BEGIN;
INSERT INTO `page` VALUES ('1', 'map', '站点地图', null, null, null, '0', '0', '2'), ('2', 'articleFile', '文章归档', null, null, null, '0', '0', '2'), ('3', 'message', '留言板', null, null, null, '0', '0', '2'), ('4', 'applyLink', '申请友链', null, null, null, '0', '0', '2'), ('5', 'aboutSite', '关于本站', '<h2>关于项目</h2><p>该项目是博主暑假粗略学完 <a href=\"https://liuyanzhao.com/tag/ssm/\" title=\"查看与 SSM 相关的文章\" target=\"_blank\">SSM</a>(Spring+SpringMVC+Mybatis)后,开始着手做的一个博客系统。<br>主要涉及的包括 JSP,JSTL,EL表达式,MySQL,Druid连接池,Spring,SpringMVC,MyBatis 等。<br>前端采用Layui框架和扒了一个[网站](http://liuyanzhao.com)的前台样式。通过Maven管理依赖。</p><h2>效果预览</h2><p>预览地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=http://blog.liuyanzhao.com\" target=\"_blank\" rel=\"noopener noreferrer\">http://blog.liuyanzhao.com</a></p><p>前台效果图<br><img class=\"alignnone size-large wp-image-6348\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/front-1024x608.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/front-1024x608.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"1024\" height=\"608\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/front-1024x608.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/front-300x178.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/front-768x456.jpg 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"></p><p>后台效果图<br><img class=\"alignnone size-large wp-image-6349\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/back-1024x611.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/back-1024x611.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"1024\" height=\"611\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/back-1024x611.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/back-300x179.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/back-768x458.jpg 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"></p><p> </p><p><span>后台地址:/admin 或者 /login</span></p><p><span>用户名为admin,密码为123456</span></p><p> </p><h2>使用注意</h2><p><strong>1、使用IDE导入项目</strong></p><p>将项目即(ForestBlog文件夹)放到 某个位置,用IDE(如Eclipse,IntelliJ IDEA)导入,然后可以在IDE里运行 Tomcat,访问项目。</p><p>因为该项目使用了`Maven`,所有你需要新的IDE需要有Maven插件或者功能,这里就不多介绍了。</p><p><img class=\"size-large wp-image-6350 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog-517x1024.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog-517x1024.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"517\" height=\"1024\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog-517x1024.jpg 517w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog-151x300.jpg 151w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog.jpg 681w\" sizes=\"(max-width: 517px) 100vw, 517px\"></p><p><strong>2、 导入数据库</strong></p><p>新建数据库 `forest_blog`,导入数据库(即forest_blog.sql)。注意,数据库的编码和排序规则是utf-8和utf-8_general_ci</p><p><img class=\"size-full wp-image-6352 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog2.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog2.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"400\" height=\"540\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog2.jpg 400w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog2-222x300.jpg 222w\" sizes=\"(max-width: 400px) 100vw, 400px\"></p><p><strong>3、修改项目中的数据库连接信息</strong></p><p>修改 `db.properties` 文件,该文件很容易找到,在 src/main/resources 中,注意修改数据库地址、表名、用户名和密码。</p><p><span><strong>如果不修改,会出现无法启动项目</strong></span></p><p> </p><p><strong>4、修改上传文件路径</strong></p><p>该项目中,文件上传是传到本地,且和项目文件夹不在一起,就是说是分离的。比如你的项目是在D盘,你可以修改上传路径到E盘。当然我们访问上传的图片时,需要 给Tomcat添加静态资源映射,比如访问 localhost:8080/uplaods/1.jpg tomcat可以在你的E盘找到。这个在第5步会说。</p><p>现在是修改上传文件路径,该文件在 src/main/java/com/liuyanzhao/blog/controller/Common/UploadFileController.java</p><p>修改第33行的 `String rootPath =\"/www/uploads/\";` 为你的 uploads 的路径。</p><p><span><strong>如果不修改,会出现无法上传图片</strong></span></p><p> </p><p><strong>5、给uploads文件夹添加静态资源映射</strong></p><p>同第4步,我们已经修改了uploads路径,该路径就要和下面的docBase一致。<br>在 tomcat/conf/server.xml 的 Host 标签内添加如下代码</p><div class=\"dp-highlighter\"><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><Context path=<span class=\"string\">\"/uploads\"</span> docBase=<span class=\"string\">\"/www/uploads\"</span> debug=<span class=\"string\">\"0\"</span> reloadable=<span class=\"string\">\"true\"</span> /></li></ol></div><p>对啦,如果你使用的是IDE,需要在该IDE里修改。</p><p>比如 IntelliJ IDEA 是在Tomcat配置中添加</p><p><img class=\"alignnone size-large wp-image-6354\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4-1024x181.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4-1024x181.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"1024\" height=\"181\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4-1024x181.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4-300x53.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4-768x136.jpg 768w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog4.jpg 1426w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"></p><p><span><strong>如果不修改,会出现uploads的图片无法加载,网页打开有延迟</strong></span></p><p> </p><p><strong>6、修改 Tomcat的首页为该项目</strong></p><p>跟第5步相似</p><p>该项目中的所有根路径都是 / ,没有使用相对路径的 `${pagecontext.request.getcontextpath}` ,因为如何相对路径不存在,该值就会为空字符串,以致 首页链接我必须改为 / 。<br>所以,你的项目首页应该是 localhost:8080,而不是loclahost:8080/ForestBlog</p><p>所以要在 server.xml 的Host标签内里添加</p><div class=\"dp-highlighter\"><ol class=\"dp-j\" start=\"1\"><li class=\"alt\"><Context path=<span class=\"string\">\"\"</span> docBase=<span class=\"string\">\"/www/server/panel/vhost/tomcat/ForestBlog\"</span> debug=<span class=\"string\">\"0\"</span> reloadable=<span class=\"string\">\"true\"</span> /></li></ol></div><p>其中path=\"\"表示为首页,即localhost:8080或者127.0.0.1:8080<br>docBase-\"xxx\"是文件路径</p><p><img class=\"size-large wp-image-6355 aligncenter\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5-1024x134.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5-1024x134.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"1024\" height=\"134\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5-1024x134.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5-300x39.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5-768x101.jpg 768w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog5.jpg 1570w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"></p><p>对啦,如果你使用的是IDE,需要在该IDE里修改。</p><p>比如 IntelliJ IDEA 是在Tomcat配置中添加</p><p><img class=\"alignnone size-large wp-image-6353\" data-original=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3-1024x321.jpg\" src=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3-1024x321.jpg\" alt=\"一个简单漂亮的Java博客系统\" width=\"1024\" height=\"321\" srcset=\"https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3-1024x321.jpg 1024w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3-300x94.jpg 300w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3-768x241.jpg 768w, https://media.liuyanzhao.com/wp-content/uploads/2017/10/blog3.jpg 1428w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"></p><p><span><strong>如果不修改,会出现内页很多链接不对</strong></span></p><p> </p><h2>下载地址:</h2><p>Github地址:<a href=\"https://liuyanzhao.com/wp-content/themes/begin/inc/go.php?url=https://github.com/saysky/ForestBlog\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/saysky/ForestBlog</a></p><p><em>(如果可以帮忙点一次Star和Fork)</em></p><p> </p><h2>更新</h2><p>上一次更新:2017年10月10日14:02:02</p>', '2017-10-06 23:40:35', '2017-10-10 14:58:12', null, null, '1');
COMMIT;
-- ----------------------------
-- Table structure for `tag`
-- ----------------------------
DROP TABLE IF EXISTS `tag`;
CREATE TABLE `tag` (
`tag_id` int(5) unsigned NOT NULL AUTO_INCREMENT,
`tag_name` varchar(20) DEFAULT NULL,
`tag_description` varchar(255) DEFAULT NULL,
`tag_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`tag_id`),
UNIQUE KEY `tag_name` (`tag_name`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `tag`
-- ----------------------------
BEGIN;
INSERT INTO `tag` VALUES ('1', 'Java', '', '1'), ('2', '算法', '', '1'), ('3', '数据结构', '', '1'), ('4', 'C', '', '1'), ('5', '操作系统', '', '1'), ('6', '计算机网络', '', '1'), ('8', '面试题', '', '1'), ('9', '数据库', '', '1'), ('10', 'MySQL', '', '1'), ('11', 'Spring', '', '1'), ('12', 'SpringMVC', '', '1'), ('13', 'MyBatis', '', '1'), ('14', 'JVM', '', '1'), ('15', '设计模式', '', '1'), ('16', '网络编程', '', '1'), ('17', 'IO', '', '1'), ('18', 'JSP', '', '1'), ('19', 'Servlet', '', '1'), ('20', 'JavaWeb', '', '1'), ('21', 'Hibernate', '', '1'), ('22', 'SQL', '', '1');
COMMIT;
-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) NOT NULL DEFAULT '',
`user_pass` varchar(255) NOT NULL DEFAULT '',
`user_nickname` varchar(255) NOT NULL DEFAULT '',
`user_email` varchar(100) DEFAULT '',
`user_url` varchar(100) DEFAULT '',
`user_avatar` varchar(255) DEFAULT NULL,
`user_last_login_ip` varchar(255) DEFAULT NULL,
`user_register_time` datetime DEFAULT NULL,
`user_last_login_time` datetime DEFAULT NULL,
`user_status` int(2) unsigned DEFAULT '1',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_name` (`user_name`),
UNIQUE KEY `user_email` (`user_email`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of `user`
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES ('1', 'admin', '123456', '言曌', 'admin@liuyanzhao.com', 'https://liuyanzhao.com', '/uploads/2017/10/20171006225356181.jpg', '0:0:0:0:0:0:0:1', '2017-10-06 21:56:33', '2017-10-10 14:55:18', '1');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;