我的2019总结

每当我想写点什么的时候,我总是无从下笔,我想过许多事,但当我真的开始写是,我不知道该如何开始,这是我的2019年的总结,我眼里这不是普通的一年,2019年,我从高中生变成了大学生,做了我人生中第一件大人才能做的事:学会开车,拿到了属于我的驾驶证,学会了许多新知识.失去了我的18岁.

现在是2020.2.26 很早我就想写一个2019年的年度总结了.只是我不太知道,我该写点什么,或许也说不定是太懒了,这是一个迟来的年度总结,不过,这也不晚,回想去年这个时候,我还是呆在我现在这个房间里,写着作业,我还记得一年前那个百日誓师,也是我记忆中为数不多的高三回忆,

上半年我回忆不来多少,我只记得,1.23那天我爷爷去世了,我想起小时候和爷爷奶奶一起长大,我就这么看着,不知道该怎么办.我真的,不知道该怎么办,我想考上大学,让我爷爷看见,记忆中小时候都是爷爷带着我去学校.

高考后那天,……

我一直相信我能考上大学,高一刚入学那会.

看到背着书包骑着自行车的学生去上学,现在挺感慨的

现在我算是一个大学生了,告别了高中乏味的试卷和课堂,我这,大学真的自由,

经过了算是人生中最后一次的军训,虽然这个军训没有高中那么”好玩”,但也体会会了一些有趣的~

学了一个叫军体拳的东西,在干枯的草地上搞战术,也就是在地上爬,还有虫子在我手上爬,.

军训过得很快,之后我换了个专业,也认识了短暂的几个室友,挺有意思的一件事,我换了专业,这个寝室刚好变成我这个专业的的了,他们5个人只能搬走了,留下我这个换了专业,但是没换寝室,直到现在,我还是呆在我刚到这个学校选的那个床铺,在这个床上记录了我的上学期学习进步

大学不用学各种不喜欢的科目了,都说大学靠自学,之前多少有点怀疑,但直到我当我真的来到了这个学校.

暑假期间我学了C 和已经忘记差不多的Python,经过这一段时间的学习,我相信,好记性不如烂笔头,跟何况,我也没有那个好记性.

总结下来2019年这一年我算是在学习中度过,上半年我是个高三的学生,写着各种试卷,下半年算是沉迷在自己的学习计划中,暑假,学会了开车,自学计算机还行,暑假拿到了驾驶证,唯有高考,算是一个失败.

2020前两个月我算是在家中度过,又是我甚至能体会到躺尸的快乐,我并不想这样.

进过这段时间的学习,我认识到学习计划的重要性,我想,生活我也应该要有个计划,计划并不是说说就过去了,我得用文字记录,并去行动.我想2020能过成为我的一个转折点,想过许多高考后做的事没有完成,新的一年我也是大学生了.

新的一年,用计划去行动

JQuery快速入门笔记

  1. JQuery 基础:
    1. 概念
    2. 快速入门
    3. JQuery对象和JS对象区别与转换
    4. 选择器
    5. DOM操作
    6. 案例

JQuery 基础:

概念:

一个JavaScript框架。简化JS开发
    * jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨    是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优    化HTML文档操作、事件处理、动画设计和Ajax交互。

    * JavaScript框架:本质上就是一些js文件,封装了js的原生代码而已
## 快速入门
    1. 步骤:
        1. 下载JQuery
            * 目前jQuery有三个大版本:
                1.x:兼容ie678,使用最为广泛的,官方只做BUG维护,
                     功能不再新增。因此一般项目来说,使用1.x版本就可以了,
                     最终版本:1.12.4 (2016年5月20日)
                2.x:不兼容ie678,很少有人使用,官方只做BUG维护,
                     功能不再新增。如果不考虑兼容低版本的浏览器可以使用2.x,
                     最终版本:2.2.4 (2016年5月20日)
                3.x:不兼容ie678,只支持最新的浏览器。除非特殊要求,
                     一般不会使用3.x版本的,很多老的jQuery插件不支持这个版本。
                     目前该版本是官方主要更新维护的版本。最新版本:3.2.1(2017年3月20日)
            * jquery-xxx.js 与 jquery-xxx.min.js区别:
                1. jquery-xxx.js:开发版本。给程序员看的,有良好的缩进和注释。体积大一些
                2. jquery-xxx.min.js:生产版本。程序中使用,没有缩进。体积小一些。程序加载更快

        2. 导入JQuery的js文件:导入min.js文件
        3. 使用
            var div1 = $("#div1");
            alert(div1.html());

JQuery对象和JS对象区别与转换

1. JQuery对象在操作时,更加方便。
2. JQuery对象和js对象方法不通用的.
3. 两者相互转换
    * jq -- > js : jq对象[索引] 或者 jq对象.get(索引)
    * js -- > jq : $(js对象)

选择器:筛选具有相似特征的元素(标签)

1. 基本操作学习:
    1. 事件绑定
        //1.获取b1按钮
        $("#b1").click(function(){
            alert("abc");
        });
    2. 入口函数
         $(function () {

            });
         window.onload  和 $(function) 区别
             * window.onload 只能定义一次,如果定义多次,后边的会将前边的覆盖掉
             * $(function)可以定义多次的。
    3. 样式控制:css方法
         // $("#div1").css("background-color","red");
          $("#div1").css("backgroundColor","pink");


2. 分类
    1. 基本选择器
        1. 标签选择器(元素选择器)
            * 语法: $("html标签名") 获得所有匹配标签名称的元素
        2. id选择器 
            * 语法: $("#id的属性值") 获得与指定id属性值匹配的元素
        3. 类选择器
            * 语法: $(".class的属性值") 获得与指定的class属性值匹配的元素
        4. 并集选择器:
            * 语法: $("选择器1,选择器2....") 获取多个选择器选中的所有元素
    2. 层级选择器
        1. 后代选择器
            * 语法: $("A B ") 选择A元素内部的所有B元素        
        2. 子选择器
            * 语法: $("A > B") 选择A元素内部的所有B子元素
    3. 属性选择器
        1. 属性名称选择器 
            * 语法: $("A[属性名]") 包含指定属性的选择器
        2. 属性选择器
            * 语法: $("A[属性名='值']") 包含指定属性等于指定值的选择器
        3. 复合属性选择器
            * 语法: $("A[属性名='值'][]...") 包含多个属性条件的选择器
    4. 过滤选择器
        1. 首元素选择器 
            * 语法: :first 获得选择的元素中的第一个元素
        2. 尾元素选择器 
            * 语法: :last 获得选择的元素中的最后一个元素
        3. 非元素选择器
            * 语法: :not(selector) 不包括指定内容的元素
        4. 偶数选择器
            * 语法: :even 偶数,从 0 开始计数
        5. 奇数选择器
            * 语法: :odd 奇数,从 0 开始计数
        6. 等于索引选择器
            * 语法: :eq(index) 指定索引元素
        7. 大于索引选择器 
            * 语法: :gt(index) 大于指定索引元素
        8. 小于索引选择器 
            * 语法: :lt(index) 小于指定索引元素
        9. 标题选择器
            * 语法: :header 获得标题(h1~h6)元素,固定写法
    5. 表单过滤选择器
        1. 可用元素选择器 
            * 语法: :enabled 获得可用元素
        2. 不可用元素选择器 
            * 语法: :disabled 获得不可用元素
        3. 选中选择器 
            * 语法: :checked 获得单选/复选框选中的元素
        4. 选中选择器 
            * 语法: :selected 获得下拉框选中的元素

DOM操作

1. 内容操作
    1. html(): 获取/设置元素的标签体内容   <a><font>内容</font></a>  --> <font>内容</font>
    2. text(): 获取/设置元素的标签体纯文本内容   <a><font>内容</font></a> --> 内容
    3. val(): 获取/设置元素的value属性值
2. 属性操作
    1. 通用属性操作
        1. attr(): 获取/设置元素的属性
        2. removeAttr():删除属性
        3. prop():获取/设置元素的属性
        4. removeProp():删除属性

        * attr和prop区别?
            1. 如果操作的是元素的固有属性,则建议使用prop
            2. 如果操作的是元素自定义的属性,则建议使用attr
    2. 对class属性操作
        1. addClass():添加class属性值
        2. removeClass():删除class属性值
        3. toggleClass():切换class属性
            * toggleClass("one"): 
                * 判断如果元素对象上存在class="one",则将属性值one删除掉。  如果元素对象上不存在class="one",则添加
        4. css():
3. CRUD操作:
    1. append():父元素将子元素追加到末尾
        * 对象1.append(对象2): 将对象2添加到对象1元素内部,并且在末尾
    2. prepend():父元素将子元素追加到开头
        * 对象1.prepend(对象2):将对象2添加到对象1元素内部,并且在开头
    3. appendTo():
        * 对象1.appendTo(对象2):将对象1添加到对象2内部,并且在末尾
    4. prependTo():
        * 对象1.prependTo(对象2):将对象1添加到对象2内部,并且在开头


    5. after():添加元素到元素后边
        * 对象1.after(对象2): 将对象2添加到对象1后边。对象1和对象2是兄弟关系
    6. before():添加元素到元素前边
        * 对象1.before(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系
    7. insertAfter()
        * 对象1.insertAfter(对象2):将对象2添加到对象1后边。对象1和对象2是兄弟关系
    8. insertBefore()
        * 对象1.insertBefore(对象2): 将对象2添加到对象1前边。对象1和对象2是兄弟关系

    9. remove():移除元素
        * 对象.remove():将对象删除掉
    10. empty():清空元素的所有后代元素。
        * 对象.empty():将对象的后代元素全部清空,但是保留当前对象以及其属性节点

JQuery 高级

动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1. 三种方式显示和隐藏元素
1. 默认显示和隐藏方式
1. show([speed,[easing],[fn]])
1. 参数:
1. speed:动画的速度。三个预定义的值("slow","normal", "fast")或表示动画时长的毫秒数值(如:1000)
2. easing:用来指定切换效果,默认是"swing",可用参数"linear"
* swing:动画执行时效果是 先慢,中间快,最后又慢
* linear:动画执行时速度是匀速的
3. fn:在动画完成时执行的函数,每个元素执行一次。

2. hide([speed,[easing],[fn]])
3. toggle([speed],[easing],[fn])

2. 滑动显示和隐藏方式
1. slideDown([speed],[easing],[fn])
2. slideUp([speed,[easing],[fn]])
3. slideToggle([speed],[easing],[fn])

3. 淡入淡出显示和隐藏方式
1. fadeIn([speed],[easing],[fn])
2. fadeOut([speed],[easing],[fn])
3. fadeToggle([speed,[easing],[fn]])

遍历

1. js的遍历方式
    * for(初始化值;循环结束条件;步长)
2. jq的遍历方式
    1. jq对象.each(callback)
        1. 语法:
            jquery对象.each(function(index,element){});
                * index:就是元素在集合中的索引
                * element:就是集合中的每一个元素对象

                * this:集合中的每一个元素对象
        2. 回调函数返回值:
            * true:如果当前function返回为false,则结束循环(break)。
            * false:如果当前function返回为true,则结束本次循环,继续下次循环(continue)
    2. $.each(object, [callback])
    3. for..of: jquery 3.0 版本之后提供的方式
        for(元素对象 of 容器对象)

事件绑定

1. jquery标准的绑定方式
    * jq对象.事件方法(回调函数);
    * 注:如果调用事件方法,不传递回调函数,则会触发浏览器默认行为。
        * 表单对象.submit();//让表单提交
2. on绑定事件/off解除绑定
    * jq对象.on("事件名称",回调函数)
    * jq对象.off("事件名称")
        * 如果off方法不传递任何参数,则将组件上的所有事件全部解绑
3. 事件切换:toggle
    * jq对象.toggle(fn1,fn2...)
        * 当单击jq对象对应的组件后,会执行fn1.第二次点击会执行fn2.....

    * 注意:1.9版本 .toggle() 方法删除,jQuery Migrate(迁移)插件可以恢复此功能。
         <script src="../js/jquery-migrate-1.0.0.js" type="text/javascript" charset="utf-8"></script>

案例

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
1. 广告显示和隐藏
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>广告的自动显示与隐藏</title>
<style>
#content{width:100%;height:500px;background:#999}
</style>

<!--引入jquery-->
<script type="text/javascript" src="../js/jquery-3.3.1.min.js"></script>
<script>
/*
需求:
1. 当页面加载完,3秒后。自动显示广告
2. 广告显示5秒后,自动消失。

分析:
1. 使用定时器来完成。setTimeout (执行一次定时器)
2. 分析发现JQuery的显示和隐藏动画效果其实就是控制display
3. 使用 show/hide方法来完成广告的显示
*/

//入口函数,在页面加载完成之后,定义定时器,调用这两个方法
$(function () {
//定义定时器,调用adShow方法 3秒后执行一次
setTimeout(adShow,3000);
//定义定时器,调用adHide方法,8秒后执行一次
setTimeout(adHide,8000);
});
//显示广告
function adShow() {
//获取广告div,调用显示方法
$("#ad").show("slow");
}
//隐藏广告
function adHide() {
//获取广告div,调用隐藏方法
$("#ad").hide("slow");
}




</script>
</head>
<body>
<!-- 整体的DIV -->
<div>
<!-- 广告DIV -->
<div id="ad" style="display: none;">
<img style="width:100%" src="../img/adv.jpg" />
</div>

<!-- 下方正文部分 -->
<div id="content">
正文部分
</div>
</div>
</body>
</html>



2. 抽奖
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jquery案例之抽奖</title>
<script type="text/javascript" src="../js/jquery-3.3.1.min.js"></script>

<script language='javascript' type='text/javascript'>

/*
分析:
1. 给开始按钮绑定单击事件
1.1 定义循环定时器
1.2 切换小相框的src属性
* 定义数组,存放图片资源路径
* 生成随机数。数组索引



2. 给结束按钮绑定单击事件
1.1 停止定时器
1.2 给大相框设置src属性

*/
var imgs = ["../img/man00.jpg",
"../img/man01.jpg",
"../img/man02.jpg",
"../img/man03.jpg",
"../img/man04.jpg",
"../img/man05.jpg",
"../img/man06.jpg",
];
var startId;//开始定时器的id
var index;//随机角标
$(function () {
//处理按钮是否可以使用的效果
$("#startID").prop("disabled",false);
$("#stopID").prop("disabled",true);



//1. 给开始按钮绑定单击事件
$("#startID").click(function () {
// 1.1 定义循环定时器 20毫秒执行一次
startId = setInterval(function () {
//处理按钮是否可以使用的效果
$("#startID").prop("disabled",true);
$("#stopID").prop("disabled",false);



//1.2生成随机角标 0-6
index = Math.floor(Math.random() * 7);
//0.000--0.999 --> * 7 --> 0.0-----6.9999
//1.3设置小相框的src属性
$("#img1ID").prop("src",imgs[index]);

},20);
});



//2. 给结束按钮绑定单击事件
$("#stopID").click(function () {
//处理按钮是否可以使用的效果
$("#startID").prop("disabled",false);
$("#stopID").prop("disabled",true);



// 1.1 停止定时器
clearInterval(startId);
// 1.2 给大相框设置src属性
$("#img2ID").prop("src",imgs[index]).hide(); //显示1秒之后
$("#img2ID").show(1000);
});
});





</script>

</head>
<body>

<!-- 小像框 -->
<div style="border-style:dotted;width:160px;height:100px">
<img id="img1ID" src="../img/man00.jpg" style="width:160px;height:100px"/>
</div>

<!-- 大像框 -->
<div
style="border-style:double;width:800px;height:500px;position:absolute;left:500px;top:10px">
<img id="img2ID" src="../img/man00.jpg" width="800px" height="500px"/>
</div>

<!-- 开始按钮 -->
<input
id="startID"
type="button"
value="点击开始"
style="width:150px;height:150px;font-size:22px">

<!-- 停止按钮 -->
<input
id="stopID"
type="button"
value="点击停止"
style="width:150px;height:150px;font-size:22px">



</body>
</html>

插件:增强JQuery的功能

1. 实现方式:
    1. $.fn.extend(object) 
        * 增强通过Jquery获取的对象的功能  $("#id")
    2. $.extend(object)
        * 增强JQeury对象自身的功能  $/jQuery

Java案例文档-j2ee旅游网综合案例笔记

《黑马旅游网》综合案例

1 前言

为了巩固web基础知识,提升综合运用能力.

2 项目导入

点击绿色+按钮

image-20200212163116894

选择travel项目的pom.xml文件,点击ok,完成项目导入。需要等待一小会,项目初始化完成。

image-20200212163128210

3 启动项目

3.1 方式一:

image-20200212163139143

3.2 方式二:配置maven快捷启动

image-20200212163147580

image-20200212163154300

4 技术选型

4.1 Web层

a) Servlet:前端控制器

b) html:视图

c) Filter:过滤器

d) BeanUtils:数据封装

e) Jackson:json序列化工具

4.2 Service层

f) Javamail:java发送邮件工具

g) Redis:nosql内存数据库

h) Jedis:java的redis客户端

4.3 Dao层

i) Mysql:数据库

j) Druid:数据库连接池

k) JdbcTemplate:jdbc的工具

5 创建数据库

– 创建数据库

CREATE DATABASE travel;

– 使用数据库

USE travel;

–创建表

​ 复制提供好的sql

6 注册功能

6.1 页面效果

image-20200212163208403

6.2 功能分析

image-20200212163214358

6.3 代码实现

6.3.1 前台代码实现

6.3.2 表单校验

​ 提升用户体验,并减轻服务器压力。

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
//校验用户名
//单词字符,长度8到20位
**function** *checkUsername*() {
//1.获取用户名值
**var** username = **$**(**"#username"**).val();
//2.定义正则
**var** reg_username = /^\w{8,20}$/;

//3.判断,给出提示信息
**var** flag = reg_username.test(username);
**if**(flag){
//用户名合法
**$**(**"#username"**).css(**"border"**,**""**);
}**else**{
//用户名非法,加一个红色边框
**$**(**"#username"**).css(**"border"**,**"1px solid red"**);
}

​ **return** flag;
​ }

​ //校验密码
​ **function** *checkPassword*() {
​ //1.获取密码值
​ **var** password = **$**(**"#password"**).val();
​ //2.定义正则
​ **var** reg_password = /^\w{8,20}$/;

​ //3.判断,给出提示信息
​ **var** flag = reg_password.test(password);
​ **if**(flag){
​ //密码合法
​ **$**(**"#password"**).css(**"border"**,**""**);
​ }**else**{
​ //密码非法,加一个红色边框
​ **$**(**"#password"**).css(**"border"**,**"1px solid red"**);
​ }

​ **return** flag;
​ }

​ //校验邮箱
**function** *checkEmail*(){
//1.获取邮箱
**var** email = **$**(**"#email"**).val();
//2.定义正则 itcast@163.com
**var** reg_email = /^\w+@\w+\.\w+$/;

//3.判断
**var** flag = reg_email.test(email);
**if**(flag){
**$**(**"#email"**).css(**"border"**,**""**);
}**else**{
**$**(**"#email"**).css(**"border"**,**"1px solid red"**);
}

**return** flag;
}

**$**(**function** () {
//当表单提交时,调用所有的校验方法
**$**(**"#registerForm"**).submit(**function**(){

​ **return** *checkUsername*() && *checkPassword*() && *checkEmail*();
​ //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
});

​ //当某一个组件失去焦点是,调用对应的校验方法
​ **$**(**"#username"**).blur(*checkUsername*);
​ **$**(**"#password"**).blur(*checkPassword*);
​ **$**(**"#email"**).blur(*checkEmail*);

​ });

6.3.3 异步(ajax)提交表单

​ 在此使用异步提交表单是为了获取服务器响应的数据。因为我们前台使用的是html作为视图层,不能够直接从servlet相关的域对象获取值,只能通过ajax获取响应数据

image-20200212163236844

6.3.4 后台代码实现

6.3.5 编写RegistUserServlet

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
@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


//验证校验
String check = request.getParameter("check");
//从sesion中获取验证码
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
//比较
if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
//验证码错误
ResultInfo info = new ResultInfo();
//注册失败
info.setFlag(false);
info.setErrorMsg("验证码错误");
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}

//1.获取数据
Map<String, String[]> map = request.getParameterMap();

//2.封装对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

//3.调用service完成注册
UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
//4.响应结果
if(flag){
//注册成功
info.setFlag(true);
}else{
//注册失败
info.setFlag(false);
info.setErrorMsg("注册失败!");
}

//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);

//将json数据写回客户端
//设置content-type
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);


}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

6.3.6 编写UserService以及UserServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class UserServiceImpl implements UserService {

private UserDao userDao = new UserDaoImpl();
/**
* 注册用户
* @param user
* @return
*/
@Override
public boolean regist(User user) {
//1.根据用户名查询用户对象
User u = userDao.findByUsername(user.getUsername());
//判断u是否为null
if(u != null){
//用户名存在,注册失败
return false;
}
//2.保存用户信息
userDao.save(user);
return true;
}
}

6.3.7 编写UserDao以及UserDaoImpl

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
public class UserDaoImpl implements UserDao {

private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

@Override
public User findByUsername(String username) {
User user = null;
try {
//1.定义sql
String sql = "select * from tab_user where username = ?";
//2.执行sql
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
} catch (Exception e) {

}

return user;
}

@Override
public void save(User user) {
//1.定义sql
String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email) values(?,?,?,?,?,?,?)";
//2.执行sql

template.update(sql,user.getUsername(),
user.getPassword(),
user.getName(),
user.getBirthday(),
user.getSex(),
user.getTelephone(),
user.getEmail());
}
}

6.3.8 邮件激活

​ 为什么要进行邮件激活?为了保证用户填写的邮箱是正确的。将来可以推广一些宣传信息,到用户邮箱中。

6.3.9 发送邮件

\1. 申请邮箱

\2. 开启授权码

\3. 在MailUtils中设置自己的邮箱账号和密码(授权码)

img

1
2
 
邮件工具类:MailUtils,调用其中sendMail方法可以完成邮件发送

6.3.10 用户点击邮件激活

经过分析,发现,用户激活其实就是修改用户表中的status为‘Y’

img

分析:

img

发送邮件代码:

img

修改保存Dao代码,加上存储status和code 的代码逻辑

img

激活代码实现:

ActiveUserServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.获取激活码
String code = request.getParameter("code");
if(code != null){
//2.调用service完成激活
UserService service = new UserServiceImpl();
boolean flag = service.active(code);

//3.判断标记
String msg = null;
if(flag){
//激活成功
msg = "激活成功,请<a href='login.html'>登录</a>";
}else{
//激活失败
msg = "激活失败,请联系管理员!";
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(msg);

UserService:active

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public boolean active(String code) {
//1.根据激活码查询用户对象
User user = userDao.findByCode(code);
if(user != null){
//2.调用dao的修改激活状态的方法
userDao.updateStatus(user);
return true;
}else{
return false;
}

}

UserDao:findByCode updateStatus

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
/**
* 根据激活码查询用户对象
* @param code
* @return
*/
@Override
public User findByCode(String code) {
User user = null;
try {
String sql = "select * from tab_user where code = ?";

user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),code);
} catch (DataAccessException e) {
e.printStackTrace();
}

return user;
}

/**
* 修改指定用户激活状态
* @param user
*/
@Override
public void updateStatus(User user) {
String sql = " update tab_user set status = 'Y' where uid=?";
template.update(sql,user.getUid());
}

7 登录

7.1 分析

img

7.2 代码实现

7.2.1 前台代码

img

7.2.2 后台代码

LoginServlet

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
//1.获取用户名和密码数据
Map<String, String[]> map = request.getParameterMap();
//2.封装User对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

//3.调用Service查询
UserService service = new UserServiceImpl();
User u = service.login(user);

ResultInfo info = new ResultInfo();

//4.判断用户对象是否为null
if(u == null){
//用户名密码或错误
info.setFlag(false);
info.setErrorMsg("用户名密码或错误");
}
//5.判断用户是否激活
if(u != null && !"Y".equals(u.getStatus())){
//用户尚未激活
info.setFlag(false);
info.setErrorMsg("您尚未激活,请激活");
}
//6.判断登录成功
if(u != null && "Y".equals(u.getStatus())){
//登录成功
info.setFlag(true);
}

//响应数据
ObjectMapper mapper = new ObjectMapper();

response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),info);

UserService

1
2
3
public User login(User user) {
return userDao.findByUsernameAndPassword(user.getUsername(),user.getPassword());
}

UserDao

1
2
3
4
5
6
7
8
9
10
11
12
13
public User findByUsernameAndPassword(String username, String password) {
User user = null;
try {
//1.定义sql
String sql = "select * from tab_user where username = ? and password = ?";
//2.执行sql
user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username,password);
} catch (Exception e) {

}

return user;
}

7.2.3 index页面中用户姓名的提示信息功能

效果:

img

header.html代码

img

Servlet代码

1
2
3
4
5
6
7
//从session中获取登录用户
Object user = request.getSession().getAttribute("user");
//将user写回客户端

ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);

8 退出

什么叫做登录了?session中有user对象。

实现步骤:

\1. 访问servlet,将session销毁

\2. 跳转到登录页面

代码实现:

​ Header.htmlimg

Servlet:

1
2
3
4
5
//1.销毁session
request.getSession().invalidate();

//2.跳转登录页面
response.sendRedirect(request.getContextPath()+"/login.html");

9 优化Servlet

9.1 目的

减少Servlet的数量,现在是一个功能一个Servlet,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。

img

Idea控制台中文乱码解决:-Dfile.encoding=gb2312

img

9.2 BaseServlet编写:

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
        public class BaseServlet extends HttpServlet {


@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//System.out.println("baseServlet的service方法被执行了...");

//完成方法分发
//1.获取请求路径
String uri = req.getRequestURI(); // /travel/user/add
System.out.println("请求uri:"+uri);// /travel/user/add
//2.获取方法名称
String methodName = uri.substring(uri.lastIndexOf('/') + 1);
System.out.println("方法名称:"+methodName);
//3.获取方法对象Method
//谁调用我?我代表谁
System.out.println(this);//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
try {
//获取方法
Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射
//method.setAccessible(true);
method.invoke(this,req,resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}


}
}

9.3 UserServlet改写

将之前的Servlet实现的功能,抽取到UserServlet中的不同方法中实现,并且将UserService创建抽取到成员变量位置

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
@WebServlet("/user/*") // /user/add /user/find
public class UserServlet extends BaseServlet {

//声明UserService业务对象
private UserService service = new UserServiceImpl();

/**
* 注册功能
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//验证校验
String check = request.getParameter("check");
//从sesion中获取验证码
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
//比较
if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
//验证码错误
ResultInfo info = new ResultInfo();
//注册失败
info.setFlag(false);
info.setErrorMsg("验证码错误");
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return;
}

//1.获取数据
Map<String, String[]> map = request.getParameterMap();

//2.封装对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

//3.调用service完成注册
//UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
//4.响应结果
if(flag){
//注册成功
info.setFlag(true);
}else{
//注册失败
info.setFlag(false);
info.setErrorMsg("注册失败!");
}

//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);

//将json数据写回客户端
//设置content-type
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);

}

/**
* 登录功能
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取用户名和密码数据
Map<String, String[]> map = request.getParameterMap();
//2.封装User对象
User user = new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

//3.调用Service查询
// UserService service = new UserServiceImpl();
User u = service.login(user);

ResultInfo info = new ResultInfo();

//4.判断用户对象是否为null
if(u == null){
//用户名密码或错误
info.setFlag(false);
info.setErrorMsg("用户名密码或错误");
}
//5.判断用户是否激活
if(u != null && !"Y".equals(u.getStatus())){
//用户尚未激活
info.setFlag(false);
info.setErrorMsg("您尚未激活,请激活");
}
//6.判断登录成功
if(u != null && "Y".equals(u.getStatus())){
request.getSession().setAttribute("user",u);//登录成功标记

//登录成功
info.setFlag(true);
}

//响应数据
ObjectMapper mapper = new ObjectMapper();

response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),info);
}

/**
* 查询单个对象
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从session中获取登录用户
Object user = request.getSession().getAttribute("user");
//将user写回客户端

ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);
}

/**
* 退出功能
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.销毁session
request.getSession().invalidate();

//2.跳转登录页面
response.sendRedirect(request.getContextPath()+"/login.html");
}

/**
* 激活功能
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取激活码
String code = request.getParameter("code");
if(code != null){
//2.调用service完成激活
//UserService service = new UserServiceImpl();
boolean flag = service.active(code);

//3.判断标记
String msg = null;
if(flag){
//激活成功
msg = "激活成功,请<a href='login.html'>登录</a>";
}else{
//激活失败
msg = "激活失败,请联系管理员!";
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(msg);
}
}
}

9.4 页面路径改写

register.html

img

login.html

img

header.html

img

UserServiceImpl发送邮件

img

10 分类数据展示

10.1 效果:

img

10.2 分析:

img

10.3 代码实现:

10.3.1 后台代码

CategoryServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@WebServlet("/category/*")
public class CategoryServlet extends BaseServlet {

private CategoryService service = new CategoryServiceImpl();

/**
* 查询所有
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用service查询所有
List<Category> cs = service.findAll();
//2.序列化json返回
/* ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),cs);*/
writeValue(cs,response);

}

}

CategoryService
java

1
2
3
4
5
6
7
8
9
public class CategoryServiceImpl implements CategoryService {

private CategoryDao categoryDao = new CategoryDaoImpl();

@Override
public List<Category> findAll() {
return categoryDao.findAll();
}
}

CategoryDao

1
2
3
4
5
6
7
8
9
10
public class CategoryDaoImpl implements CategoryDao {

private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

@Override
public List<Category> findAll() {
String sql = "select * from tab_category ";
return template.query(sql,new BeanPropertyRowMapper<Category>(Category.class));
}
}

在BaseServlet中封装了序列化json的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 直接将传入的对象序列化为json,并且写回客户端
* @param obj
*/
public void writeValue(Object obj,HttpServletResponse response) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),obj);
}

/**
* 将传入的对象序列化为json,返回
* @param obj
* @return
*/
public String writeValueAsString(Object obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(obj);
}

10.3.2 前台代码

hader.html加载后,发送ajax请求,请求category/findAll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//查询分类数据
$.get("category/findAll",{},function (data) {
//[{cid:1,cname:国内游},{},{}]
var lis = '<li class="nav-active"><a href="index.html">首页</a></li>';
//遍历数组,拼接字符串(<li>)
for (var i = 0; i < data.length; i++) {
var li = '<li><a href="route_list.html">'+data[i].cname+'</a></li>';

lis += li;

}
//拼接收藏排行榜的li,<li><a href="favoriterank.html">收藏排行榜</a></li>

lis+= '<li><a href="favoriterank.html">收藏排行榜</a></li>';

//将lis字符串,设置到ul的html内容中
$("#category").html(lis);
});

10.4 对分类数据进行缓存优化

分析发现,分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。

分析:

img

10.5 优化代码实现

期望数据中存储的顺序就是将来展示的顺序,使用redis的sortedset

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
@Override
public List<Category> findAll() {
//1.从redis中查询
//1.1获取jedis客户端
Jedis jedis = JedisUtil.getJedis();
//1.2可使用sortedset排序查询
Set<String> categorys = jedis.zrange("category", 0, -1);
List<Category> cs = null;
//2.判断查询的集合是否为空
if (categorys == null || categorys.size() == 0) {

System.out.println("从数据库查询....");
//3.如果为空,需要从数据库查询,在将数据存入redis
//3.1 从数据库查询
cs = categoryDao.findAll();
//3.2 将集合数据存储到redis中的 category的key
for (int i = 0; i < cs.size(); i++) {

jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname());
}
} else {
System.out.println("从redis中查询.....");

//4.如果不为空,将set的数据存入list
cs = new ArrayList<Category>();
for (String name : categorys) {
Category category = new Category();
category.setCname(name);
cs.add(category);

}
}


return cs;
}

11 旅游线路的分页展示

点击了不同的分类后,将来看到的旅游线路不一样的。通过分析数据库表结构,发现,旅游线路表和分类表时一个多对一的关系

img

查询不同分类的旅游线路sql

Select * from tab_route where cid = ?;

11.1 类别id的传递

Redis中查询score(cid)

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
public class CategoryServiceImpl implements CategoryService {

private CategoryDao categoryDao = new CategoryDaoImpl();

@Override
public List<Category> findAll() {
//1.从redis中查询
//1.1获取jedis客户端
Jedis jedis = JedisUtil.getJedis();
//1.2可使用sortedset排序查询
//Set<String> categorys = jedis.zrange("category", 0, -1);
//1.3查询sortedset中的分数(cid)和值(cname)
Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);

List<Category> cs = null;
//2.判断查询的集合是否为空
if (categorys == null || categorys.size() == 0) {

System.out.println("从数据库查询....");
//3.如果为空,需要从数据库查询,在将数据存入redis
//3.1 从数据库查询
cs = categoryDao.findAll();
//3.2 将集合数据存储到redis中的 category的key
for (int i = 0; i < cs.size(); i++) {

jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname());
}
} else {
System.out.println("从redis中查询.....");

//4.如果不为空,将set的数据存入list
cs = new ArrayList<Category>();
for (Tuple tuple : categorys) {
Category category = new Category();
category.setCname(tuple.getElement());
category.setCid((int)tuple.getScore());
cs.add(category);

}
}


return cs;
}
}

页面传递cid

header.html传递cid

1
var li = '<li><a href="route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>';

获取cid

1
2
3
4
5
6
$(function () {
var search = location.search;
//alert(search);//?id=5
// 切割字符串,拿到第二个值
var cid = search.split("=")[1];
});

11.2 根据id查询不同类别的旅游线路数据

分页展示旅游线路数据:

11.2.1 分析

img

11.2.2 编码

\1. 客户端代码编写

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
$(function () {
var search = location.search;
// 切割字符串,拿到第二个值
var cid = search.split("=")[1];

//当页码加载完成后,调用load方法,发送ajax请求加载数据
load(cid);
});

function load(cid ,currentPage){
//发送ajax请求,请求route/pageQuery,传递cid
$.get("route/pageQuery",{cid:cid,currentPage:currentPage},function (pb) {
//解析pagebean数据,展示到页面上

//1.分页工具条数据展示
//1.1 展示总页码和总记录数
$("#totalPage").html(pb.totalPage);
$("#totalCount").html(pb.totalCount);

var lis = "";

var fristPage = '<li onclick="javascipt:load('+cid+')"><a href="javascript:void(0)">首页</a></li>';

//计算上一页的页码
var beforeNum = pb.currentPage - 1;
if(beforeNum <= 0){
beforeNum = 1;
}

var beforePage = '<li onclick="javascipt:load('+cid+','+beforeNum+')" class="threeword"><a href="javascript:void(0)">上一页</a></li>';

lis += fristPage;
lis += beforePage;
//1.2 展示分页页码
/*
1.一共展示10个页码,能够达到前5后4的效果
2.如果前边不够5个,后边补齐10个
3.如果后边不足4个,前边补齐10个
*/

// 定义开始位置begin,结束位置 end
var begin; // 开始位置
var end ; // 结束位置


//1.要显示10个页码
if(pb.totalPage < 10){
//总页码不够10页

begin = 1;
end = pb.totalPage;
}else{
//总页码超过10页

begin = pb.currentPage - 5 ;
end = pb.currentPage + 4 ;

//2.如果前边不够5个,后边补齐10个
if(begin < 1){
begin = 1;
end = begin + 9;
}

//3.如果后边不足4个,前边补齐10个
if(end > pb.totalPage){
end = pb.totalPage;
begin = end - 9 ;
}
}


for (var i = begin; i <= end ; i++) {
var li;
//判断当前页码是否等于i
if(pb.currentPage == i){

li = '<li class="curPage" onclick="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';

}else{
//创建页码的li
li = '<li onclick="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
}
//拼接字符串
lis += li;
}





var lastPage = '<li class="threeword"><a href="javascript:;">末页</a></li>';
var nextPage = '<li class="threeword"><a href="javascript:;">下一页</a></li>';

lis += nextPage;
lis += lastPage;


//将lis内容设置到 ul
$("#pageNum").html(lis);




//2.列表数据展示
var route_lis = "";

for (var i = 0; i < pb.list.length; i++) {
//获取{rid:1,rname:"xxx"}
var route = pb.list[i];

var li = '<li>\n' +
' <div class="img"><img src="'+route.rimage+'" style="width: 299px;"></div>\n' +
' <div class="text1">\n' +
' <p>'+route.rname+'</p>\n' +
' <br/>\n' +
' <p>'+route.routeIntroduce+'</p>\n' +
' </div>\n' +
' <div class="price">\n' +
' <p class="price_num">\n' +
' <span>&yen;</span>\n' +
' <span>'+route.price+'</span>\n' +
' <span>起</span>\n' +
' </p>\n' +
' <p><a href="route_detail.html">查看详情</a></p>\n' +
' </div>\n' +
' </li>';
route_lis += li;
}
$("#route").html(route_lis);

//定位到页面顶部
window.scrollTo(0,0);
});

}

\2. 服务器端代码编写

a) 创建PageBean对象

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
public class PageBean<T> {

private int totalCount;//总记录数
private int totalPage;//总页数
private int currentPage;//当前页码
private int pageSize;//每页显示的条数

private List<T> list;//每页显示的数据集合

public int getTotalCount() {
return totalCount;
}

public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}

public int getTotalPage() {
return totalPage;
}

public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}

public int getCurrentPage() {
return currentPage;
}

public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}

public int getPageSize() {
return pageSize;
}

public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}

public List<T> getList() {
return list;
}

public void setList(List<T> list) {
this.list = list;
}
}

b) RouteServlet

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
@WebServlet("/route/*")
public class RouteServlet extends BaseServlet {

private RouteService routeService = new RouteServiceImpl();

/**
* 分页查询
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.接受参数
String currentPageStr = request.getParameter("currentPage");
String pageSizeStr = request.getParameter("pageSize");
String cidStr = request.getParameter("cid");

int cid = 0;//类别id
//2.处理参数
if(cidStr != null && cidStr.length() > 0){
cid = Integer.parseInt(cidStr);
}
int currentPage = 0;//当前页码,如果不传递,则默认为第一页
if(currentPageStr != null && currentPageStr.length() > 0){
currentPage = Integer.parseInt(currentPageStr);
}else{
currentPage = 1;
}

int pageSize = 0;//每页显示条数,如果不传递,默认每页显示5条记录
if(pageSizeStr != null && pageSizeStr.length() > 0){
pageSize = Integer.parseInt(pageSizeStr);
}else{
pageSize = 5;
}

//3. 调用service查询PageBean对象
PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize);

//4. 将pageBean对象序列化为json,返回
writeValue(pb,response);

}

}

c) RouteService

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
public class RouteServiceImpl implements RouteService {
private RouteDao routeDao = new RouteDaoImpl();
@Override
public PageBean<Route> pageQuery(int cid, int currentPage, int pageSize) {
//封装PageBean
PageBean<Route> pb = new PageBean<Route>();
//设置当前页码
pb.setCurrentPage(currentPage);
//设置每页显示条数
pb.setPageSize(pageSize);

//设置总记录数
int totalCount = routeDao.findTotalCount(cid);
pb.setTotalCount(totalCount);
//设置当前页显示的数据集合
int start = (currentPage - 1) * pageSize;//开始的记录数
List<Route> list = routeDao.findByPage(cid,start,pageSize);
pb.setList(list);

//设置总页数 = 总记录数/每页显示条数
int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize :(totalCount / pageSize) + 1 ;
pb.setTotalPage(totalPage);


return pb;
}
}

d) RouteDao

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class RouteDaoImpl implements RouteDao {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

@Override
public int findTotalCount(int cid) {
String sql = "select count(*) from tab_route where cid = ?";
return template.queryForObject(sql,Integer.class,cid);
}

@Override
public List<Route> findByPage(int cid, int start, int pageSize) {
String sql = "select * from tab_route where cid = ? limit ? , ?";

return template.query(sql,new BeanPropertyRowMapper<Route>(Route.class),cid,start,pageSize);
}
}

SSM整合-SpringMVC+Spring+Mybatis

SpringMVC第三天

第一章:搭建整合环境

1. 搭建整合环境

  1. 整合说明:SSM整合可以使用多种方式,咱们会选择XML + 注解的方式

  2. 整合的思路

    1. 先搭建整合的环境

    2. 先把Spring的配置搭建完成

    3. 再使用Spring整合SpringMVC框架

    4. 最后使用Spring整合MyBatis框架

  3. 创建数据库和表结构

    1. 语句
      1
      2
      3
      4
      5
      6
      7
      create database ssm;
      use ssm;
      create table account(
      id int primary key auto_increment,
      name varchar(20),
      money double
      )
  4. 创建maven的工程(今天会使用到工程的聚合和拆分的概念,这个技术maven高级会讲)

    1. 创建ssm_parent父工程(打包方式选择pom,必须的)

    2. 创建ssm_web子模块(打包方式是war包)

    3. 创建ssm_service子模块(打包方式是jar包)

    4. 创建ssm_dao子模块(打包方式是jar包)

    5. 创建ssm_domain子模块(打包方式是jar包)

    6. web依赖于service,service依赖于dao,dao依赖于domain

    7. 在ssm_parent的pom.xml文件中引入坐标依赖

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      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
      <properties>
      <spring.version>5.0.2.RELEASE</spring.version>
      <slf4j.version>1.6.6</slf4j.version>
      <log4j.version>1.2.12</log4j.version>
      <mysql.version>5.1.6</mysql.version>
      <mybatis.version>3.4.5</mybatis.version>
      </properties>
      <dependencies>
      <!-- spring -->
      <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.6.8</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
      </dependency>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
      </dependency>
      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
      </dependency>
      <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
      </dependency>
      <!-- log start -->
      <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
      </dependency>
      <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
      </dependency>
      <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
      </dependency>
      <!-- log end -->
      <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
      </dependency>
      <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.0</version>
      </dependency>
      <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      </dependencies>
      <build>
      <finalName>ssm</finalName>
      <pluginManagement>
      <plugins>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.2</version>
      <configuration>
      <source>1.8</source>
      <target>1.8</target>
      <encoding>UTF-8</encoding>
      <showWarnings>true</showWarnings>
      </configuration>
      </plugin>
      </plugins>
      </pluginManagement>
      </build>

  5. 部署ssm_web的项目,只要把ssm_web项目加入到tomcat服务器中即可

  6. 编写实体类,在ssm_domain项目中编写

    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
    import java.io.Serializable;


    public class Account implements Serializable {
    private static final long serialVersionUID = 7355810572012650248L;
    private Integer id;
    private String name;
    private Double money;

    public Integer getId() {
    return id;
    }

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

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public Double getMoney() {
    return money;
    }

    public void setMoney(Double money) {
    this.money = money;
    }
    }

  7. 编写dao接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import cn.itcast.domain.Account;

    import java.util.List;


    public interface AccountDao {
    public void saveAccount(Account account);

    public List<Account> findAll();
    }

  8. 编写service接口和实现类

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

import java.util.List;
import cn.itcast.domain.Account;
public interface AccountService {
public void saveAccount(Account account);
public List<Account> findAll();
}




import java.util.List;
import org.springframework.stereotype.Service;
import cn.itcast.dao.AccountDao;
import cn.itcast.domain.Account;
import cn.itcast.service.AccountService;
@Service("accountService")
public class AccountServiceImpl implements AccountService {
private AccountDao account;
public void saveAccount(Account account) {
}
public List<Account> findAll() {
System.out.println("业务层:查询所有账户...");
return null;
}
}

第二章:Spring框架代码的编写

  1. 搭建和测试Spring的开发环境
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="UTF-8"?>
    <beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 开启注解扫描,要扫描的是service和dao层的注解,要忽略web层注解,因为web层让SpringMVC框架去管理 -->
    <context:component-scan base-package="cn.itcast">
    <!-- 配置要忽略的注解 -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    </beans>

  2. 在ssm_web项目中编写测试方法,进行测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import cn.itcast.service.AccountService;

    import org.junit.Test;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;


    public class ServiceTest {
    @Test
    public void run1() {
    ApplicationContext ac = new ClassPathXmlApplicationContext(
    "classpath:applicationContext.xml");
    AccountService as = (AccountService) ac.getBean("accountService");
    as.findAll();
    }
    }

    第三章:Spring整合SpringMVC框架

1. 搭建和测试SpringMVC的开发环境

  1. 在web.xml中配置DispatcherServlet前端控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 配置前端控制器:服务器启动必须加载,需要加载springmvc.xml配置文件 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置初始化参数,创建完DispatcherServlet对象,加载springmvc.xml配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 服务器启动的时候,让DispatcherServlet对象创建 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
  1. 在web.xml中配置DispatcherServlet过滤器解决中文乱码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!-- 配置解决中文乱码的过滤器 -->
    <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

  2. 创建springmvc.xml的配置文件,编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?xml version="1.0" encoding="UTF-8"?>
    <beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 扫描controller的注解,别的不扫描 -->
    <context:component-scan base-package="cn.itcast">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- JSP文件所在的目录 -->
    <property name="prefix" value="/WEB-INF/pages/" />
    <!-- 文件的后缀名 -->
    <property name="suffix" value=".jsp" />
    </bean>
    <!-- 设置静态资源不过滤 -->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="../images/" mapping="../images/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <!-- 开启对SpringMVC注解的支持 -->
    <mvc:annotation-driven />
    </beans>
  3. 测试SpringMVC的框架搭建是否成功

    1. 编写index.jsp和list.jsp编写,超链接
      1
      <a href="account/findAll">查询所有</a>
    2. 创建AccountController类,编写方法,进行测试
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import org.springframework.stereotype.Controller;

      import org.springframework.web.bind.annotation.RequestMapping;


      @Controller
      @RequestMapping("/account")
      public class AccountController {
      /**
      * 查询所有的数据
      * @return
      */
      @RequestMapping("/findAll")
      public String findAll() {
      System.out.println("表现层:查询所有账户...");

      return "list";
      }
      }

      2. Spring整合SpringMVC的框架

  4. 目的:在controller中能成功的调用service对象中的方法。

  5. 在项目启动的时候,就去加载applicationContext.xml的配置文件,在web.xml中配置

1
2
3
4
5
6
7
8
9
<!-- 配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listenerclass>
</listener>
<!-- 配置加载类路径的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
  1. 在controller中注入service对象,调用service对象的方法进行测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    @Controller
    @RequestMapping("/account")
    public class AccountController {
    @Autowired
    private AccountService accoutService;

    /**
    * 查询所有的数据
    * @return
    */
    @RequestMapping("/findAll")
    public String findAll() {
    System.out.println("表现层:查询所有账户...");
    accoutService.findAll();

    return "list";
    }
    }

    第四章:Spring整合MyBatis框架

1. 搭建和测试MyBatis的环境

  1. 在web项目中编写SqlMapConfig.xml的配置文件,编写核心配置文件

    image-20200210210222275

  2. 在AccountDao接口的方法上添加注解,编写SQL语句

    image-20200210210239023

  3. 编写测试的方法

    image-20200210210321291

2. Spring整合MyBatis框架

  1. 目的:把SqlMapConfig.xml配置文件中的内容配置到applicationContext.xml配置文件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 配置连接池对象 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///ssm" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>

<!-- 配置SqlSession的工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置扫描dao的包 -->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.itcast.dao"/>
</bean>
  1. 在AccountDao接口中添加@Repository注解

  2. 在service中注入dao对象,进行测试

  3. 代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    @Repository
    public interface AccountDao {
    @Insert( value = "insert into account (name,money) values (#{name},#{money})" )
    public void saveAccount( Account account );


    @Select( "select * from account" )
    public List<Account> findAll();
    }





    @Service( "accountService" )
    public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    public void saveAccount( Account account )
    {
    }


    public List<Account> findAll()
    {
    System.out.println( "业务层:查询所有账户..." );
    return(accountDao.findAll() );
    }
    }





    @Controller
    @RequestMapping( "/account" )
    public class AccountController {
    @Autowired
    private AccountService accoutService;
    /**
    * 查询所有的数据
    * @return
    */
    @RequestMapping( "/findAll" )
    public String findAll()
    {
    System.out.println( "表现层:查询所有账户..." );
    List<Account> list = accoutService.findAll();
    for ( Account account : list )
    {
    System.out.println( account );
    }
    return("list");
    }
    }

  4. 配置Spring的声明式事务管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--配置Spring框架声明式事务管理-->
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>

<!--配置AOP增强-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.itcast.service.impl.*ServiceImpl.*(..))"/>
</aop:config>

SpringMVC-02返回值类型-响应数据-文件上传

SpringMVC框架第二天

第一章:响应数据和结果视图

1. 返回值分类

返回字符串

  1. Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
1
2
3
4
5
6
@RequestMapping(value="/hello")
public String sayHello() {
System.out.println("Hello SpringMVC!!");
// 跳转到XX页面
return "success";
}
  1. 具体的应用场景
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
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 请求参数的绑定
*/
@RequestMapping(value="/initUpdate")
public String initUpdate(Model model) {
// 模拟从数据库中查询的数据
User user = new User();
user.setUsername("张三");
user.setPassword("123");
user.setMoney(100d);
user.setBirthday(new Date());
model.addAttribute("user", user);
return "update";
}
}



<h3>修改用户</h3>
${ requestScope }
<form action="user/update" method="post">
姓名:<input type="text" name="username" value="${ user.username }"><br>
密码:<input type="text" name="password" value="${ user.password }"><br>
金额:<input type="text" name="money" value="${ user.money }"><br>
<input type="submit" value="提交">
</form>

返回值是void

  1. 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。

    1. 默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。

    2. 可以使用请求转发或者重定向跳转到指定的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping(value="/initAdd")
public void initAdd(HttpServletRequest request,HttpServletResponse response) throws Exception {
System.out.println("请求转发或者重定向");
// 请求转发
request.getRequestDispatcher("/WEBINF/pages/add.jsp").forward(request,response);
// 重定向
// response.sendRedirect(request.getContextPath()+"/add2.jsp");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 直接响应数据
response.getWriter().print("你好");
return;
}

返回值是ModelAndView对象

  1. ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

  2. 具体的代码如下

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
/**
* 返回ModelAndView对象
* 可以传入视图的名称(即跳转的页面),还可以传入对象。
* @return
* @throws Exception
*/
@RequestMapping(value="/findAll")
public ModelAndView findAll() throws Exception {
ModelAndView mv = new ModelAndView();
// 跳转到list.jsp的页面
mv.setViewName("list");
// 模拟从数据库中查询所有的用户信息
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setUsername("张三");
user1.setPassword("123");
User user2 = new User();
user2.setUsername("赵四");
user2.setPassword("456");
users.add(user1);
users.add(user2);
// 添加对象
mv.addObject("users", users);
return mv;
}
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>查询所有的数据</h3>
<c:forEach items="${ users }" var="user">
${ user.username }
</c:forEach>
</body>
</html>

2. SpringMVC框架提供的转发和重定向

forward请求转发

  1. controller方法返回String类型,想进行请求转发也可以编写成
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 使用forward关键字进行请求转发
* "forward:转发的JSP路径",不走视图解析器了,所以需要编写完整的路径
* @return
* @throws Exception
*/
@RequestMapping("/delete")
public String delete() throws Exception {
System.out.println("delete方法执行了...");
// return "forward:/WEB-INF/pages/success.jsp";
return "forward:/user/findAll";
}

redirect重定向

  1. controller方法返回String类型,想进行重定向也可以编写成
1
2
3
4
5
6
7
8
9
10
11
/**
* 重定向
* @return
* @throws Exception
*/
@RequestMapping("/count")
public String count() throws Exception {
System.out.println("count方法执行了...");
return "redirect:/add.jsp";
// return "redirect:/user/findAll";
}

3. ResponseBody响应json数据

  1. DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置

    1. mvc:resources标签配置不过滤
      1. location元素表示webapp目录下的包下的所有文件
      2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
        1
        2
        3
        4
        5
        6
        7
        <!-- 设置静态资源不过滤 -->
        <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
        <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
        <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->

        //
        <mvc:default-servlet-handler />
  2. 使用@RequestBody获取请求体数据

    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
    // 页面加载
    // 页面加载
    $(function(){
    // 绑定点击事件
    $("#btn").click(function(){
    $.ajax({
    url:"user/testJson",
    contentType:"application/json;charset=UTF-8",
    data:'{"addressName":"aa","addressNum":100}',
    dataType:"json",
    type:"post",
    success:function(data){
    alert(data);
    alert(data.addressName);
    }
    });
    });
    });





    /**
    * 获取请求体的数据
    * @param body
    */
    @RequestMapping("/testJson")
    public void testJson(@RequestBody String body) {
    System.out.println(body);
    }

  3. 使用@RequestBody注解把json的字符串转换成JavaBean的对象

    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
    // 页面加载
    $(function(){
    // 绑定点击事件
    $("#btn").click(function(){
    $.ajax({
    url:"user/testJson",
    contentType:"application/json;charset=UTF-8",
    data:'{"addressName":"aa","addressNum":100}',
    dataType:"json",
    type:"post",
    success:function(data){
    alert(data);
    alert(data.addressName);
    }
    });
    });
    });



    /**
    * 获取请求体的数据
    * @param body
    */
    @RequestMapping("/testJson")
    public void testJson(@RequestBody Address address) {
    System.out.println(address);
    }
  4. 使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
    要求方法需要返回JavaBean的对象,在返回类型上加注解

    1
    2
    3
    4
    5
    6
    @RequestMapping("/testJson")
    public @ResponseBody Address testJson(@RequestBody Address address) {
    System.out.println(address);
    address.setAddressName("上海");
    return address;
    }
  1. json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.0</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.0</version>
    </dependency>

    第二章:SpringMVC实现文件上传

1. 文件上传的回顾

  1. 导入文件上传的jar包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
    </dependency>
    <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
    </dependency>
  2. 编写文件上传的JSP页面

    1
    2
    3
    4
    5
    <h3>文件上传</h3>
    <form action="user/fileupload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"/><br/>
    <input type="submit" value="上传文件"/>
    </form>
  3. 编写文件上传的Controller控制器

    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
    /**
    * 文件上传
    * @throws Exception
    */
    @RequestMapping(value = "/fileupload") public String fileupload(HttpServletRequest request) throws Exception {
    // 先获取到要上传的文件目录
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建File对象,一会向该路径下上传文件
    File file = new File(path);
    // 判断路径是否存在,如果不存在,创建该路径
    if (!file.exists()) {
    file.mkdirs();
    }
    // 创建磁盘文件项工厂
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    // 解析request对象
    List < FileItem > list = fileUpload.parseRequest(request);
    // 遍历
    for (FileItem fileItem: list) {
    // 判断文件项是普通字段,还是上传的文件
    if (fileItem.isFormField()) {} else {
    // 上传文件项
    // 获取到上传文件的名称
    String filename = fileItem.getName();
    // 上传文件
    fileItem.write(new File(file, filename));
    // 删除临时文件
    fileItem.delete();
    }
    }
    return "success";
    }

    2. SpringMVC传统方式文件上传

  4. SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。

  5. 代码如下

    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
    /**
    * SpringMVC方式的文件上传
    *
    * @param request
    * @return
    * @throws Exception
    */
    @RequestMapping(value = "/fileupload2") public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
    System.out.println("SpringMVC方式的文件上传...");
    // 先获取到要上传的文件目录
    String path = request.getSession().getServletContext().getRealPath("/uploads");
    // 创建File对象,一会向该路径下上传文件
    File file = new File(path);
    // 判断路径是否存在,如果不存在,创建该路径
    if (!file.exists()) {
    file.mkdirs();
    }
    // 获取到上传文件的名称
    String filename = upload.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    // 把文件的名称唯一化
    filename = uuid + "_" + filename;
    // 上传文件
    upload.transferTo(new File(file, filename));
    return "success";
    }
  6. 配置文件解析器对象

    1
    2
    3
    4
    5
    6
    <?xml version="1.0" encoding="utf-8"?>

    <!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"/>
    </bean>

    3. SpringMVC跨服务器方式文件上传

  7. 搭建图片服务器

    1. 根据文档配置tomcat9的服务器,现在是2个服务器

    2. 导入资料中day02_springmvc5_02image项目,作为图片服务器使用

  8. 实现SpringMVC跨服务器方式文件上传

    1. 导入开发需要的jar包
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
      <version>1.18.1</version>
      </dependency>
      <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.18.1</version>
      </dependency>
    2. 编写文件上传的JSP页面
      1
      2
      3
      4
      5
      <h3>跨服务器的文件上传</h3>
      <form action="user/fileupload3" method="post" enctype="multipart/form-data">
      选择文件:<input type="file" name="upload"/><br/>
      <input type="submit" value="上传文件"/>
      </form>
    3. 编写控制器
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      /**
      * SpringMVC跨服务器方式的文件上传
      *
      * @param request
      * @return
      * @throws Exception
      */
      @RequestMapping(value = "/fileupload3") public String fileupload3(MultipartFile upload) throws Exception {
      System.out.println("SpringMVC跨服务器方式的文件上传...");
      // 定义图片服务器的请求路径
      String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
      // 获取到上传文件的名称
      String filename = upload.getOriginalFilename();
      String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
      // 把文件的名称唯一化
      filename = uuid + "_" + filename;
      // 向图片服务器上传文件
      // 创建客户端对象
      Client client = Client.create();
      // 连接图片服务器
      WebResource webResource = client.resource(path + filename);
      // 上传文件
      webResource.put(upload.getBytes());
      return "success";
      }

      第三章:SpringMVC的异常处理

1. 异常处理思路

1.Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进行异常的处理。

2. SpringMVC的异常处理

  1. 自定义异常类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class SysException extends Exception{
    private static final long serialVersionUID = 4055945147128016300L;
    // 异常提示信息
    private String message;
    public String getMessage() {
    return message;
    }
    public void setMessage(String message) {
    this.message = message;
    }
    public SysException(String message) {
    this.message = message;
    }
    }
  2. 自定义异常处理器
    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
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    /**
    * 异常处理器
    * @author rt
    */
    public class SysExceptionResolver implements HandlerExceptionResolver {
    /**
    * 跳转到具体的错误页面的方法
    */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    ex.printStackTrace();
    SysException e = null;
    // 获取到异常对象
    if (ex instanceof SysException) {
    e = (SysException) ex;
    } else {
    e = new SysException("请联系管理员");
    }
    ModelAndView mv = new ModelAndView();
    // 存入错误的提示信息
    mv.addObject("message", e.getMessage());
    // 跳转的Jsp页面
    mv.setViewName("error");
    return mv;
    }
    }
  3. 配置异常处理器
    1
    2
    <!-- 配置异常处理器 -->
    <bean id="sysExceptionResolver" class="cn.xxhoz.exception.SysExceptionResolver"/>

    第四章:SpringMVC框架中的拦截器

1. 拦截器的概述

  1. SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。

  2. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。

  3. 拦截器和过滤器的功能比较类似,有区别

    1. 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。

    2. 拦截器是SpringMVC框架独有的。

    3. 过滤器配置了/*,可以拦截任何资源。

    4. 拦截器只会对控制器中的方法进行拦截。

  4. 拦截器也是AOP思想的一种实现方式

  5. 想要自定义拦截器,需要实现HandlerInterceptor接口。

2. 自定义拦截器步骤

  1. 创建类,实现HandlerInterceptor接口,重写需要的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.HandlerInterceptor;
    /**
    * 自定义拦截器1
    * @author rt
    */
    public class MyInterceptor1 implements HandlerInterceptor {
    /**
    * controller方法执行前,进行拦截的方法
    * return true放行
    * return false拦截
    * 可以使用转发或者重定向直接跳转到指定的页面。
    */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("拦截器执行了...");
    return true;
    }
    }
  2. 在springmvc.xml中配置拦截器类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- 配置拦截器 -->
    <mvc:interceptors>
    <mvc:interceptor>
    <!-- 哪些方法进行拦截 -->
    <mvc:mapping path="/user/*"/>
    <!-- 哪些方法不进行拦截-->
    <mvc:exclude-mapping path=""/>
    <!-- 注册拦截器对象 -->
    <bean class="cn.itcast.demo1.MyInterceptor1"/>
    </mvc:interceptor>
    </mvc:interceptors>

    3. HandlerInterceptor接口中的方法

  3. preHandle方法是controller方法执行前拦截的方法

    1. 可以使用request或者response跳转到指定的页面

    2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。

    3. return false不放行,不会执行controller中的方法。

  4. postHandle是controller方法执行后执行的方法,在JSP视图执行前。

    1. 可以使用request或者response跳转到指定的页面

    2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。

  5. postHandle方法是在JSP执行后执行

    1. request或者response不能再跳转页面了

4. 配置多个拦截器

  1. 再编写一个拦截器的类

  2. 配置2个拦截器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- 配置拦截器 -->
    <mvc:interceptors>
    <mvc:interceptor>
    <!-- 哪些方法进行拦截 -->
    <mvc:mapping path="/user/*"/>
    <!-- 哪些方法不进行拦截-->
    <mvc:exclude-mapping path=""/>
    <!-- 注册拦截器对象 -->
    <bean class="cn.itcast.demo1.MyInterceptor1"/>
    </mvc:interceptor>
    <mvc:interceptor>
    <!-- 哪些方法进行拦截 -->
    <mvc:mapping path="/**"/>
    <!-- 注册拦截器对象 -->
    <bean class="cn.itcast.demo1.MyInterceptor2"/>
    </mvc:interceptor>
    </mvc:interceptors>

Html案例小记录

LOGO SEO优化:

1
2
3
4
5
<div class="logo">
<h1>
<a href="index.html" title="品优购商城">品优购商城</a>
</h1>
</div>

可设置输入框选择无边光

1
outline:none 

CSS3盒子模型

1
box-sizing:border-box   

精灵图

1
background:url("../images/icons.png") no-repeat -19px -15px;    

超出文字显示省略号:

1
2
3
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;

块元素.垂直居中

1
vertical-align:middle;

label与输入框绑定,当点击label时会选中焦点

1
2
3
4
<1i>
<label for="name">Name:</Label>
<input id="name"type="text">
</1i>

SpringMVC-01入门-参数绑定-常用注解

SpringMVC框架第一天,课程学习笔记

第一章:三层架构和MVC

1. 三层架构

  1. 咱们开发服务器端程序,一般都基于两种形式,一种C/S架构程序,一种B/S架构程序

  2. 使用Java语言基本上都是开发B/S架构的程序,B/S架构又分成了三层架构

  3. 三层架构

    1. 表现层:WEB层,用来和客户端进行数据交互的。表现层一般会采用MVC的设计模型

    2. 业务层:处理公司具体的业务逻辑的

    3. 持久层:用来操作数据库的

2. MVC模型

  1. MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。

  2. Model:数据模型,JavaBean的类,用来进行数据封装。

  3. View:指JSP、HTML用来展示数据给用户

  4. Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。

第二章:SpringMVC的入门案例

1. SpringMVC的概述(查看大纲文档)

  1. SpringMVC的概述

    1. 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。

    2. Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。

    3. 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的

SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。

  1. SpringMVC在三层架构中的位置

    1. 表现层框架
  2. SpringMVC的优势

  3. SpringMVC和Struts2框架的对比

SpringMVC核心构架:

image-20200209114823733

2. SpringMVC的入门程序

  1. 创建WEB工程,引入开发的jar包

    1. 具体的坐标如下
      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
        <!-- 版本锁定 -->    
      <properties>
      <spring.version>5.0.2.RELEASE</spring.version>
      </properties>

      <dependencies>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
      </dependency>

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
      </dependency>

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
      </dependency>

      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
      </dependency>

      <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
      </dependency>
      </dependencies>

  2. 配置核心的控制器(配置DispatcherServlet)

    1. 在web.xml配置文件中核心控制器DispatcherServlet

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
       <!-- SpringMVC的核心控制器 -->
      <servlet>
      <servlet-name>dispatcherServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass>
      <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
      <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
      </init-param>
      <!-- 配置servlet启动时加载对象 -->
      <load-on-startup>1</load-on-startup>
      </servlet>

      <servlet-mapping>
      <servlet-name>dispatcherServlet</servlet-name>
      <url-pattern>/</url-pattern>
      </servlet-mapping>

  3. 编写springmvc.xml的配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!-- 配置视图解析器 -->
    <bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>

    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>
    </beans>
  1. 编写index.jsp和HelloController控制器类

    1. index.jsp

      1
      2
      3
      4
      <body>
      <h3>入门案例</h3>
      <a href="${ pageContext.request.contextPath }/hello">入门案例</a>
      </body>
    2. HelloController

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      package cn.itcast.controller;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      /**
      * 控制器
      * @author rt
      */
      @Controller
      public class HelloController {
      /**
      * 接收请求
      * @return
      */
      @RequestMapping(path="/hello")
      public String sayHello() {
      System.out.println("Hello SpringMVC!!");
      return "success";
      }
      }
  1. 在WEB-INF目录下创建pages文件夹,编写success.jsp的成功页面

    1
    2
    3
    <body>
    <h3>入门成功!!</h3>
    </body>
  1. 启动Tomcat服务器,进行测试

3. 入门案例的执行过程分析

  1. 入门案例的执行流程

    1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载springmvc.xml配置文件

    2. 开启了注解扫描,那么HelloController对象就会被创建

    3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解找到执行的具体方法

    4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件

    5. Tomcat服务器渲染页面,做出响应

  2. SpringMVC官方提供图形

  3. 入门案例中的组件分析

    1. 前端控制器(DispatcherServlet)

    2. 处理器映射器(HandlerMapping)

    3. 处理器(Handler)

    4. 处理器适配器(HandlAdapter)

    5. 视图解析器(View Resolver)

    6. 视图(View)

4. RequestMapping注解

  1. RequestMapping:

    注解的作用是建立请求URL和处理方法之间的对应关系

  2. RequestMapping注解可以作用在方法和类上

    1. 作用在类上:第一级的访问目录

    2. 作用在方法上:第二级的访问目录

    3. 细节:路径可以不编写表示应用的根目录开始

    4. 细节:${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写

  3. RequestMapping的属性

    1. path 指定请求路径的url

    2. value value属性和path属性是一样的

    3. mthod 指定该方法的请求方式

    4. params 指定限制请求参数的条件

    5. headers 发送的请求中必须包含的请求头

第三章:请求参数的绑定

  1. 请求参数的绑定说明
    1.1绑定机制

    1
    2
    3
    1.  表单提交的数据都是k=v格式的 username=haha&password=123
    2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
    3. 要求:提交表单的name和参数的名称是相同的

    1.2支持的数据类型

    1. 基本数据类型和字符串类型
    2. 实体类型(JavaBean)
    3. 集合数据类型(List、map集合等)
  2. 基本数据类型和字符串类型

    1. 提交表单的name和参数的名称是相同的
    2. 区分大小写
  3. 实体类型(JavaBean)

    1. 提交表单的name和JavaBean中的属性名称需要一致
    2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如: address.name
  4. 给集合属性数据封装

    1. JSP页面编写方式:list[0].属性
  5. 请求参数中文乱码的解决

    1. 在web.xml中配置Spring提供的过滤器类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      <!-- 配置过滤器,解决中文乱码的问题 -->
      <filter>
      <filter-name>characterEncodingFilter</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter class>
      <!-- 指定字符集 -->
      <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
      </init-param>
      </filter>

      <filter-mapping>
      <filter-name>characterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
      </filter-mapping>
  1. 自定义类型转换器

    1. 表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换。
      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
      package cn.itcast.utils;
      import java.text.DateFormat;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      import org.springframework.core.convert.converter.Converter;
      /**
      * 把字符串转换成日期的转换器
      * @author rt
      */
      public class StringToDateConverter implements Converter<String, Date>{
      /**
      * 进行类型转换的方法
      */
      public Date convert(String source)
      {
      // 判断
      if(source == null) {
      throw new RuntimeException("参数不能为空");
      }
      try {
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      // 解析字符串
      Date date = df.parse(source);
      return date;
      }catch (Exception e) {
      throw new RuntimeException("类型转换错误");
      }
      }
      }
  2. 如果想自定义数据类型转换,可以实现Converter的接口

    1. 自定义类型转换器

    2. 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

1
2
3
4
5
6
7
8
9
10
11
<!-- 注册自定义类型转换器 -->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.utils.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 开启Spring对MVC注解的支持 -->
<mvc:annotation-driven conversion-service="conversionService"/>
  1. 在控制器中使用原生的ServletAPI对象

1. 只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

第四章:常用的注解

1.RequestParam注解

1.  作用:把请求中的指定名称的参数传递给控制器中的形参赋值

2.  属性

    1.  value:请求参数中的名称

    2.  required:请求参数中是否必须提供此参数,默认值是true,必须提供

    3.  代码如下

2.RequestBody注解

1.  作用:用于获取请求体的内容(注意:get方法不可以)

2.  属性

    1. required:是否必须有请求体,默认值是true
  1. 代码如下
1
2
3
4
5
6
7
8
9
10
/**
* 接收请求
* @return
*/
@RequestMapping(path="/hello")
public String sayHello(@RequestBody String body) {
System.out.println("aaaa");
System.out.println(body);
return "success";
}

3.PathVariable注解

  1. 作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符

  2. 属性

    1. value:指定url中的占位符名称
  3. Restful风格的URL

    1. 请求路径一样,可以根据不同的请求方式去执行后台的不同方法

    2. restful风格的URL优点

      1. 结构清晰

      2. 符合标准

      3. 易于理解

      4. 扩展方便

  4. 代码如下

1
2
3
4
5
6
7
8
9
10
<a href="user/hello/1">入门案例</a>
/**
* 接收请求
* @return
*/
@RequestMapping(path="/hello/{id}")
public String sayHello(@PathVariable(value="id") String id) {
System.out.println(id);
return "success";
}

4.RequestHeader注解

  1. 作用:获取指定请求头的值

  2. 属性

    1. value:请求头的名称
  3. 代码如下

1
2
3
4
5
@RequestMapping(path="/hello")
public String sayHello(@RequestHeader(value="Accept") String header) {
System.out.println(header);
return "success";
}

5.CookieValue注解

1.  作用:用于获取指定cookie的名称的值

2.  属性

    1.  value:cookie的名称

3.  代码
1
2
3
4
5
@RequestMapping(path="/hello")
public String sayHello(@CookieValue(value="JSESSIONID") String cookieValue) {
System.out.println(cookieValue);
return "success";
}

6.ModelAttribute注解

1.  作用

    1.  出现在方法上:表示当前方法会在控制器方法执行前线执行。

    2.  出现在参数上:获取指定的数据给参数赋值。

2.  应用场景

    1.  当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。

3.  具体的代码
  1. 修饰的方法有返回值

    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
    /**
    * 作用在方法,先执行
    * @param name
    * @return
    */
    @ModelAttribute
    public User showUser(String name) {
    System.out.println("showUser执行了...");
    // 模拟从数据库中查询对象
    User user = new User();
    user.setName("哈哈");
    user.setPassword("123");
    user.setMoney(100d);
    return user;
    }



    /**
    * 修改用户的方法
    * @param cookieValue
    * @return
    */
    @RequestMapping(path="/updateUser")
    public String updateUser(User user) {
    System.out.println(user);
    return "success";
    }
  2. 修饰的方法没有返回值

    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
    /**
    * 作用在方法,先执行
    * @param name
    * @return
    */
    @ModelAttribute
    public void showUser(String name,Map<String, User> map) {
    System.out.println("showUser执行了...");
    // 模拟从数据库中查询对象
    User user = new User();
    user.setName("哈哈");
    user.setPassword("123");
    user.setMoney(100d);
    map.put("abc", user);
    }
    /**
    * 修改用户的方法
    * @param cookieValue
    * @return
    */
    @RequestMapping(path="/updateUser")
    public String updateUser(@ModelAttribute(value="abc") User user) {
    System.out.println(user);
    return "success";
    }

    7.SessionAttributes注解

  3. 作用:用于多次执行控制器方法间的参数共享

  4. 属性

    1. value:指定存入属性的名称
  5. 代码如下

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
@Controller
@RequestMapping(path="/user")

@SessionAttributes(value= {"username","password","age"},types=
{String.class,Integer.class}) // 把数据存入到session域对象中

public class HelloController {
/**
* 向session中存入值
* @return
*/
@RequestMapping(path="/save")
public String save(Model model) {
System.out.println("向session域中保存数据");
model.addAttribute("username", "root");
model.addAttribute("password", "123");
model.addAttribute("age", 20);
return "success";
}


/**
* 从session中获取值
* @return
*/
@RequestMapping(path="/find")
public String find(ModelMap modelMap) {
String username = (String) modelMap.get("username");
String password = (String) modelMap.get("password");
Integer age = (Integer) modelMap.get("age");
System.out.println(username + " : "+password +" : "+age);
return "success";
}


/**
* 清除值
* @return
*/
@RequestMapping(path="/delete")
public String delete(SessionStatus status) {
status.setComplete();
return "success";
}
}

课程总结

  1. SpringMVC的概述

  2. 入门

    1. 创建工程,导入坐标
  3. 在web.xml中配置前端控制器(启动服务器,加载springmvc.xml配置文件)

    1. 编写springmvc.xml配置文件
  4. 编写index.jsp的页面,发送请求

    1. 编写Controller类,编写方法(@RequestMapping(path="/hello")),处理请求
  5. 编写配置文件(开启注解扫描),配置视图解析器

    1. 执行的流程
  6. @RequestMapping注解

    1.  path
    2.  value 
    3. method
    4....
  7. 参数绑定

    1. 参数绑定必须会

    2. 解决中文乱码,配置过滤器

    3. 自定义数据类型转换器