---行内容居中
4、th:行中的第一行表头内容,自动加粗居中
5、td:行中单元格具体内容
td属性:
(1)内容 :5行进行合并
(2)内容 5列进行合并
6、子标签 caption:给表格设置标题元素
七、表单标签
用户录入"用户信息",通过"表单"将用户的数据提交给服务器,服务器去接收数据
录入的时候,表单中表单元素必须指定name属性,给后端进行标记用户输入实际内容
1、表单标签form格式
2、form属性
(1)action:
八、iframe画中画
url:连接点页面或者资源文件的统一资源定位符号
九、value属性和placeholder属性的区别
value:
在html表单元素中(文本输入框/密码输入框/复习框/单项按钮/下拉菜单....),这些元素的默认值;
结合js事件(获取焦点事件,输入的时候,就将这个默认值删除)
placeholder:
表单元素的新增属性, 字体灰色,当键入内容之后,就自动删除(效果)
十、get方式和post方式提交区别
(1)是否提交在地址栏上
get方式将数据提交到地址栏上的, action提交的地址url?key1=value1&key2=value2....(浏览器默认get提交)
post提交方式,不会将数据提交到地址栏上,在浏览器(F12--进入调试器)--->"网络"里面的负载 可以看到表单提交的数据 (post提交针对中文会出现乱码)
(2)是否适合私密数据提交
get提交方式,相对post来说不安全,地址栏是可以直接看到明文的敏感数据
post提交方式,相对get来说安全,地址栏不会直接看到具体内容;针对隐私数据,post提交的数据也需要加密
get/post提交的数据(密码等等)----加密的! md5加密(信息摘要算法) "123456" + 加盐 "qianfeng" 保证不会被破解
3)提交数据大小是否有限制
get提交方式,在地址栏上提交数据,提交数据大小有限制
post提交方式,是在浏览器中 网络中的请求头后面的负载里面可以直接不断去提交数据,没有大小限制
CSS
一、css概念
CSS:层叠样式表 Cascading Style Sheet。通过CSS给页面添加修饰效果
二、给标签添加样式使用方式
1、行内样式
超链接
style="样式属性名称1:样式值1;样式属性名称2:样式值2;..."
每一个html标签都有属性style(样式),一次只能控制一个标签。适用于在局部位置设置某个标签样式
2、内联样式(css内部方式)
XXX
超链接
弊端:html标签和css代码混合使用,不利于后期项目维护
3、外联方式(CSS外部样式)
(1)
xxx
(2)
1)在css文件夹中新建一个.calss文件
2)使用 css选择器{
样式属性名称1:值1;
样式属性名称2:值2;
...
}
3)在当前页面导入css文件
rel="stylesheet" ---固定格式,必须写,"关联样式库中样式"
4、在当前html页面中导入css样式, 在head标题体中
(1)
(2)
三、CSS选择器
优先级: id选择器 > class类选择器 > 标签名称选择器
1、标签名称选择器
标签名称{
样式名称1:值1 ;
样式名称2:值2 ;
}
2、class(类)选择器
.class属性值{
样式名称1:值1 ;
样式名称2:值2 ;
}
3、id选择器
#id属性值{
样式名称1:值1 ;
样式名称2:值2 ;
}
在标签中指定id属性="id值"(不能以数字开头,字母开头)
id属性值在同一个html页面中,必须是 "唯一的"
4、子元素选择器
选择器1 选择器2{
样式名称1:值1 ;
样式名称2:值2 ;
}
选择器2选中的标签是选择器1选中标签的子标签
5、并集选择器
选择器1,选择器2,选择器3....{
样式名称1:值1 ;
样式名称2:值2 ;
}
6、伪类选择器
1、标签的四种状态:
(1)、 link:鼠标没有访问标签的状态
(2)、 hover:鼠标经过这个标签的状态
(3)、 active:鼠标点击且没有松开的状态
(4)、 visited:鼠标已经点击访问过的状态
visited升到放在link之后才能循环使用
伪类名称对大小写不敏感
2、伪类选择器格式
选择器名称(标签名称/class/id):状态名称{
样式名称:值;
...
...
}
背景的简写属性:
background:background-color background-image background-repeat backgound-position;
示范 background: darkgray url(img/index_right.jpg) no-repeat top center;
必须严格按照顺序
2、CSS背景属性
1、background-color:背景颜色
2、background-image: url(图片文件地址)
3、background-repeat:背景图片是否重复,如何重复
(1)background-repeat,默认,图片尺寸达不到当前屏幕分辨率,x轴/y轴都重复
(2)background-repeat-x:x轴重复
(3)background-repeat-y:y轴重复
(4)background-no-repeat:不重复
4、background-attachment:背景附着: 设置fixed 固定,图片不会随着页面滚动而滚动
5、background-position:设置背景图像的起始位置,默认左上对齐
top left
center center
bottom right
background: red url(xxx) no-repeat top center
五、CSS文本样式
1、文本颜色:color
2、文本对齐方式:text-align
(1)tetx-align:left---左对齐,默认
(2)text-align:center---居中
(3)text-align:right---右对齐
3、文本装饰:text-decoration
text-decoration:onoe---删除链接的下划线
text-decoration:underline---设置下划线
text-decoration:voerline---上划线
text-decoration:line-through---中划线
4、文本字符间距
(1)letter-spacing:10px
(2)word-spacing:20px 两个字组成一个词
5、大小写转换:text-transform
text-transform:uppercase ---转换成大写字母
text-transform:lowercase ---转换成小写字母
6、文本缩进 textt-indent:10px ---指定文本第一行缩进
7、行高 text-height:20px
六、CSS字体样式
1、字体格式 font-family=“黑体”
2、字体类型 font-style
(1)font-style:normal 默认字体类型
(2)font-style:italic 斜体
(3)font-style:oblique 斜体
3、字体粗细 font-weight:10px bold:等价于700
4、字体大小 font-size:20px
font的简写
font:字体类型 字体粗细 字体大小 字体格式 ---按顺序
font:italic bold 20px “仿宋”
七、CSS边框样式
1、边框颜色
(1)border-top-color:上边框颜色
(2)border-bottom-color:底边框颜色
(3)border-left-color:左边框颜色
(4)border-right-color:右边框颜色
2、边框宽度
(1)border-top-width:上边框宽度
(2)border-bottom-width:底边框宽度
(3)border-left-width:左边框宽度
(4)border-right-width:右边框宽度
3、边框样式
(1)border-top-style:上边框样式
(2)border-bottom-style:底边框样式
(3)border-left-style:左边框样式
(4)border-right-style:右边框样式
边框样式值:solid(单实线)、double(双实线)、dashed(虚线)、dotted(点)
border的简写属性
border:边框宽度 边框样式(必须有) 边框颜色 ---按顺序
border:10px solid red
八、CCS列表样式
一、无序列表
1、列表标记类型
(1)list-style-type:none ---去掉列表项前面的标记
(2)list-style-type:square ---小黑正方形
(3)list-style-type:circle ---空心圆点
(4)list-style-type:disc ---小黑圆圈,默认
2、将图片指定为列表标记项 list-style-image
list-style-image;url(图片地址)
3、display-inline 设置到同一行上
li {
display: inline;
}
浮动列表项
创建水平导航栏的另一种方法是浮动 元素,并为导航链接规定布局:
li {
float: left;
}
a {
display: block;
padding: 8px;
background-color: #dddddd;
}
4、border-collapse 属性设置是否将表格边框折叠为单一边框: collapse:合并
九、浮动
浮动和清除
CSS float 属性规定元素如何浮动
CSS clear 属性规定哪些元素可以在清除的元素旁边以及在哪一侧浮动
float 属性用于定位和格式化内容,例如让图像向左浮动到容器中的文本那里。
float 属性可以设置以下值之一:
left - 元素浮动到其容器的左侧
right - 元素浮动在其容器的右侧
none - 元素不会浮动(将显示在文本中刚出现的位置)。默认值。
inherit - 元素继承其父级的 float 值
clear 属性可设置以下值之一:
none - 允许两侧都有浮动元素。默认值
left - 左侧不允许浮动元素
right- 右侧不允许浮动元素
both - 左侧或右侧均不允许浮动元素
inherit - 元素继承其父级的 clear 值
十、CSS定位
定位属性:position 也可以进行部分内容的布局
position:绝对定位 absolute:根据当前元素的父元素进行移动的
相对定位 relative:根据之前元素的位置进行移动的方式
固定定位 :fixed:永远在页面中指定位置,不会随着滚动而滚动
top:整个元素向下移动
left:整个元素向右移动
盒子模型
概念:
(1)将任何标签都看成盒子,整个页面布局大体方向先使用div将内容包裹起来,形成 "层级" ,一个页面分成了很多块。给div加入id/class等选择器,通过css样式属性精准控制
(2块级元素:
div 占一行标签
h1-h6 占一行内容
(3行级元素:
(4)将html页面中任何标签 看成一个"盒子"
容量:width/height
厚度: 边框 border
内边距:padding 盒子的内边距: 边框和内容之间的距离(上右下左)
外边距:margin 盒子和盒子之间的距离:通过外边距让整个盒子进行移动!
---导入外部css样式
框架标签
概念:
框架标签:frame,一个frame包含一个html页面
如果整个页面结构并非一个html组成,而是两个或者两个以上的html页面组成,需要使用框架集frameset
一、框架
frame:框架标签。
src="链接到html页面地址"
name="给框架标签起名称"
frameset框架集。不能和body共存
*:代表剩下的百分比 20%就是头部页面
rows属性:由上而下划分,每一个部分所占的权重百分比
---链接头部html页面地址
*:代表剩下的百分比 15%是左边菜单页,剩下为中间主页
cols属性:由左而右划分,每一个部分所占的权重百分比
---链接菜单html页面地址
超链接的target打开方式。如果在框架标签中使用,target也可以指定在哪个一个frame中打开,需要和frame标签中name属性值一致!
二、菜单页面-menu
查询所有学生
超链接的target打开方式,如果在框架标签中使用,target也可以指定在哪个一个frame中打开需要和frame标签中name属性值一致!
教师管理
三、中间主页面-main
四、头部页面-header
font、boostrap框架引入
一、使用方式
1)将font图标库的css文件夹和font文件夹放在前端项目下
2)将boostrap前端框架这里面所有css文件夹的内容以及font文件夹的放在当前项目下
3)首先页面中导入boostrap全局样式boostraom. min.css(压缩版)
4)在head标题体中导入第三方提供的 font-awesome.min.css图标样式
二、样例
(1)
导入css样式
(2)
学生信息表
boostrap
jsp中导入boostrap样式
//导入bootstrap的css样式
//导入js库,需用用到boostrap框架js插件,在导入boostrap.min.js之前,先导入Jquery
boostrap格栅
1)布局容器
class="container":容器:是固定宽度并且支持响应式布局
class="container-fluid":容器:是支持width,100%(占整个视口宽度)
2)行 class="row"
3)行定义列 column class="col-设备编号-所占的列数量"
设备编号:
xs :超小桐木 手机 <768px
sm :小屏幕 平板>=768px
md :中等屏幕 桌面显示器 (≥992px
lg :大屏幕 大桌面显示器 (≥1200px)
class ="table-bordere" 设置边框
boostrap表格样式
class="table"基本表格样式
class="table-striped" 斑马条纹样式
class="table-bordere" 为单元格增加边框
class="table-hover " 鼠标悬浮在上面有样式效果
class="table-condensed" 紧缩表格
class="table-responsive" 响应式表格,视口尺寸小于768像素开始出现水平滚动条,大于768px水平滚动条消失
给tr行上加入的的样式
class="active": 鼠标悬停在行或单元格上时所设置的颜色
class="success"成功标识的颜色
class="danger"成功标识的颜色
商品编号
商品名称
1
小米p10
2
小米p10
boostrap表单样式
class="form-horizontal" 设置表单水平排列表单
laber元素和input组件在一行上
class="form-group" 包含laber和input或者select下拉菜单
class ="form-control" :将input元素或者select或者textarea设置为100%宽度
boostrap按钮样式
class="btn btn-default" 默认样式按钮
class = "btn-group"按钮组,将所有的按钮放在 同一行上
boostrap导航条
nav:导航组件:水平导航条
class="navbar navbar-default":导航条样式
boostrap分页
URL和URI
url:统一资源定位符 是URI的子集
http://localhost:8080/day38_HTML_CSS/01_html%E5%B8%B8%E7%94%A8%E5%9F%BA%E7%A1%80%E6%A0%87%E7%AD%BE.html
URI:定位符: 前面没有带协议
/day38_HTML_CSS/01_html%E5%B8%B8%E7%94%A8%E5%9F%BA%E7%A1%80%E6%A0%87%E7%AD%BE.html
URI的范围大于url
URI--->/web项目名称/资源文件名称
/day38_HTML_CSS/---->web项目的上下文路径(Application Context)
web项目一般都需要带上 "上下文路径名称",防止前端请求会出现404:一般页面地址找不到
JavaScript
JavaScript的变量定义及类型划分
javascript(js):属于弱类型语言 (语法不严谨)
1)定义变量使用var定义 ,可以重复定义变量
2)var可以定义任何类型,而且可以省略
js类型划分:
基本类型 引用类型
(整数/小数)number 数值类型 提升为 内置对象:Number:数值对象
(双引号括起来的/单引号括起来的)String 提升为 内置对象:String:字符串对象
boolean类型 提升为 内置对象:Boolean
object类型 创建对象 提升为 内置对象Object:所有js对象的模板
undefined 未定义类型 (没有意义)
js内置的常用函数:
给浏览器输出内容
document.write(输出内容) ;
console.log(输出内容):在浏览器-f12---控制台里面的日志信息
查看变量的数据类型
typeof(变量名)
js经常测试:是否能够获取数据通过弹框的方式
window.alert(对话提示框)
JavaScript运算符及流程控制
与java不同点:
1、switch(表达式){ //switch中case语句,在js可以跟变量,而java中只能是常量
case 变量/常量:
语句1;
break;
case 变量名2/常量名2:
语句2;
break ;
....
default:
语句n;
break ;
}
2、for-in语句: 遍历数组或者性
for(var 变量名 in 数组对象名称或者对象名称){
使用这个变量名即可;
}
for(var i in strArray){
document.write(strArray[i]+" ") ;
}
3、 var a = 3 ;
var b = 4 ;
//不取整
document.write("(a/b):" + (a/b)) ;
4、
//定义字符串数组
创建数组格式
arrayObj = new Array() ; 不给数组长度
arrayObj = new Array([size]) 给定长度
arrayObj = new Array([element0[, element1[, ...[, elementN]]]])
简写
arrayObj = [element0[, element1[, ...[, elementN]]]] ;
var strArray = ["JavaEE","MySql","Redis","JavaScript","Jdbc"] ;
与java相同点
算术运算符 :+,-,*,/,%
赋值运算符: =,+=,-=.....
逻辑运算符
&,|,^,逻辑非!
&&:连接的表达式左边为false,右边不执行
||:连接表达式左边为true,右边不执行
比较运算符<=,>=,==,<,>....
三元(三目运算符)
(条件表达式)?执行成立的结果:执行不成立的结果;
流程语句
顺序结构语句
选择结构:
if()
if()...else{}...
if()...else if()... else{}
循环结构语句
for(var 变量名= 值;条件表达式;步长语句){
循环体语句
}
var 变量名 = 值;
while(条件表达式){
循环体语句;
步长语句;
}
do{
循环体语句;
步长语句;
}while(条件表达式) ;
for-in语句: 遍历数组或者性
for(var 变量名 in 数组对象名称或者对象名称){
使用这个变量名即可;
}
Person对象---name属性和age属性
var 数组名称= new Array([元素1,元素2....]) ;
等价于
var 数组清除 = [元素1,元素2....] ; 静态初始化
JavaScript比较运算符(不同点)
a==b
a===b
=== 和 == 的区别
===:比较两个引用,==比较两个值
比较两个值的时候不考虑数据类型
JavaScript函数
js定义函数的格式固定的写法:
function 函数名称(形参名称1,形参名称2...){
//方法体内容
1.可以直接return 结果; 带有返回值;
2.可以直接输出document.write(xxx)
}
调用函数
var 结果 = 函数名称(实际参数列表) ; 有返回值的直接接收,使用它
定义函数注意事项:
1)定义函数的时候,形式参数不能携带var,直接参数名称即可
2)js弱类型语言,没有函数重载的概念,后面定义的函数将前面的函数覆盖
3)当实际参数个数小于形式参数个数,结果就是NaN(没值),但是依然会调用
4)实际参数个数大于形式参数个数,结果将前面的实际参数进行赋值计算
5)函数里面数组---arguments,将实际的值绑定给形式参数
JavaScript常见弹窗函数
window均可以省略
window.alert("信息") 只有一个确定的弹窗
window.confirm("你好");
他的返回值是boolean,当点击“确定”时,返回true,无论点击“取消”还是右上角的那个“X“关闭,都返回false
prompt弹窗
window.prompt("你爱学习吗?","爱");
第一个参数是提示信息,第二个参数是用户输入的默认值。
当你点击确定的时候,返回用户输入的内容。当你点击取消或者关闭的时候,返回null
JavaScript事件
事件编程的三要素
1、事件源--特定的html标签 如:button按钮具备点击事件
2、事件监听器--编写一个函数
3、绑定事件监听器到事件源上
通过标签一些特定的属性将上面的函数进行绑定
一、和点击相关的事件
1、单击 onclick
方式1:
function click(){
alert(“触发单击事件”);
}
方式2:
dom操作,获取id=“btn”的input标签对象
var inputObject = document.getElementById(“btn”);
使用对象名.onclick属性
inpuitObj.οnclick=function(){
alert(“触发单击事件”);
}
2、双击ondblclick
;
定义触发函数
function.mydbllclick(){
alert(“触发双击事件”);
}
二、和焦点相关事件
3、获取焦点 onfocus(输入数据)
用户名:
//定义函数
function myFocus(){
var input=document.getElementById("username") ;
//改变value属性,输入内容时,默认属性值变为空
input.value="";
}
4、失去焦点onblur(输入数据完毕,到输入框外面)
用户名:
//定义函数
function myBlur(){
//获取文本输入框的内容
var username = document.getElementById("username") ;
var span = document.getElementById("spanTip") ;
if(username!= “张三”){
//匹配失败,给span标签设置标签文本innerHTML属性
span.innerHTML = “不符合格式”.fontcolor(“red”);
}else{
//匹配成功
span.innerHTML="√ ".fontcolor("green") ;
}
}
普通纯文本 innerText :不能渲染html标签,原样输入内容
标签文本 innerHTML:可用渲染html标签
三、选项卡发生变化事件onchange
onchange:下拉菜单,选择的时候。元素就会改变 onchange
籍贯:
请选择
陕西省
山西省
广东省
湖南省
//定义函数,html元素改变,就会触发onchange指定的函数
function myChange(){
//通过id=“province” 获得select标签对象
var pro = document.getElementById("province") ;
//获取选择的内容的value属性
var province = pro.value ;
//获取当前id=“city”的select的标签对象
var city = document.getElementById("city") ;
//每一次选项卡变化之前,清空掉上一次内容
city.innerHTML=“”;
if("陕西省"==province){
//创建城市数组--陕西省城市
var cityArr = ["西安市","咸阳市","宝鸡市","渭南市"] ;
//遍历
for(var i = 0 ; i < arr.length ; i ++){
//设置city所在的select标签对象的option标签--- 作为select的innerHTML
city.innerHTML+= ""+arr[i]+" " ;
}
}
//创建城市数组--山西省城市
if("山西省"==province){
//js创建数组
var arr = ["太原市","运城市","大同市","晋中市"] ;
//遍历
for(var i = 0 ; i < arr.length ; i ++){
//arr[i]每一个城市
//设置city所在的select标签对象的option标签--- 作为select的innerHTML
city.innerHTML += ""+arr[i]+" " ;
}
}
四、鼠标相关事件
6、鼠标经过onmouseover / 移出 onmoueout
经过这个区域,打开一个页面
var myTaskId ;
//定义函数新建窗口打开02_函数的应用.html
function opennewUrl(){
window.open("02_函数的应用.html","_blank") ;
}
//定义函数每隔5秒执行一次函数opennewUrl()
function openInterVal(){
myTaskId = window.setInterval("opennewUrl()",5000) ;
}
//定义函数取消定时任务
function clearMyTask(){
//window对象---clearInteval(任务id) ; 取消定时任务
window.clearInterval(myTaskId) ;
}
//鼠标经过,打开链接
function myMouseOver(){
top.location.href="01_js事件变成三要素.html" ;
}
//鼠标移出,每隔3秒打开一个页面
function myMouseOut(){
myTaskId = window.setInterval("opennewUrl()",3000) ;
}
js完成 页面跳转(打开url)
1)window.open("url","打开资源文件方式")
window.open("02_函数的应用.html","_blank") ;
2)window.location.href="重新载入url地址" 新的窗口
top.location.href 在当前页面中直接将当前页码覆盖,打开一个新的页面
top.location.href="01_js事件变成三要素.html" ;
五、页面载入事件onload
浏览器将body内容加载完毕就会触发 onload事件
function myInit(){
alert("载入事件触发了")
}
JavaScript自定义对象
打开窗口
1.新页面弹出一个窗口
top.location.href="01_js事件变成三要素.html" ;
2.当前页面打开一个窗口
window.location.href="01_js事件变成三要素.html" ;
确认提示框 window.confirm("str"),返回一个boolean型的值
function deleUser(uid){
var flag = window.confirm("是否要删除");
if(flag){
window.location.href="${pageContext.request.contextPath}/delUser?uid="+uid ;
}
}
var–let–const的区别
let和const是ES6新增的声明变量的关键词,之前声明变量的关键词是var。
let:
1.var定义的变量,可以预解析提前调用的结果是undefined,let定义的变量不能预解析,提前调用的结果是 报错。
2.var定义的变量,变量名称可以重复,效果是重复赋值,let定义的变量不能重复,否则执行报错。
3.var定义的变量作用域是全局/局部作用域。let定义的变量如果在{}中只能在{}中调用。
4.在循环语句中var定义的循环变量和使用let定义的循环变量。执行原理和执行效果不同。
const:
1.var定义的变量,可以预解析提前调用的结果是undefined,const定义的变量不能预解析,提前调用的结果是 报错。
2.var定义的变量,变量名称可以重复,效果是重复赋值,const定义的变量不能重复,否则执行报错。
3.var定义的变量作用域是全局/局部作用域。const定义的变量如果在{}中只能在{}中调用。
4.const 定义的变量存储的数据数值不能改变,也就是const定义的变量,不能重复赋值。
使用const声明常量,一旦声明,就必须立即初始化,const声明常量,允许在不重新赋值的情况下修改它的值(基本数据类型不可,只有引用数据类型可以,引用类型引用的是地址不是值)
DOM编程
基于Document Object Model:文档对象模型编程
将html文档每一个封装"标签对象",自己的属性,自己的函数,完成表单校验
dom核心:
1)获取指定的标签对象
2)改变标签对象的属性
一、获取标签对象
Title
//document集合属性:
//links:获取带有href的a标签对象 以及area标签(热点域)
//获取第一个a标签对象
var aNode = document.links[0] ; //集合属性
//获取它的父节点
var bodyNode = aNode.parentNode ;
//childNodes:所有子节点
var nodes = bodyNode.childNodes ;
for(var i = 0 ; i < nodes.length ; i ++){
alert(nodes[i].nodeName) ;
}
var first = bodyNode.firstChild ;//第一个子节点
通过id获取标签对象
var 对象名= document.getElementById(“id”);
//添加文本内容
对象名.span.innerHTML =“xxx“;
获取通过标签对象获得标签属性
var 对象名= document.getElementById(“id”).value;
通过标签名找到 HTML 元素
方法:getElementsByTagName("合法的元素名");
通过类名找到HTML 元素
方法:getElementsByClassName("class属性的值")
修改css属性
Hello World!
定时器
JavaScript定时器
定义定时器:
setInterval('调用函数',毫秒时间):每间隔固定毫秒值就执行一次函数
setTimeout('调用函数',毫秒时间):在固定时间之后执行一次调用函数
关闭定时器:
clearInterval(定时器名称)
clearTimeout(定时器名称)
window.setInterval()
setInterval("generateTime()",1000) ;//每隔1秒执行这个函数一次
JavaScript 内置对象字符串
字符串定义方式
var str1 = new String("hello");
var str2 = "jack";
字符串比较
==:默认比较地址值
str1==str2
valueOf():返回指定对象的原始值
str1.valueOf() == str2.valueOf()
正则表达式
js的正则表达式基本语法;
x后面带上符号:x代表任意字符
数量词
x+:x字符出现1次或者多次
X?:x字符出现0次或1次
X*:x字符出现0次或者多次
范围
x{n}:x恰好出现n次
x{n,}:x字符至少出现n次
x{n,m}:x字符至少出现n次,不超过m次
x[a-z]:x字符为a-z的小写字母
\d :0-9的数字字符
\w : 匹配下划线的任意单词字符。等价于[A-Za-z0-9_]
创建一个正则规则:基本语法
不完全匹配
var 正则对象名 = /基本语法/; 不完全匹配
完全匹配
var 正则对象名 = /^正则语法$/; 精确匹配
^:输入匹配规则的开始位置:以指定的字符开头
$:输入匹配的结束位置:以指定的字符结尾
内置的方法:
var 结果变量 = 正则对象名.test(字符串);true匹配成功,false匹配失败
var str = “waha123”;
var reg = /^[a-z0-9]+$/ 代表:a-z0-9的字符出现1次或者多次
if(reg.test(str)){
//匹配成功
}else{
alter("匹配失败")
}
修饰符:
i 执行对大小写不敏感的匹配
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
m 执行多行匹配
方法:
exec() 方法:检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回
null
var patt1=new RegExp("e");
document.write(patt1.test("The best things in life a
正则表达式表单校验-onsubmit事件
用户 名
密 码
确认密码
//调用所有校验的函数,并提交返回值true或false给 onsubmit
function checkAll(){
if(checkUsername() && checkPwd() && checkRepwd() && checkEmail())
return ture;
}else{
returen false;
}
//校验用户名是否符合正则表达式
function checkUsername(){
//获取id="username"的input标签对象同时获取内容
var username = document.getElementById("username").value ;
//获取id="userTip"的span标签对象
var span = document.getElementById("userTip") ;
//创建正则规则
//用户名:6-16位数字或者字母组成
var reg = /^[A-Za-z0-9_]{6,16}$/ ;
/* if(username==""){
span.innerHTML ="用户名不能为空".fontcolor("red") ;
}*/
if(reg.test(username)){
//成立,给span标签设置标签文本
span.innerHTML = "恭喜您".fontcolor("green") ;
return true ;
}else{
span.innerHTML = "不可用".fontcolor("red") ;
return false ;
}
}
//校验密码
function checkPwd(){
//获取密码框的内容
var pwd = document.getElementById("pwd").value;
//获取id="pwdTip" 的span标签对象
var span = document.getElementById("pwdTip") ;
//创建正则规则:校验密码
//密码:6-10位的数字或者字母组成
var reg = /^\w{6,10}$/ ;
//校验
if(reg.test(pwd)){
span.innerHTML ="√".fontcolor("green") ;
return true ;
}else{
span.innerHTML ="X".fontcolor("red") ;
return false ;
}
}
//校验确认密码
function checkRepwd(){
//获取密码框的内容
var pwd = document.getElementById("pwd").value;
//获取确认密码框的内容
var repwd = document.getElementById("repwd").value ;
//获取id="repwdTip"的span标签对象
var span = document.getElementById("repwdTip") ;
//两次内容一致
if(pwd.valueOf() == repwd.valueOf()){
span.innerHTML = "一致".fontcolor("green") ;
return true ;
}else{
span.innerHTML = "两次信息不一致".fontcolor("red") ;
return false ;
}
}
function checkEmail(){
//获取邮箱的内容
var email = document.getElementById("email").value ;
//id="emailTip"的span标签对象
var span = document.getElementById("emailTip") ;
//创建邮箱正则规则:
var reg = /^\w+@\w+(\.[a-z]{2,3}){1,2}$/ ;// \w -- [A-Za-z0-9_]+
if(reg.test(email)){
span.innerHTML = "邮箱格式满足".fontcolor("green") ;
return true ;
}else{
span.innerHTML = "不满足格式".fontcolor("red") ;
return false ;
}
}
Servlet
Servlet概念
Servlet:Server Applet:服务器连接器(java语言编写的服务端程序)
必须应用在应用服务器(web容器,tomcat/jetty/apache Http服务器...)
Servlet的本质:
习惯称为:一个能够实现javax.servlet.Servlet接口的类
servlet作用
1、接收前端的发送的请求
2、解析请求,完成服务端程序的登录/注册等并响应给客户
使用Servlet步骤
1)需要导入servlet的核心jar包
javax.servlet-api-4.0.1.jar
javax.servlet-api-3.1.0.jar
或者tomcat的解压目录lib---servlet-api.jar包
2)创建一个类(具体类),继承Servlet接口的抽象的子实现类(HttpServlet)
3)重写HttpServlet里面的两个方法
doGet(请求对象,响应对象):接收前端的get请求
doPost(请求对象,响应对象):接收前端的post请求
4)配置Servlet: 在WEB-INF的web.xml文件(网站全局配置文件)
MyFirstServlet
com.qf.servlet_01.MyFirstServlet
MyFirstServlet
/first
5)默认get接收前端请求:
@Override
//HttpServletRequest\HttpServletResponse http底层网络协议创建HttpServletResponse/HttpServletRequest对象
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//本质就是设置一个响应头:content-type:text/html;charset=utf-8
resp.setContentType("text/html;charset=utf-8");
//浏览器中输入地址:http://localhost:8080/day41_Servlet_Jsp_Web_exploded/first
System.out.println("进入到了MyFirstServlet") ;
//服务器端给浏览器响应一句话:HttpServletResponse
resp.getWriter().write("响应成功了!"); //有中文,解决响应的中文乱码
}
tomcat 怎么将请求精确转发给 servlet
web项目通过压缩成war部署到Tomcat服务器上 Serv实现子类对应out中xx.class文件
tomcat 怎么将请求精确转发给 servlet ?
一个 tomcat 下有好多个 servlet,那 tomcat 是怎么请求精确转发给 servlet 的呢?
tomcat 根据 URL 先确定转发给 webapps 下的哪个项目,再确定转发给项目中的哪个 servlet。
RL:http://localhost:8080/ch06-cookies/checkcookie.do
通信协议:http://(使用 http 通信协议)。
服务器IP:localhost (本地)。
端口号:8080 (tomcat 对应的 socket 的端口号默认是8080,大家常说的 tomcat “监听” 8080 端口)。
uri:/ch06-cookies/checkcookie.do (tomcat 用这部分判断是要将请求转发给哪个 servlet)。
webapps 下的项目名字:ch06-cookies
项目中的 servlet:checkcookie.do
在 tomcat 的 webapps 目录下,存放的项目文件结构是有要求的。
(1)webapps 目录下,每一个文件夹就是一个单独的 web 项目,文件夹的名字会作为 uri 的起始
确定了项目,接下来就是确定请求该转发给哪个 servlet
day41_Servlet_Jsp_Web_exploded 项目内部文件结构:
day41_Servlet_Jsp_Web_exploded
├── WEB-INF
│ ├── classes
│ │ └── com
│ │ └── qf
│ │ ├── CheckCookie.class
│ │ └── CookieTest.class
│ └── web.xml
├── cookieresult.jsp
└── form.html
web项目通过压缩成war部署到Tomcat服务器上 Serv实现子类对应out中xx.class文件
每个项目下都必须有有个 web.xml 文件,它被叫做(Deployment Descriptor,DD),里面定义了路径和 servlet 的对应关系
web.xml:
、 这样的一对元素定义一个对应关系,这里定义了两个对应关系:
Ch6_Check_Cookie
com.example.CheckCookie
Ch6_Check_Cookie
/checkcookie.do
http://localhost:8080/ch06-cookies/checkcookie.do 请求会被转发给 CheckCookie servlet 来处理。
Servlet执行流程
Servelt的生命周期
Servelt接口有关生命周期的方法:
1、 初始化init
public void init(ServletConfig config) throws ServletException;
初始化参数ServletConfig,可以直接获取到web.xml的配置文件信息
Servelt的抽象子类:GenericsServlet未做任何实现(private transient ServletConfig config;定义ServletConfig不可序列化)
GenericsServlet的抽象子类HttpServlet未做任何实现
2、服务端应用程序的入口 service
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
被抽象子类HttpServlet做了具体实现,里面实现了doxx方法
子类需重写该方法
3、销毁destroy
public void destroy();
自定义类可以实现这个方法
servlet销毁:服务器(web容器)正常关闭,就会标记当前这个servlet,被jvm进行对象回收
Servelt的初始化加载
服务器启动时不创建实现子类对象,前端发送请求给服务器时才创建
该类加载只执行一次,只有一个实例,单例。
初始化方法init(ServletConfig)以及构造方法都执行一次:
Servlet-->单例设计模式(线程不安全的,可以被多个浏览器同时访问) :在内存中始终只有一个对象
1、第一次访问 当前端访问时:
inti方法被调用:初始化该类, service方法被调用
2、第二次访问
只调用service方法 service方法不断被调用
底层方法:获取前端提交方式,判断前端是GET,还是Post请求,执行不同
doXXX()方法;直接覆盖doXXX方法,完成自己的逻辑
初始化时机:在访问Servlet的时候创建
想要服务器一启动就进行初始化该类(Servlet),需要在配置文件中进行设置
1
web.xml文件配置参数说明
1、全局参数
encoding
utf-8
2、servet的基本配置
//serlvet的名称:可以自定义名字或则和你定义的Servlet的类名一致
MyFirstServlet
//当前servlet的全限定名称,用于Tomcat通过反射获得当前类的字节码文件并调用方法
com.qf.servlet_01.MyFirstServlet
3、servlet的映射配置mapping
//必须和上面的serlvet-name一致
MyFirstServlet
/*前端请求服务器的路径
必须以"/开头"
精确匹配,具体前端请求的路径, /名称
*/
/first
4、初始化配置参数:放在load-on-startup上面
类一加载,立马就会加载上下文的地址,地址中加载资源文件
path 上下文地址
D:\EE_2302\day41\hello.java 资源文件
encoding
utf-8
5、配置servlet的初始化时机参数,一启动web容器就加载(原先web容器启动时不初始化,客户端访问时才初始化)
1
ServletConfig配置对象
web.xml文件
初始化配置参数:类一加载,立马就会加载上下文的地址,地址中加载资源文件
path 上下文地址
D:\EE_2302\day41\hello.java 资源文件
可以有多个初始化参数
ServletConfig接口:servlet配置对象,可以获得web.xml文件里面的配置系信息
作用:可以获取Servlet配置信息中init-param:初始化参数
获取ServletConfig
GenericsServlet中个方法可以直接拿到ServletConfig,
浏览器发请求--解析servlet--->顶层父类可以直接获取到Servletconfig
被自定义类继承
public ServletConfig getServletConfig() {
return config;
}
private transient ServletConfig config;
ServletConfig config = this.getServletConfig();
方法1:一次获取一个配置信息
可以获取Servlet配置信息中初始化参数:init-param
ServletConfig中方法 public String getInitParameter(String name)
可以获取Servlet配置信息中init-param:初始化参数
param-name :初始化名称
param-value :初始化值
String pathValue = config.getInitParameter("path");
方法2:一次获获取所有初始化参数名称
ServletConfig接口中方法,被自定义类继承(servlet)
//Enumeration迭代器
public Enumeration getInitParameterNames();
//获取所有初始化参数名称,遍历参数名称,通过参数名称获取参数值
Enumeration en = config.getInitParameterNames();
while(en.hasMoreElements()){
String paramName = en.nextElement();
//public String getInitParameter(String name)
String paramValue = config.getInitParameter(paramName);
}
用于框架中读取配置文件
类一加载,立马就会加载上下文的地址,地址中加载资源文件
path 上下文地址
D:\EE_2302\day41\hello.java 资源文件
方法3:String servletName = config.getServletName();
获取servlet的名称,及当前的类
ServletContext接口
ServletContext接口:代表整个web Application :全局对象 无实现子类,唯一父类Object
作用:
获取ServletContext对象
GenericsServlet中getServletContext()方法
public ServletContext getServletContext() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getServletContext();
}
ServletContext context = this.getServletContext();
1)获取全局参数--开发中 使用context-param获取全局参数读取核心配置文件
xxx
xxx.properties/xx.xml
contextConfigLocation
/WEB-INF / root-context.xml
2)获取上下文路径 String getContextPath()
String contextPath = request.getContextPath();
//接收get请求
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//统一这块处理post乱码
//请求服务器的时候,服务器端将请求过来的中文解决
//1)获取ServletContext对象:
ServletContext context = this.getServletContext();
// public String getInitParameter(String name);
String encoding = context.getInitParameter("encoding");//全局参数
request.setCharacterEncoding(encoding);
//获取到用户名登录的信息 用户名和密码
//HttpServletRequest--->public String getParameter(String name);
//参数:表单提交的表单元素的里面的name属性值
// http://localhost:8080/day41_Servlet_Jsp_Web_exploded/context1?username=hello&password=123
//get请求,提交数据有中文,不会乱码
String username = request.getParameter("username");
String password = request.getParameter("password");
//2)ServletContext获取上下文路径
//public String getContextPath();
String contextPath = context.getContextPath();
//简写格式:请求对象HttpSevletRequest里面-->public String getContextPath(); 动态获取上下文路径
String contextPath = request.getContextPath();
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("用户未登录 ");
}
//接收post请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端提交的数据的方式通用的
//post提交的是,中文有乱码的
/*String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("登录的用户名是:"+username+",密码是:"+password);*/
//get请求或者post请求获取前端提交数据都是一样,直接复用
doGet(req,resp);
3)请求转发
4)域对象:在不同servelt之间进行数据传输
请求/响应解决中文乱码
请求解决中文乱码
encoding
utf-8
ServletContext context = this.getServletContext();
String encoding = context.getInitParameter("encoding");//获取全局参数
request.setCharacterEncoding(encoding);
1. request.setCharacterEncoding("utf-8");
同时设置服务端的编码格式和客户端响应的文件类型及响应时的编码格式
响应解决中文乱码
2. response.setContentType("text/html;charset=utf-8");
域对象
域对象:在不同servlet之间进行"数据传输"(数据共享)
Servlet+jsp :jsp本质就是Servlet
1、PageContext page域 在某一个jsp(java server Page)有效
2、HttpServletRequest :请求对象: 在一次请求有效 (请求对象) 使用居多
3、HttpSession session会话 : 在一次"会话"中有效(存储服务器端),关闭浏览器失效
4、ServletContext : 全局对象:代表整个web application,服务器重启或关闭失效
通用方法:public void setAttribute(String name,Object obj) :
给域对象中属性名称中添加任意类型数据
public Object getAttribute(String name):通过属性名称获取内容
HttpServletRequest请求对象
//所有的请求信息都封装在HttpServletRequest,获取请求信息
1、获取请求行中的请求方式 String getMethod()
String method = request.getMethod();
2、获取请求行的中uri(范围大),getRequestURI()
String requestURI = request.getRequestURI();
3、获取请求行的中url(范围小),getRequestURL()
StringBuffer requestURL = request.getRequestURL();
4、获取请求行中的协议版本String getProtocol()
String protocol = request.getProtocol();
5、获取请求头中的具体内容
String getHeader(String var1);通过指定的请求头获取请求的内容
//请求头:User-Agent:客户端的浏览器类型
String header = request.getHeader("user-agent");
header.contains("Chrome") //客户端的浏览器类型
6、通过参数名称获取参数值String getParameter(String var1)
String username = request.getParameter("username");
7、获取所有参数名称Enumeration getParameterNames()
Enumeration parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
String name = parameterNames.nextElement(); //参数名称
//通过参数名称获取参数值
String value = request.getParameter(name);
}
8、后端通过Map集合的方法获取参数
//Map getParameterMap();获取前端提交的所有参数的参数名和参数值都封装Map中,遍历map取出来
Map parameterMap = request.getParameterMap();
//遍历Map---Set keySet()获取所有键 + V get(K key) (推荐)
//要么entryset--Map.entry键值对对象
Set set = parameterMap.keySet();
for(String key:set){
//通过键获取值
String[] array = parameterMap.get(key);
for(String s:array){
System.out.println(key+"---"+s);
}
}
9、request域对象存一个数据
request.setAttribute("name",object) ;
HttpServletResponse响应对象
HttpServletRequest处理请求信息
1、设置响应的内容 void setContentType(String var1)
//设置响应的字符编码格式
response.setContentType("text/html;charset=utf-8");
2、设置给浏览器响应头
//void setHeader(String var1, String var2);设置响应头
response.setHeader("content-type","text/html;charset=utf-8");
3、添加响应头
//refresh,定时刷新或者定时跳转页面
//每秒刷新访问的这个地址
response.setHeader("refresh","1");
//定时跳转指定的页面,3秒后跳转登录页
response.setHeader("refresh","3;/Servlet_Jsp_02_Web_exploded/login.jsp");
请求转发
请求转发:属于"服务器行为"进行操作,不需要带上下文路径
前端发送请求,后端的Servlet,接收参数,查询数据库,获取到数据库的信息,将判断结果返回前端,从后端跳转前端 , 用户名或者密码输入错误,给页面提示"错误信息"
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
一、通过ServletContext请求转发,是域对象
//获取SevletContext对象
ServletContext servletContext = this.getServletContext();
1)获取分发器:RequesDispatcher
//public RequestDispatcher getRequestDispatcher(String path);
//参数:是转发到前端页面地址或者后端的另一个地址
RequestDispatcher rd = servletContext.getRequestDispatcher("/getValue.jsp”)属于"服务器行为"进行操作,不需要带上下文路径
//2)RequestDispatcher分发器--->进行转发
//public void forward(ServletRequest request, ServletResponse response)
rd.forward(request,response);
二、 //简写格式,通过域对象HttpServlet请求转发
request.getRequestDispatcher("/getValue.jsp").forward(request,response);
//request对象---类型:HttpServletRequest:本身是域对象,域对象可以存数据
}
//直接后端/context2地址,请求转发到一个jsp页面上,并且jsp页面还能获取到里面存储数据
//域对象方法:通用方法:public void setAttribute(String name,Object obj) :
给域对象属性名称中添加任意类型数据
servletContext.setAttribute("name","李国栋");
request.setAttribute("name2","高圆圆");
web容器里面内部进行跳转,当前目录下面的xx.jsp
请求转发的特点:
1)地址栏没有变化
2)整个过程request对象一致
request对象---类型:HttpServletRequest:本身是域对象,域对象可以存数据
在jsp页面中,可以取数据
3)请求转发可以访问WEB—INF资源文件(WEB—INF的资源文件不能直接访问)
重定向
后端直接完成页面跳转---重定向方式也可以跳转页面,用于页面跳转
原理:
1)设置响应头名称location 以及跳转地址 "/web上下文路径/资源页面"
response.setHeader("location",request.getContextPath()+"/login.jsp");
2)设置响应状态 302 :进一步请求
response.setStatus(302);
浏览器第一次请求原界面,返回给浏览器信息,浏览器看到响应信息302将第二次请求login.jsp
重定向简写格式
// void sendRedirect(String var1) throws IOException;
response.sendRedirect(request.getContextPath()+"/login.jsp");
请求转发和重定向的区别
1.地址栏是否有变化
请求转发:地址栏没有变化
重定向:地址栏有变化
2.是否能够访问WEB-INF下的资源文件
请求转发:可以访问WEB-INF下的资源文件
重定向:不能访问WEB-INF下的资源文件
3.整个过程请求对象是否一致
请求转发:request对象一致,所以使用请求转发,在servlet存数据,请求转发jsp从request中获取数据
重定向:request对象不一致
4.是否能够访问外部项目资源文件(一个tomcat可以部署多个web项目)
请求转发:只能访问当前项目下的资源文件包括wEB-INE下面的资源文件
重定向:可以访问当项目下的资源文件以及访问其他项目下的资源文件
JSP—Java server Pages
jsp注释
<%-- 注释 --%> JSP注释,注释内容不会被发送至浏览器甚至不会被编译
< !--注释-- > HTML注释,通过浏览器查看网页源代码时可以看见注释内容
jsp的三大指令/九大内置对象
三大指令<%@page%>\<%@include%>\<%@taglib prefix="c" uri="xxx" %>
<%@page
contentType="text/html;charset=UTF-8" language="java"
isErrorPage="false"
errorPage="指定错误页面的路径" //errorPage="404.jsp"
%>
contentType:页面编码格式(默认的)
language:支持的语言格式java(默认)
isErrorPage:是否是错误页面:默认值是false()默认的
errorPage:如果当前页码存在问题(异常等),直接跳转错误页面上
buffer="8kb":jsp页面存储缓冲区大小 8kb(默认的)
isELIgnored:是否能够使用EL表达式 ${},默认为true可以使用
自定义:404页面
<%@ page
contentType="text/html;charset=UTF-8"
language="java"
isErrorPage="true" //这个页面是错误页面
%>
亲,您访问的资源找不到了
静态包含指令include
<%--静态包含指令
特点:不会将被导入进来的jsp文件(03_导航.jsp)单独进行翻译和编译:节省jsp内存
拼接到该文件(jsp)中
--%>
<%@include file="03_导航.jsp"%> //导入其他页面
<%--主页信息--%>
<%--taglib指令
导入jstl的核心库,指定前缀名称"c" c标签
uri:指定jsp/jstl/core地址
--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
9大内置对象:前面4个域对象:从小到大
PageContext page域:仅仅是当前某个jsp页面中有效,范围最小,页面跳转后无效
HttpServletRequest request域:在请求中有效,
HttpSession session域:一次会话中有效,浏览器关闭无效
ServletContext application域:在整个web程序中有效
//给request域中存储数据
pageContext.setAttribute("name","王宝强");
request.setAttribute("name","高圆圆"); //类似于Map结合
session.setAttribute("name","李国栋"); //session存储的服务器端的
application.setAttribute("name","赵又廷");
//取数据
<%=(String)request.getAttribute("name")%>
<%--el表达式默认在jsp是可以启用的 代替上面的输出表达式
${pageScope.属性名} page域中取数据 // ${pageScope.name3}
${requestScope.属性名} request域中取数据 //${requestScope.name}
${sessionScope.属性名} session域中取数据 //${sessionScope.name2}
${applicationScope.属性名} application域取数据 //${applicationScope.name4}
简写 ${name}
当属性明相同时:
${属性名}--必须从域对象搜索(从小到大搜索),里面是否存在数据,有的数据直接获取
EL表达式,OGNL对象图导航语言
<%--使用jsp的角标模拟服务器端代码--%>
<%
//存储User实体到request域中
User user = new User() ;
user.setUsername("高圆圆") ;
user.setGender("女");
user.setAge(44);
user.setAddress("西安市") ;
request.setAttribute("user",user);
%>
OGNL对象图导航语言:
<%=((User)request.getAttribute("user")).getName()%> //原书写方式
<%--el表达式可以操作javabean(javabean导航)
${存储的属性名称}--->类似于Map
${Key}--->获取到value
${Key.javabean实体的bean属性}
Object Graph Navigation Language ---OGNL 对象图导航语言:jsp支持/开源框架Spring家族/mybatis
${user} 就等价于(User)request.getAttribute("user") 获取到user对象
${user}访问getUsername():get()去掉,第一个字母小写:username
user对象实例.getUsername()方法
${user.username}
--%>
${user.name} - ${user.gender} - ${user.age} - ${user.address}
Servlet+jsp:实践
Servlet--->接收前端页面提交数据,调用service获取业务数据,在控制台视图以及数据(存储域对象中)
Jsp----->里面通过jsp内置对象:其中四个域对象:request域和Session域,从servlet取数据,展示数据:渲染视图
jstl标签库:里面核心标签:展示数据
<%
//频繁书写java代码(不推荐)
%>
Jsp:
1)翻译 :将jsp文件翻译成.java文件
2)编译 :将.java文件 编译.class文件
<%
jsp脚本书写,java代码
%>
jstl标签库
<%--使用jsp的角标模拟服务器端代码--%>
<%
//存储User实体到request域中
User user = new User() ;
user.setUsername("高圆圆") ;
user.setGender("女");
user.setAge(44);
user.setAddress("西安市") ;
request.setAttribute("user",user);
User user2 = new User() ;
user2.setUsername("王五") ;
user2.setGender("男");
user2.setAge(23);
user2.setAddress("渭南市") ;
List list = new ArrayList<>() ;
list.add(user) ;
list.add(user2) ;
request.setAttribute("list",list);
//jsp页面上遍历List集合获取里面每一个实体,需要jstl:jsp的标签库(导入jar包)
%>
<%--taglib指令
导入jstl的核心库,指定前缀名称"c" c标签
uri:指定jsp/jstl/core地址
--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
1、遍历集合标签foreach
<%--遍历集合数据
c:foreach标签的属性
items="从域对象获取的数据"
var ="循环中变量名"
--%>
<%--${循环中的变量}
${u}---就是每一个user实体
--%>
${u.name}
${u.gender}
${u.age}
${u.address}
<%-- varStatus="循环中状态属性">
它的属性值.ixdex:索引值,根据begin的值开始计算
--%>
${status.index}helloword${i}
2、<%--c:if:判断存储的数据内容是否满足要求
test属性=${域对象获取的数据}
empty:空
empty 对象名:表示对象是否为空
--%>
list集合是空的
list集合对象不为空
3、<%--c:choose
c:when test="${域对象获取数据}"
c:otherwise:类似java语言中选择结构语句
--%>
request.setAttribute("number",2);
星期一
星期二
非法数据
jstl函数库
< % @ taglib prefix= "fn" uri= "http://java.sun.com/jsp/jstl/functions" % >
${ fn : substring ( < string> , < beginIndex> , < endIndex> ) }
参数1 : 获取指定的字符串名称
参数2 : 指定开始截取的索引位置 从0 开始
参数3 : 最终索引, 包含endIndex- 1 处
< a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" style= 'color:#666' > ${ fn : substring ( p. pname, 0 , 6 ) } ... < / a>
信息摘要算法的工具:MessageDigest
//jdk提供:信息摘要算法的工具:MessageDigest
//public sattic MessageDigest getIntstance 创建当前类的实例
// String字符串内容---byte[] digest() :转换成字节数组
password = MD5Utils.md5(password) ;
HttpSession清除会话
//public void invalidate()
//1)从request对象中获取HttpSession
HttpSession session = request.getSession();
//2)判断
if(session!=null){
//将session清除了,使用会话无效
//public void invalidate()
session.invalidate();
}
//public void removeAttribute(String name);
从此会话中移除与指定名称绑定在一起的对象。如果会话没有与指定名称绑定在一起的对象,则此方法不执行任何操作。
超链接失效与js事件
请登录
恭喜,${admin.username}
<%-- 【退出】 --%>
超链接失效:javascript:void(0)
【退出】
function btn_logOut(){
//window:代表窗口对象
//window.loaction.href="加载地址":窗口打开一个页面
//top.laction.href="从顶部弹出一个页面"
top.location.href ="${pageContext.request.contextPath}/logOut" ;
}
function btn_login(){
//点击登录,打开登录页面
top.location.href="${pageContext.request.contextPath}/admin/admin_login.jsp"}
//修改
修改
1.原生js对象转为Jqery对象
function changeSpanInnerHTML(){
//使用Jquery对象方式:改变span的内容
//获取id="span"标签对象
var span = document.getElementById("span") ;
// span.innerHTML :原生js访问它的innerHTML:设置标签文本 (推荐)
// span.innerText :原生Js访问它的innerText:设置普通文本
var $span = $(span) ;
//设置它的文本方法:text(xx):等价于之前的innerText
// html("<标签名称>xxx标签名称>"):等价于innerHTML属性
$span.html("将span内容切换为了JavaEE ") ;
}
2.jquery对象转js对象 $("#xx").get(0) 0,1,2...依次获取
//页面载入事件
$(function (){
//逻辑
//给id="btn" 设置点击(Jquery的写法)
$("#btn").click(function(){
//$("#btn"):将它(Jq对象)转换成原生js对象
//Jq提供对象的方法:Jq对象.get(index):匹配第几个index的元素
var spanObj = $("#spanTip").get(0) ; //id="spanTip"
//原生Js改变它的文本
spanObj.innerHTML = "使用Jq对象转换Js改变为:Filter " ;
}) ;
}) ;
Jquery基本选择器
常用三个基本选择器
id选择器:$("#id属性值") :id必须唯一
1. class选择器:$(".class属性值"):class可以同名
2. element选择器:$("标签名称");
3. $(selector1,selector2,...):jquery并集选择器
//页面载入事件
$(function(){
//获取id="b1"标签对象,并设置点击
$("#b1").click(function (){
//改变 id 为 one 的元素的背景色为 红色
//Jquery对象设置样式:css("样式名称","样式样式")
//或者多个样式css({"样式名称1":"值1","样式名称2":"值2"}...)
$("#one").css("background-color","red") ;
}) ;
Jquery层级选择器/子元素选择器
层级选择器
$("selector1 selector2"):Jquery的后代选择器:匹配父标签下所有的子元素
//页面载入事件
$(function(){
//id="b1"设置点击
$("#b1").click(function(){
//改变 内所有 的背景色为红色
$("body div").css("background-color","red") ;
}) ;
子元素选择器
$("selector1 > selector2"):Jquery的子元素选择器,第二个选择器中的元素一定是第一个选择器中元素的子元素
//id="b2"设置点击
$("#b2").click(function(){
//改变 内子
的背景色为 红色
$("body>div").css("background-color","orange") ;
}) ;
Jquery属性选择器
Jquery属性选择器
$("元素名称[attribute]"):带有指定属性的元素
$("元素名称:[attribute=value]"):匹配给定元素具有特定值的元素
$("[attribute!=value]") :匹配给定元素不具备特定的值
$("[attribute^=value]"):匹配给定的属性以某些值开始的元素
$("[attribute$=value]"):匹配给定的属性以某些特定值结尾的元素
$("[attribute*=value]"):匹配给定的属性包含value值的元素
$("[selector1][selector2][selectorN]"):符合属性选择器,同时有多个属性满足条件
//含有属性title 的div元素背景色为红色
$("div[title]").css("background-color","red") ;
//属性title值等于test的div元素背景色为红色
$("div[title='test']").css("background-color","red") ;
//属性title值不等于test的div元素(没有属性title的也将被选中)背景色为红色
$("div[title!='test']").css("background-color","red") ;
//属性title值 以te开始 的div元素背景色为红色
$("div[title^='te']").css("background-color","red ") ;
//属性title值 以est结束 的div元素背景色为红色
$("div[title$='est']").css("background-color","red ") ;
//属性title值 含有es的div元素背景色为红色
$("div[title*='es']").css("background-color","red ") ;
//选取有属性id的div元素,然后在结果中选取属性title值含有“es”的 div 元素背景色为红色
$("div[id][title*='es']").css("background-color","red ") ;
Jquery文档处理
Jq对象.append("xx"):在文档内部追加指定内容
$("#ul").append("宝鸡 ")
Jq对象.appednTo("xx"):将XX内容添加到Jq对象指定元素的后面
$("#gz").appendTo($("#xa")) ;
Jq对象.prepend(content):在文档内容指定的元素的前面追加内容
$("#ul").prepend("神木 ");
Jq对象.prependTo(content):在文档内容指定的元素的前面追加内容
$("#sm").prependTo($("#xa")) ;
Jquery对象.after("xx"):在文档外部插入
$("#ul").after("宝鸡 ")
Jquery方式表单校验
//页面载入事件
$(function(){
//获取到id="formSubmit"的form标签对象
//Jquery里面的函数submit ---->类似form表单给了属性on submit
$("#formSubmit").submit(function(){
//验证表单元素
//用户名 密码 确认密码 邮箱
if(checkUsername() && checkPwd() && checkRepwd() && checkEmail()){
return true ;//表单提交
}
return false ;//禁用提交
}) ;
})
//校验用户名
function checkUsername(){
//获取id="username"的input标签对象同时获取内容
//var username = document.getElementById("username").value ;
//Jq方式获取用户名的内容
var username = $("#username").val() ;
alert(username) ;
//获取id="userTip"的span标签对象
//var span = document.getElementById("userTip") ;
var span = $("#userTip") ;
//创建正则规则
//用户名:6-16位数字或者字母组成
var reg = /^[A-Za-z0-9_]{6,16}$/ ;
/* if(username==""){
span.innerHTML ="用户名不能为空".fontcolor("red") ;
}*/
var flag = reg.test(username) ;
if(flag){
//成立,给span标签设置标签文本
// span.innerHTML = "恭喜您".fontcolor("green") ;
//给input标签对象css样式
$("#username").css("border","") ;
//满足正则规则提示
span.html("恭喜") ;
span.css("color","green") ;
}else{
//span.innerHTML = "不可用".fontcolor("red") ;
//给输入框的input对象设置边框样式
$("#username").css("border","1px solid red") ;
span.html("不可用") ;
span.css("color","red") ;
}
return flag ;
}
//校验确认密码
function checkRepwd(){
//获取密码框的内容
// var pwd = document.getElementById("pwd").value;
var pwd = $("#pwd").val() ;
//获取确认密码框的内容
//var repwd = document.getElementById("repwd").value ;
var repwd = $("#repwd").val() ;
//获取id="repwdTip"的span标签对象
// var span = document.getElementById("repwdTip") ;
var span =$("#repwdTip") ;
//两次内容一致
if(pwd.valueOf() == repwd.valueOf()){
// span.innerHTML = "一致".fontcolor("green") ;
$("#repwd").css("border","") ;
span.html("√ ") ;
span.css("color","green") ;
return true ;
}else{
// span.innerHTML = "两次信息不一致".fontcolor("red") ;
$("#repwd").css("border","1px solid red") ;
span.html("× ") ;
span.css("color","red") ;
return false ;
}
}
原生ajax的操作步骤
1)创建xmlHttpRequest
2)建立连接open(method,url,是否异步);
3)发送请求
4)等待响应
function mySendAjax() {
//1)创建xmlHttpRequest:浏览器代理对象
var xmlHttp;
if (window.XMLHttpRequest) {
//所有现代浏览器使用这个XMLHttpRequest
xmlHttp = new XMLHttpRequest();
} else {
// code for IE6, IE5 //很低版本的浏览器
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2)建立连接open
//open(method, url, async)
//参数1:请求方式: get/post
//如果get请求,可以地址栏携带参 url?key1=value1&key2=value2....
//参数2:和服务器端建立连接的地址 后端服务器接口地址
//参数3:默认true:表示异步,false,表示同步
xmlHttp.open("get", "/Jquery_boostrap_war/my?username=zhangsan", true);
//3)发送器请求到服务器地址
//send()
xmlHttp.send();
//4)异步交互:等待响应
//代理对象:监听服务器的状态的改变,会触发函数:
//onreadystatechange
xmlHttp.onreadystatechange = function () {
//等待响应状态 readyState是4并且状态码200响应成功
if (this.readyState == 4 && this.status == 200) {
//获取数据
//响应文本属性 responseText
//将服务器端响应过来的内容存储在这个代理对象中
alert(this.responseText);
}
}
}
jquery的ajax代替原生写法
//jquery的ajax发送异步请求
$.ajax(
type: 请求方式:GET/POST,(默认get)
url: 请求后端地址,
data: 请求的参数:如果get,还在url?key1=value1&key2=value2,
success:function(data){
//响应成功的回调函数,data:服务器响应的数据
},
error:function(data){
//失败的回调函数:data服务器响应过来的数据
},
dataType:服务器响应过来的数据格式 :jsonjson/text文本格式/html格式,
contentType:浏览器请求的服务器内容格式(可以不写)
//方式2:
$.get(url,参数,function(data),"服务器响应的格式");get提交
//方式3
$.post(url,参数,function(data),"服务器响应的格式"); post提交
$(function(){
//给用户名文本输入框添加失去焦点事件
$("#username").blur(function(){
//获取用户名的内容
var username = $(this).val() ;
$.ajax({
type:"get",
url:"/Jquery_boostrap_war/my?username="+username+"",
success:function(data){
//data服务器响应过来的数据
//{"code":1,"msg":"用户名太受欢迎了,请更换!"}
//{"code":0,"msg":"共享,可用"}
if(data.code==0){
alert(data.msg) ;
}
if(data.code==1){
alert(data.msg) ;
}
},
dataType:"json" //服务器响应来的数据格式
}) ;
}) ;
}) ;
JSON接收与发送数据
发送数据:
如果数据存储在JavaScript对象中,可以把该对象转换为JSON,然后将其发送到服务器。
var myJSON = JSON.strirlgify(myobj);
接收数据:
如果以]JSON格式接收到数据,能够将其转换为JavaScript对象
var myobj =JSON.parse(myJSON);
jsp的el表达式
jsp的el表达式
内置对象
${sessionScope.属性名} session域中取数据
${requestScope.属性名} request域域中取数据
${pageScope.属性名} page域中获取数据
${applicationScope.属性名} 全局(servletContext)获取数据
${cookie}:---Map ${cookie.名称} 获取cookie 对象
${param} --- Map 获取url地址栏上?后面的所有的参数名称以及参数值
${param.key}获取value
jstl: substring方法
${fn:substring(, , )}
参数1:获取指定的字符串名称
参数2:指定开始截取的索引位置 从0开始
参数3:最终索引,包含endIndex-1处
注解
注解是一种标记,是可用Java程序解析;
公共接口---本质就是一个接口:public interface Annotation---里面方法名在注解中,称为"属性"
@Annotation
注解分为:---底层都依赖"元注解":@Target:正在使用的注解它使用的范围(类上/方法/参数...)
@Retention:正在使用的直接它的保留阶段: SORUCE/CLASS/RUNTIME
1)jdk内置注解
@Override:标记这个方法是否实现接口或者重写父类的
@Deprecated //标记这个方法已经过时的,但是可以用
@SuppressWarnings//压制警告
@FunctionalInterface:函数式接口:当前接口中有且仅仅有一个抽象的方法,加入注解标记
@Override注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Target
@Target--->public @interface Target { //当前标记的这个注解能够在什么类型上用(方法用/类上用/参数上用...)
ElementType[] value();//value属性--返回值类型:枚举类型
---public enum ElementType{
TYPE, //当前这个注解可以用在类上
FIELD,//当前这个注解可以用在成员变量上
METHOD,//这个注解可以用在成员方法上
PARAMETER,//这注解可以用在形式参数上
CONSTRUCTOR,//能够用在构造函数上
LOCAL_VARIABLE,//能够用在局部变量上
ANNOTATION_TYPE,//能够注解类型上
PACKAGE,//能够用在包上
TYPE_PARAMETER, //能够使用在参数类型上
TYPE_USE //使用标记类型
}}
@Retention(RetentionPolicy.SOURCE):标记当前正在使用的注解的保留范围(标记当前这个在原码阶段)
@Retention(RetentionPolicy.RUNTIME) 标记当前这个注解的保留范围在运行阶段
//Java代码经历三个阶段
public enum RetentionPolicy {
SOURCE,//Java源代码阶段
CLASS,//Java编译阶段(类的加载-获取字节码文件对象,创建对象...)
RUNTIME//运行阶段 (一般自己用 Runtime)
}
自定义注解
自定义注解
@自定义名称 ---指定的属性
自定义注解 MySelfAnno
@Target(ElementType.TYPE) //能够在类上
@Retention(RetentionPolicy.RUNTIME) //保留在运行阶段上
public @interface MySelfAnno {
String value() ;
String name() ;
}
在类上加入刚才自定义的注解MySelfAnno
@MySelfAnno(value = "com.qf.ann.Fateher",name = "show")
public class ParseAnno {
public static void main(String[] args) {
//如何解析这里MySelfAnno的value和name?
//public A getAnnotation(类 annotationClass)
// 就可以直接获取"注解"(接口)的实现类
Class c = ParseAnno.class ;
}
}
1.
//自定义了一个注解:本质是接口 public @interface MyAnno{}
//标记MyAnno能够在类上使用,加入元注解
@Target(ElementType.TYPE)
//标记MyAnno保留在运行阶段上使用
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
//注解中的属性----也就是接口的方法名
//属性的返回值只有5中类型:
int myId() ; //myId属性的返回值int类型
String value() ; //value属性,返回值String类型
MyEnum my() ; //my属性返回值,枚举类型
MyAnn2 anno() ;//anno属性的返回值 注解类型
//以上四种类型的数组
String[] strs() ;//数组格式
}
2.
public enum MyEnum {
LEFT, //传统定义的类的时候自定义常量 :public static final 数据类型 变量名 = 初始化值;
RIGHT,
BEHIND,
FRONT ;
}
3.
//使用这个自定义注解:注解里面只有五种类型
@MyAnno(myId = 1,
value = "高圆圆",
my=MyEnum.BEHIND,
anno = @MyAnn2(value = "helloword"),
strs = {"servlet","hello"})
public class MyTest {
//@MyAnno() :只能在类上用
public void method(){
}
}
实际开发中:
大量使用第三方提供的注解:
现在使用Servlet---->@WebServlet:标记在类上使用,里面有很多的属性---代替了xml配置
//给MyTest2加入刚才自定义的注解
@MySelfAnno(className = "com.qf.demo.Worker",name = "love")
public class MyTest2 {
public static void main(String[] args) throws Exception {
//解析自定义注解
//1)获取当前类的字节码文件对象 MyTest2.class
Class c = MyTest2.class ;
//2)public A getAnnotation(类 annotationClass)
//参数是:当前注解类型的Class对象
MySelfAnno mySelfAnno = (MySelfAnno) c.getAnnotation(MySelfAnno.class);
//返回值是Annotation公共接口,需要强转为自己的注解类型
//上面操作:获取到了注解(接口)它的实现类,就可以调用方法(注解中的属性名)
String s1 = mySelfAnno.className();
//System.out.println(s1);
String name = mySelfAnno.name();
//System.out.println(name);
//反射代码
Class clazz = Class.forName(s1) ; //正在使用的类对象
//创建实例
Object obj = clazz.newInstance();
//获取这个类的方法Method类对象
Method method = clazz.getDeclaredMethod(name);
//取消Java语言访问检查
method.setAccessible(true) ;
//调用方法
method.invoke(obj) ;
}
}
Servlet启用注解方式
//@WebServlet(name="默认当前类名MyServlet",value="/my(可以配置多个路径,只有一个value则可以省略)",loadOnStartup=1(初始化时机,类一加载就创建实例),initParams=@WebInitParam(name="初始化参数",value="初始化值"))
@WebServlet("/my") //必须"/开头"
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("访问到了Servlet了");
response.getWriter().write("hello,Servlet,,,");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
Servlet启用注解方式---代替xml配置方式
@WebServlet
String name():name属性---等价于xml配置的时候 (不写,默认当前类名)
默认当前类名/可以自己定义名称
1 //web容器一启动,创建当前类实例
String[] value() default {};
int loadOnStartup() default -1; 等价于1
String[] urlPatterns() default {};
value属性和urlPatterns他们意义一样的,指定后端服务器请求地址 等价
/映射路径
WebInitParam[] initParams() default {} -->等价于
初始化参数
用户登录
1.jsp中设置登录的表单页面
//action:提交的服务器地址
用户 名
......
2.登录的servlet设置
//解决post提交乱码
request.setCharacterEncoding("utf-8");
//1)接收管理员登录用户密码
//2)密码需要加密 :get提交/post提交 都可以看到密码信息
String username = request.getParameter("username");
String password = request.getParameter("password");
//jdk提供:信息摘要算法的工具:MessageDigest-->
// public static MessageDigest getInstance :创建当前类的实例
// String字符串内容---byte[] digest() :转换成字节数组
//加密工具类
password = MD5Utils.md5(password) ;
//调用管理员业务接口,返回管理员用户实体
AdminService adminService = new AdminServiceImpl() ;
Admin admin = adminService.getAdminByName(username, password);
//进行判断,数据库中存在用户就将管理员实体存储在HttpSession中,否则请求转发到登录页面
if(admin!=null){
//从请求对象中获取HttpSession
HttpSession session = request.getSession() ;
session.setAttribute("admin",admin) ;
//重定向到admin/admin_index.jsp :后台主页
response.sendRedirect(request.getContextPath()+"/admin/admin_index.jsp");
}else{
//没找到用户请求转发到登录页面
request.setAttribute("msg","用户名或者密码输入错误") ;
request.getRequestDispatcher("/admin/admin_login.jsp").forward(request,response);
}
3.登录的用户业务接口实现
public Admin getAdminByName(String username,String password) {
try {
//调用dao :管理员的数据访问接口
AdminDao ad = new AdminDaoImpl() ;
Admin admin = ad.selectAdmin( username) ;
if(admin!=null){
//判断密码是否一致
if(admin.getPassword().equals(password)){
return admin ;
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
4.访问数据库
public Admin selectAdmin(String username) throws SQLException {
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
String sql = "select * from admin where username = ?" ;
Admin admin = qr.query(sql, new BeanHandler<>(Admin.class), username);
return admin;
}
用户登录成功-查询所有商品-图解
用户注销
判断当前是否在session中存在用户,存在则显示(XX已登录,注销),不存在(用户未登录)则显示请登录
//1)pom.xml中导入jstl包
taglibs
standard
1.1.2
//2)当如jstl核心标签库
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
//3)判断是否存在用户登录
请登录
恭喜,${admin.username}
<%-- 【退出】 --%>
<%--超链接失效--%>
【退出】
//4)设置点击事件
//5)设置注销的servlet
//1)从request对象中获取HttpSession
HttpSession session = request.getSession();
//2)判断
if(session!=null){
//将session清除了,使用会话无效
//public void invalidate()
session.invalidate();
}
//重定向到管理员主页
response.sendRedirect(request.getContextPath()+"/admin/admin_index.jsp");
window打开窗口
window:代表窗口对象
window.location.href="地址" 窗口打开一个页面
top.location.href="地址" 从顶部弹开一个页面
新的请求对象,存储在request中的信息会没有,分页查询页码数据须在地址后重新接默认值
MVC架构思想
Model:业务模型
pojo里面存储存放的实体类(JavaBean)
service:业务层----完成的业务逻辑功能(登录/注册/获取某个实体/获取列表...)
dao:持久层 ----操作数据库db,获取数据---返回service层
View:视图
html / 模板引擎 :
jsp (el表达式/核心库jstl)/freemarker网页静态化技术...
/vue框架 +elementUI(组件/布局容器...)
Controller:控制器
通过服务连接器: 处于前端和业务接口中间层---servlet 获取service层的数据,
控制视图(后端请求转发/重定向),或者响应json串
前台用户管理
一.查询所有用户
查询所有用户1:定义jsp展示数据
< table border= "1px" align= "center" width= "100%" height= "500px" >
< tr>
< th> 用户编号< / th>
< th> 用户昵称< / th>
< th> 真实姓名< / th>
< th> 用户邮箱< / th>
< th> 用户性别< / th>
< th> 用户操作< / th>
< / tr>
< c: forEach items= "${users}" var = "u" >
< tr>
< td> ${ u. uid} < / td>
< td> ${ u. username} < / td>
< td> ${ u. name} < / td>
< td> ${ u. email} < / td>
< td> ${ u. sex} < / td>
< td>
< a href= "javascript:void(0)" onclick= "update('${u.uid}')" style= "color: blue" > 修改< / a>
< a href= "#" style= "color: red;" > 删除< / a>
< / td>
< / tr>
< / c: forEach>
< / table>
查询所有用户2:定义servlet
管理员获取所有用户的后端服务地址
*/
public class AdminGetAllUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//调用业务接口
AdminService adminService = new AdminServiceImpl() ;
List users = adminService.allUsers() ;
if(users!=null){
//将users存储在request域中
request.setAttribute("users",users) ;
//请求转发到管理员里面用户列表页面
request.getRequestDispatcher("/admin/user/user_list.jsp").forward(request,response);
}else{
request.setAttribute("msg","未获取到数据");
request.getRequestDispatcher("/message.jsp").forward(request,response);
}
}
查询所有用户3:service实现
/**
* 查询所有前台用户
* @return 返回用户列表
*/
@Override
public List allUsers() {
try {
//调用AdminDao:数据库中获取用户列表
AdminDao adminDao = new AdminDaoImpl() ;
List users = adminDao.selectAllUsers() ;
if(users!=null || users.size()>0){
//有数据
//返回
return users;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
查询所有用户4:dao实现
/**
* 管理员数据访问接口查询所有前台用户
* @return 返回用户列表
*/
@Override
public List selectAllUsers() throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select * from user" ;
//查询
List list = qr.query(sql, new BeanListHandler<>(User.class));
return list;
}
二:添加用户
添加用户1:定义jsp
用户ID
<%--表单中的所有name属性和实体的属性名称一致--%>
用户昵称
真实姓名
用户邮箱
用户性别
添加用户2:定义servlet后端地址
管理员添加用户后端地址
*/
public class AdminAddUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决添加用户的中文乱码(post提交)
request.setCharacterEncoding("utf-8") ;
//接收参数
String uid = request.getParameter("uid");
String username = request.getParameter("username");
String name = request.getParameter("name");
String eamil = request.getParameter("email");
String sex = request.getParameter("sex");
//封装User对象
User user = new User() ;
user.setUid(uid) ;
user.setUsername(username) ;
user.setEmail(eamil) ;
user.setName(name);
user.setSex(sex);
//调用AdminService业务接口
AdminService adminService = new AdminServiceImpl() ;
adminService.add(user) ;
//请求转发到查询所有的后台地址上
request.getRequestDispatcher("/getAllUser").forward(request,response);
System.out.println("添加成功");
}
添加用户3:定义service
/**
* 添加前台用户
* @param user 用户实体
*/
@Override
public void add(User user) {
try {
//访问管理员的数据访问接口
AdminDao adminDao = new AdminDaoImpl() ;
adminDao.insertUser(user) ;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
添加用户4:dao实现
/**
* 添加前台用户
* @param user 用户实体
*/
@Override
public void add(User user) {
try {
//访问管理员的数据访问接口
AdminDao adminDao = new AdminDaoImpl() ;
adminDao.insertUser(user) ;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
三:修改用户
修改用户1:先查询用户,展示数据
function update(uid){
// alert(uid) ;
window.location.href="${pageContext.request.contextPath}/adminGetUser?uid="+uid ;
}
public class AdminGetUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 前端发送的请求:window.loaction.href="${pageContext.request.contextPath}/adminGetUser?uid="+uid ;
String uid = request.getParameter("uid");
System.out.println(uid);
//调用管理员的业务接口
AdminService adminService = new AdminServiceImpl() ;
User user = adminService.getUser(uid) ;
//将user对象存在request域中
request.setAttribute("user",user) ;
//请求转发到admin/user/update_user.jsp
request.getRequestDispatcher("/admin/user/update_user.jsp").forward(request,response);
}
<%--隐藏域 :没有效果,但是可以携带数据--%>
<%--uid=xxxx值--%>
<%--
用户ID
<%–表单中的所有name属性和实体的属性名称一致–%>
--%>
用户昵称
真实姓名
用户邮箱
用户性别
修改用户2:查询到的用户数据界面,显示用户数据,并按修改后提交到修改的后端地址
//解决post提交中文乱码
request.setCharacterEncoding("utf-8") ;
//获取修改的参数
String uid = request.getParameter("uid");
String username = request.getParameter("username");
String name = request.getParameter("name");
String email = request.getParameter("email");
String sex = request.getParameter("sex");
//System.out.println(uid+"---"+username+"---"+name+"---"+email+"----"+sex);
//封装User对象
User user = new User() ;
user.setUid(uid) ;
user.setUsername(username) ;
user.setName(name) ;
user.setEmail(email) ;
user.setSex(sex); ;
//调用管理员的业务接口
AdminService adminService = new AdminServiceImpl() ;
adminService.updateUser(user) ;
//请求转发到查询所有的服务端地址
request.getRequestDispatcher("/getAllUser").forward(request,response);
}
/**
* 更新用户
* @param user 用户实体
*/
@Override
public void updateUser(User user) {
try {
//调用AdminDao更新数据库
AdminDao adminDao = new AdminDaoImpl() ;
adminDao.updateUser(user) ;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
/**
* dao层数据访问接口操作数据库---更新用户
* @param user 用户实体
*/
@Override
public void updateUser(User user) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "update user set username=?,name=?,email=?,sex=? where uid= ?" ;
qr.update(sql,
user.getUsername(),
user.getName(),
user.getEmail(),
user.getSex(),
user.getUid()) ;
}
删除用户
< a href= "javascript:void(0)" onclick= "delUser('${u.uid}')" style= "color: red;" > 删除< / a>
< script>
function delUser ( uid) {
var flag = window. confirm ( "您忍心删除吗?" ) ;
if ( flag) {
window. location. href= "${pageContext.request.contextPath}/delUser?uid=" + uid ;
} }
< / script>
public class AdminDelUserServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
String uid = request. getParameter ( "uid" ) ;
AdminService adminService = new AdminServiceImpl ( ) ;
adminService. deleteUser ( uid) ;
request. getRequestDispatcher ( "/getAllUser" ) . forward ( request, response) ;
}
分页查询
增加\修改\删除数据后若想跳转到分页查询页面,需传入当前页码及每页显示条数参数
//请求转发到查询所有的服务端地址
request.getRequestDispatcher("/getAllUser?curPage=1&pSize=4").forward(request,response);
分页查询步骤1:自定义分页实体PageBean
自定义分页实体
public class PageBean {
//5个属性
private int currentPage ; //当前页码
private int pageSize ; //每页显示的条数
private int totalPage ; //总页数 //计算出来的,查询到总记录数 除以 pageSize
private int totalCount ; // 总记录数
private List pageList ; //分页查询的列表数据
public PageBean() {
}
public PageBean(int currentPage, int pageSize, int totalCount, List pageList) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.totalCount = totalCount;
this.pageList = pageList;
}
//总页数计算出来
public int getTotalPage() {
return ((totalCount % pageSize == 0)?(totalCount/pageSize):(totalCount/pageSize)+1);
}
/* public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}*/ 不提供
分页查询步骤2:jsp设置默认页码/每页显示数量
查询所有用户
//默认当前页码为第一页,每页显示4条信息 ,提交到/getAllUser服务器地址上
分页查询步骤3:定义服务器地址/getAllUser
页面链接请求次服务器地址
携带参数当前页码, 每页显示条数curPage= 1 & pSize= 4 , 类型为字符串类型
@WebServlet ( "/getAllUser" )
public class AdminGetAllUserServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
String curPage = request. getParameter ( "curPage" ) ;
String pSize = request. getParameter ( "pSize" ) ;
int currentPage = Integer . parseInt ( curPage) ;
int pageSize = Integer . parseInt ( pSize) ;
AdminService adminService = new AdminServiceImpl ( ) ;
PageBean < User > pb = adminService. getUserByPage ( currentPage, pageSize) ;
request. setAttribute ( "pb" , pb) ;
request. getRequestDispatcher ( "/admin/user/user_list.jsp" ) . forward ( request, response) ;
分页查询步骤4:AdminService业务层实现
业务层通过代用dao层获取分页列表数据list, 总记录数totalCount, 封装分页实体返回给servlet
@Override
public PageBean < User > getUserByPage ( int currentPage,
int pageSize) {
try {
AdminDao adminDao = new AdminDaoImpl ( ) ;
List < User > list = adminDao. selectUserByPage ( currentPage, pageSize) ;
int totalCount = adminDao. getTotalCount ( ) ;
if ( list!= null || list. size ( ) > 0 ) {
return new PageBean < > ( currentPage, pageSize,
totalCount, list) ;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return null ;
}
分页查询步骤5:dao层实现
1. 分页查询数据库数据
2. 查询总数
@Override
public List < User > selectUserByPage ( int currentPage, int pageSize) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from user limit ?,?" ;
List < User > users = qr. query ( sql, new BeanListHandler < > ( User . class ) , ( currentPage - 1 ) * pageSize, pageSize) ;
return users;
}
@Override
public int getTotalCount ( ) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select count(uid) from user" ;
Object obj = qr. query ( sql, new ScalarHandler < > ( ) ) ;
int totalCount = Integer . parseInt ( String . valueOf ( obj) ) ;
return totalCount;
}
分页查询步骤6:jsp列表定义展示数据
接收servlet传过来的分页实体PageBean,"pb"
包含当前页码数 currentPage,每页显示的条数totalPage,总页数totalPage计算出来的,总记录数totalCount,分页查询的列表数据pageList
1.导入样式及jquery
2.使用boostrap样式定义列表表格
用户编号
用户昵称
真实姓名
用户邮箱
用户性别
用户操作
//遍历分页查询到的数据
${u.uid}
${u.username}
${u.name}
${u.email}
${u.sex}
//操作列,获取可获取当前用户实体的id值
修改
删除
3.表格右下角显示总数
共有${pb.totalPage} 页
共有${pb.totalCount} 记录
4.boostrap分页组件,定义页码的按钮,传入页码数及页面记录总数,跳转再次进入servlet进行查询
数据增删改设置提醒弹窗
script>
function delUser(uid){
// alert(uid) ;
//友情提示,确认提示框
var flag = window.confirm("您忍心删除吗?") ;//确认返回ture,取消或x返回false
if(flag){
//alert("要删除了") ;
window.location.href="${pageContext.request.contextPath}/delUser?uid="+uid ; xxx
}
}
function update(uid){
// alert(uid) ;
window.location.href="${pageContext.request.contextPath}/adminGetUser?uid="+uid ;
}
function addUser(){
window.location.href="${pageContext.request.contextPath}/admin/user/add_user.jsp";
xxx
}
ajax校验用户名是否可用
1.jsp页面+ajax校验
用户名
//用户名输入之后,鼠标移出之后触发失去焦点事件
$("#username").blur(function(){
//异步校验用户名(昵称)是否可用
//获取用户名的内容
var username = $("#username").val() ;
alert(username) ;
//获取id="tip"标签对象
var div = $("#tip");
//发送ajax
$.ajax({
type:"get",
url :"${pageContext.request.contextPath}/checkUser?username="+username+"",
success:function(data){
//服务器响应成功的回调函数
//获取数据
if(data.code==0){
//可用
//给$span设置标签文本
div.html(data.msg) ;
//设置样式
div.css("color","green") ;
}
if(data.code==1){
//不可用
//给$span设置标签文本
div.html(data.msg) ;
//设置样式
div.css("color","red") ;
$("#username").css("border","1px solid red") ;
}
},
dataType:"json"
}) ;
2.响应实体定义
public class ResponseResult {
private Object data ; //任意java对象
private int code ; //0,没有数据 1,有数据
private String msg ; //消息字符串
public ResponseResult() {
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
3.定义后端servlet地址
@WebServlet ( "/checkUser" )
public class CheckUserServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request,
HttpServletResponse response) throws ServletException , IOException {
response. setContentType ( "text/html;charset=utf-8" ) ;
String username = request. getParameter ( "username" ) ;
UserService userService = new UserServiceImpl ( ) ;
ResponseResult responseResult = userService. getUser ( username) ;
String jsonStr = JsonUtils . object2json ( responseResult) ;
response. getWriter ( ) . write ( jsonStr) ;
}
4.定义Service
@Override
public ResponseResult getUser ( String username) {
ResponseResult rr = null ;
try {
UserDao ud = new UserDaoImpl ( ) ;
User user = ud. selectUserByUsername ( username) ;
rr = new ResponseResult ( ) ;
if ( user== null ) {
rr. setCode ( 0 ) ;
rr. setData ( null ) ;
rr. setMsg ( "恭喜您,可用" ) ;
} else {
rr. setCode ( 1 ) ;
rr. setData ( null ) ;
rr. setMsg ( "用户名太受欢迎了,请更换!" ) ;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return rr;
}
5.dao实现
/**
* 数据库访问接口 通过用户名查询指定的用户
* @param registerUsername 注册的用户名
* @return 返回用户实体
*/
@Override
public User selectUserByUsername(String registerUsername) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select * from user where username = ?" ;
//执行查询
User user = qr.query(sql, new BeanHandler<>(User.class), registerUsername);
return user;
}
注册/登录图片验证码使用
一:验证码工具类:ImgUtils
public class ImgUtils extends HttpServlet {....}
//继承HttpServlet,需在web.xml中进行配置,
工具类核心代码:
//产生4个随机验证码
String checkCode = getCheckCode();
//将验证码放入HttpSession中 //存储在服务器端
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
二:登录主页先进行设置
//验证码通过工具类ImgUtils存储在HttpSession中
//1) 接表单输入的验证码内容
String code = request.getParameter("code");
//2) 获取HttpSession
HttpSession session = request.getSession();
//3) 从session取出服务器端存储的验证码
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
//4) 验证码一次验证,如果当前这次输入出错了,将上一次的信息从session中删除
session.removeAttribute("CHECKCODE_SERVER");
//5) 验证表单提交的验证码是否和服务器端存储的验证码内容是否一致,不区分大小写
if(code==null || !checkcode_server.equalsIgnoreCase(code)){
request.setAttribute("msg","验证码输入错误") ;
//请求转发到登录界面
request.getRequestDispatcher("/admin/admin_login.jsp").forward(request,response);
return;
}
三:jsp中
验证码
//点击图片刷新
function checkCode(){
//获取id="img1"的标签对象
var img = document.getElementById("img1");
//一点击就改变img的src属性,产生一个新的图片验证码
img.src="${pageContext.request.contextPath}/checkCode?newDate=" +new Date();
}
前台用户注册-同步提交
前台用户注册1:jsp页面
注册 REGISTER
${msg}
用户名
前台用户注册2:响应实体定义
public class ResponseResult {
private Object data ; //任意java对象
private int code ; //0,没有数据 1,有数据
private String msg ; //消息字符串
public ResponseResult() {
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
前台用户注册3:自定义转换器:日期转换器
public interface Constant {
public static final int USER_ACTIVE = 1 ;
}
//自定义转换器:日期转换器
//自定义类实现org.apache.commons.beanutils.Converter接口
public class MyDateConverter implements Converter {
//转换方法
@Override
public T convert(Class aClass, Object source) {
try {
//字符串日期文本---java.util.Date ---> Date parse(String日期文本)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;
Date date = sdf.parse((String) source);
return (T) date;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
前台用户注册4:服务器地址servlet定义+BeanUtils封装用户实体+邮箱验证
@WebServlet ( "/registerUser" )
public class RegisterUserServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
request. setCharacterEncoding ( "utf-8" ) ;
String code = request. getParameter ( "code" ) ;
HttpSession session = request. getSession ( ) ;
String checkcode_server = ( String ) session. getAttribute ( "CHECKCODE_SERVER" ) ;
session. removeAttribute ( "CHECKCODE_SERVER" ) ;
if ( code == null || ! checkcode_server. equalsIgnoreCase ( code) ) {
request. setAttribute ( "msg" , "验证码错误" ) ;
request. getRequestDispatcher ( "/jsp/register.jsp" ) . forward ( request, response) ;
return ;
}
Map < String , String [ ] > parameterMap = request. getParameterMap ( ) ;
User user = new User ( ) ;
ConvertUtils . register ( new MyDateConverter ( ) , Date . class ) ;
try {
BeanUtils . populate ( user, parameterMap) ;
} catch ( IllegalAccessException e) {
e. printStackTrace ( ) ;
} catch ( InvocationTargetException e) {
e. printStackTrace ( ) ;
}
user. setUid ( UUIDUtils . getId ( ) ) ;
String password = user. getPassword ( ) ;
password = MD5Utils . md5 ( password) ;
user. setPassword ( password) ;
user. setCode ( UUIDUtils . getCode ( ) ) ;
UserService userService = new UserServiceImpl ( ) ;
userService. addUser ( user) ;
request. setAttribute ( "msg" , "注册成功,请在注册邮箱进行激活!" ) ;
request. getRequestDispatcher ( "/message.jsp" ) . forward ( request, response) ;
}
@Override
protected void doPost ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
doGet ( request, response) ;
}
}
前台用户注册5:业务层sercvice实现添加用户\发送激活邮件
添加用户
/**
* 添加用户
* @param user 用户实体
*/
@Override
public void addUser(User user) {
try {
//调用UserDao
UserDao userDao = new UserDaoImpl() ;
userDao.insertUser(user) ;//插入数据
//给注册邮箱上发送一份邮件:需要正文---超链接
String content = "欢迎注册,请点击激活 " ;//邮件正文
MailUtils.sendMail(user.getEmail(),content,"用户邮件激活") ;
//sendMail(目标邮件,邮件内容超链接,邮件标题),需导入支持邮件技术的jar包,自定义邮件工具类
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
ajax异步校验查询用户是否存在
/**
* 通过用户名查询用户是否存在
* @param username 用户名
* @return 如果数据存在或者不存在,返回自定义实体对象,设置对应的属性值
*/
@Override
public ResponseResult getUser(String username) {
ResponseResult rr = null ;
try {
//访问数据库:调用UserDao
UserDao ud = new UserDaoImpl() ;
User user = ud.selectUserByUsername(username);
//创建自定义响应实体对象
rr = new ResponseResult() ;
//如果user是null,没有查到,可以注册
if(user==null){
//封装数据
rr.setCode(0) ;
rr.setData(null);
rr.setMsg("恭喜您,可用");
}else{
rr.setCode(1);
rr.setData(null);
rr.setMsg("用户名太受欢迎了,请更换!");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return rr;
}
前台用户注册6:Dao层实现添加用户
/**
* 用户的数据访问接口添加用户
* @param user 用户实体
*/
@Override
public void insertUser(User user) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "insert into user values(?,?,?,?,?,?,?,?,?,?)" ;
int count = qr.update(sql,
user.getUid(),
user.getUsername(),
user.getPassword(),
user.getName(),
user.getEmail(),
user.getTelephone(), //这个数据暂时没有
user.getBirthday(),
user.getSex(),
user.getState(),
user.getCode());
}
前台用户注册7:点击邮箱验证
1.pom.xml导入
javax.mail
mail
1.4
2.邮件工具类
private static final String USER = "[email protected] "; // 发件人称号,同邮箱地址
private static final String PASSWORD = "csobpqlwmowybfcc"; // 如果是qq邮箱/其他邮箱等可以使户端授权码,或者登录密码
邮箱接收的地址
String content = "欢迎注册,请点击激活 " ;
前台用户注册7:点击邮箱验证-servle后端地址定义
邮箱显示数据
邮箱接收的地址
String content = "欢迎注册,请点击激活 " ;
@WebServlet( "/activeUser")
public class ActiveUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//http://localhost:8080/Maven_2302_war_exploded/activeUser?code=477D3B9AFEA4474B8B044E7DDBAD199D
//接收参数
String code = request.getParameter("code");
//调用UserService
UserService userService = new UserServiceImpl() ;
User user = userService.getUserByCode(code);
if(user!=null){
request.setAttribute("msg","用户激活成功,请登录 ");
request.getRequestDispatcher("/message.jsp").forward(request,response);
}
}
前台用户注册7:点击邮箱验证-service定义,State设为1,已激活
/**
* 通过激活码获取用户
* @param code 用户的激活码
* @return 返回用户实体
*/
@Override
public User getUserByCode(String code) {
try {
//访问数据接口
UserDao userDao = new UserDaoImpl() ;
User user = userDao.selectUserByCode(code) ;
//逻辑判断
if(user==null){
return null ;
}else{
//存在
//更新用户的激活状态
user.setState(1) ;
//更新数据库---调用数据访问接口
userDao.updateUserState(user) ;
return user ;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
前台用户注册7:点击邮箱验证-Dao实现-根据激活码查询用户,修改用户的激活状态
/**
* 数据访问接口根据激活查询指定用户
* @param code 激活码
* @return 返回用户实体
*/
@Override
public User selectUserByCode(String code) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select * from user where code = ?" ;
//查询
User user = qr.query(sql, new BeanHandler<>(User.class), code);
return user;
}
/**
* 更新用户的激活状态
* @param user 用户实体
*/
@Override
public void updateUserState(User user) throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "update user set state = ? where uid = ?" ;
int count = qr.update(sql,
user.getState(),
user.getUid());
}
}
用户实体
private String uid ;//用户编号 (UUID工具生成随机字符串)
private String username ;//昵称
private String password ;//用户密码
private String name ; //前台用户的真实姓名
private String email ; //邮箱
private String telephone ;//电话号码
private Date birthday ;//用户出生日期
private String sex ; //性别
private int state ;//用户激活状态: 默认值0,未激活(前台用户不能登录),1表示登录
private String code ;//用户的激活码 (jdk提供工具:UUID参数随机字符串)
前台用户注册-异步提交
//如果写js表单校验,每一个表单元素---都满足正则条件,然后表单提交
//表单提交---jquery的ajax提交表单
$("#registerForm").submit(function(){
$.ajax({
type:"get", url:"${pageContext.request.contextPath}/registerUser" ,//前台用户注册的服务地址
data:$("#registerForm").serialize(), //获取$("#registerForm")的表单,进行序列化操作
//"key1=vaue1&key2=value2"
success:function(data){
/*if(data.code ==0){
alert(data.msg) ;
}*/
//服务器响应成功的回调函数
//获取到的自定义数据里json串key-->data如果是true,
//window.location.href = "" ;//跳转消息提示页,注册成功,请登录
},
dataType:"json"
}) ;
前台用户登录
前台用户登录步骤1:jsp页面
Rice mall登录 LOGIN
${msg}
验证码
前台用户登录步骤2:servlet定义页面(验证用户是否激活)
@WebServlet ( "/userLogin" )
public class UserLoginServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response)
throws ServletException , IOException {
request. setCharacterEncoding ( "utf-8" ) ;
HttpSession session = request. getSession ( ) ;
String code = request. getParameter ( "code" ) ;
String checkcode_server = ( String ) session. getAttribute ( "CHECKCODE_SERVER" ) ;
session. removeAttribute ( "CHECKCODE_SERVER" ) ;
if ( code== null || ! checkcode_server. equalsIgnoreCase ( code) ) {
request. setAttribute ( "msg" , "验证码错误!" ) ; request. getRequestDispatcher ( "/jsp/login.jsp" ) . forward ( request, response) ;
return ;
}
String username = request. getParameter ( "username" ) ;
String password = request. getParameter ( "password" ) ;
password = MD5Utils . md5 ( password) ;
UserService userService = new UserServiceImpl ( ) ;
User user = userService. getUseByUserNameAndPwd ( username, password) ;
System . out. println ( user) ;
if ( user == null ) {
request. setAttribute ( "msg" , "用户名或者密码输入错误!" ) ;
request. getRequestDispatcher ( "/jsp/login.jsp" ) . forward ( request, response) ;
return ;
}
if ( user. getState ( ) != Constant . USER_ACTIVE) {
request. setAttribute ( "msg" , "用户状态未激活,请到邮箱先激活" ) ;
request. getRequestDispatcher ( "/jsp/login.jsp" ) . forward ( request, response) ;
return ;
}
session. setAttribute ( "user" , user) ;
response. sendRedirect ( request. getContextPath ( ) + "/jsp/index.jsp" ) ;
}
前台用户登录步骤3:service业务实现
@Override
public User getUseByUserNameAndPwd ( String username, String password) {
try {
UserDao userDao = new UserDaoImpl ( ) ;
User user = userDao. selectUserByUsername ( username) ;
if ( user!= null ) {
if ( user. getPassword ( ) . equals ( password) ) {
return user ;
}
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return null ;
}
前台用户登录步骤4:dao业务实现
@Override
public User selectUserByUsername ( String registerUsername) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from user where username = ?" ;
User user = qr. query ( sql, new BeanHandler < > ( User . class ) , registerUsername) ;
return user;
}
主页头部显示登录人信息
< c: if test= "${empty user}" >
< li> < a href= "${pageContext.request.contextPath}/jsp/login.jsp" > 登录< / a> < / li>
< li> < a href= "${pageContext.request.contextPath}/jsp/register.jsp" > 注册< / a> < / li>
< / c: if >
< c: if test= "${not empty user}" >
< strong> 欢迎${ user. name} 登录, < / strong> < a href= "#" > 【退出】< / a>
< / c: if >
用户登出
@WebServlet("/logOut")
public class AdminLogOutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1)从request对象中获取HttpSession
HttpSession session = request.getSession();
//2)判断
if(session!=null){
//将session清除了,使用会话无效
//public void invalidate()
session.invalidate();
}
//重定向到管理员主页 response.sendRedirect(request.getContextPath()+"/admin/admin_index.jsp");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}
Cookie
Cookie 的使用步骤
@WebServlet ( "/myCookie" )
public class CookieServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
Cookie cookie = new Cookie ( "name" , "李国栋" ) ;
Cookie cookie2 = new Cookie ( "name2" , "王宝强" ) ;
cookie. setMaxAge ( 3600 ) ;
cookie2. setMaxAge ( 3600 ) ;
response. addCookie ( cookie) ;
response. addCookie ( cookie2) ;
/ public Cookie [ ] getCookies ( )
Cookie [ ] cookies = request. getCookies ( ) ;
if ( cookies!= null ) {
for ( Cookie c : cookies) {
String name = c. getName ( ) ;
String value = c. getValue ( ) ;
}
} else {
System . out. println ( "浏览器第一次访问,没有cookie数据!" ) ;
}
}
Cookie和HttpSession的区别?
1)存储数据类型的区别
cookie:只能存储String类型
HttpSession:存储任意Java类型,因为它是域对象 setAttribute(String name,Object obj)
2)存储位置的区别
cookie:存储在浏览器端,是有服务器携带给浏览器
HttpSession:是存在服务器端的,但是HttpSession依赖于Cookie的
cookie的名称:"JSESSIONID" "随机的ID字符串(标识)"
是一种持久存储"持久化",在setAttribute(String name,Object obj),"钝化"
给SESSION.ser文件写入内容,即使服务器关闭了,文件还在;
再次启动服务器,HttpSession对象.getAttribute(String name)--->"活化",从本地磁盘桑
SESSION.ser文件读取内容;
3)是否有限限制
Cookie是有限制,浏览器 可以存储20-30站点,每一个站点理论300个cookie
HttpSession无限制,不断的进行"钝化",setAttribute(String name,Object obj)写数据到文件中
过滤器Filter
过滤器的使用及生命周期
自定义一个类,让这个类实现Filter接口,重写里面的三个方法
过滤器:
1.默认是web容器启动的时候创建当前类实例,而且进行初始化: 就一次
2.过滤任务DoFilter:过滤器的入口,不断的反复调用
3.销毁:服务器正常关闭,web容器需要将过滤器实例进行销毁(标记,清除!)
@WebFiler替代xml配置方式
String[] value();
String[] urlPatterns(); //过滤的路径:一般就使用 value,
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
// dispatcherTypes属性就是过滤器的过滤规则:直接访问还是请求转发/还是地址栏上包含某个路径等等
@WebFilter(value = "/login.jsp",dispatcherTypes = {DispatcherType.REQUEST})
public class MyFilter implements Filter {
// value = "/login.jsp" 拦截的地址 value = "/*" 拦截所有
//无参构造方法
public MyFilter(){
System.out.println("MyFilter对象被创建了...web容器一启动就创建");
}
/**
* 过滤器的初始化
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//FilterConfig过滤器的配置对象
System.out.println("init方法被调用了...." );
//过滤器配置对象FilterConfig
String filterName = filterConfig.getFilterName();
System.out.println(filterName ) ;
}
//过滤任务:过滤的逻辑
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求来了,过滤任务里面获取请求相关的信息
HttpServletRequest request = (HttpServletRequest) servletRequest;
//获取浏览器携带的所有cookie
Cookie[] cookies = request.getCookies() ;
if(cookies!=null){
for(Cookie c: cookies){
System.out.println(c.getName()+"---"+c.getValue());
}
}else{
System.out.println("没有cookie");
}
//服务器响应,可以处理响应相关的信息
HttpServletResponse response = (HttpServletResponse) servletResponse;
//获取前端提交的方式
String method = request.getMethod();
System.out.println("过滤任务中获取到了前端提交方式:"+method);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("hello,响应成功了!");
//放行
//参数3:过滤链
filterChain.doFilter(request,response) ;
}
//销毁
@Override
public void destroy() {
System.out.println("MyFilter.destory执行了...");
}
}
全局过滤器,解决请求及响应乱码
解决全局中文乱码的过滤器
* 解决post提交中文乱码,解决响应的中文的乱码
*/
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("CharacterEncodingFilter初始化了");
}
public void destroy() {
}
//过滤任务
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//将req,resp强转为子接口HttpServetlRequest/HttpServletResponse
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//获取前端提交方式
String method = request.getMethod();
if("POST".equals(method)){ //POST提交
//解决POST提交中文乱码
request.setCharacterEncoding("utf-8") ;
}
//处理响应的中文乱码
response.setContentType("text/html;charset=utf-8") ;
//放行
chain.doFilter(request, response);
}
}
前台用户登录,勾选自动登录,用户信息存储在Cookie中,实现自动登录
步骤1:jsp中设置自动登录
自动登录
记住用户名
步骤2:Servlet实现
@WebServlet("/userLogin")
public class UserLoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//0)解决post中文乱码
//request.setCharacterEncoding("utf-8");
//1)校验验证码 ,因为验证码存储在服务器端的
HttpSession session = request.getSession();
//接收name="code"这个验证码数据
String code = request.getParameter("code");
//获取服务器端的存储验证码
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
//一次性验证
session.removeAttribute("CHECKCODE_SERVER");
if("".equals(code) || !checkcode_server.equalsIgnoreCase(code)){
request.setAttribute("msg","验证码错误!");
request.getRequestDispatcher("/jsp/login.jsp").forward(request,response);
return;
}
//接收用户名和密码
String username = request.getParameter("username") ;
String password = request.getParameter("password") ;
//将密码加密
password = MD5Utils.md5(password);
System.out.println(username+"---"+password);
//调用UserService
UserService userService = new UserServiceImpl() ;
User user = userService.getUseByUserNameAndPwd(username,password) ;
System.out.println(user);
if(user == null){
//提示错误信息
request.setAttribute("msg","用户名或者密码输入错误!") ;
request.getRequestDispatcher("/jsp/login.jsp").forward(request,response);
return;
}
//用户不为null
//判断用户激活状态不是1
if(user.getState() != Constant.USER_ACTIVE) {
request.setAttribute("msg","用户状态未激活,请到邮箱先激活") ;
request.getRequestDispatcher("/jsp/login.jsp").forward(request,response) ;
return;
}
//判断用户是否勾选了自动登录
//获取name="atuoUser"参数
String autoUser = request.getParameter("autoUser");
//复选框的默认值auto_user和autoUser进行比较
if(!"auto_user".equals(autoUser)){
//没有勾选
//创建Cookie
Cookie cookie = new Cookie("autouser","") ;
//设置最大存活时间 0 ---自动删除cookie
cookie.setMaxAge(0) ;
//响应给浏览器
response.addCookie(cookie) ;
}else{
//勾选了
//存储Cookie
//定义一个cookie的内容-就是"用户名=密码",
String content = user.getUsername() +"="+user.getPassword() ;
//使用jdk工具: 编码器- URLEncoder--->public static String encode(String s, String enc)
//import java.net.URLEncoder;
//参数1:字符串内容
//参数2:字符集
content = URLEncoder.encode(content, "utf-8");
Cookie cookie = new Cookie("autouser",content) ;
//设置最大存活时间
cookie.setMaxAge(60*60*24*30) ;
//响应给浏览器
response.addCookie(cookie) ;
}
//将用户实体存储在HttpSession中
session.setAttribute("user",user) ;
//重定向到/jsp/index.jsp,前台主页
response.sendRedirect(request.getContextPath()+"/jsp/index.jsp") ;
}
步骤3:前台用户自动登录,过滤器实现自动登录
自动登录的过滤器
@WebFilter(value = "/jsp/login.jsp",dispatcherTypes = DispatcherType.REQUEST) //默认直接访问这个地址进行过滤
public class AutoLoginFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("AutoLoginFilter初始化了");
}
//销毁
public void destroy() {
}
/**
* 过滤任务
* @param req 请求对象
* @param resp 响应对象
* @param chain 过滤链
* @throws ServletException
* @throws IOException
*/
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1)req,resp---强转为HttpServletRequest/HttpServletResponse
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//2)获取所有的cookie(当浏览器再次请求服务器的时候 "/jsp/login.jsp")
Cookie[] cookies = request.getCookies();
//声明cookie的内容
String content = null ;
if(cookies!=null){
//浏览器中有cookie
//遍历cookie
for(Cookie cookie :cookies){
//获取到每一个Cookie ,判断如果当前cookie的名称是"autouser",获取它的内容
if("autouser".equals(cookie.getName())){
content = cookie.getValue() ;
}
}
//判断如果当前获取到的content不为null,
if(content!=null){
//加密的内容----Jdk解码器URLDecoder--->public static String decode(String s, String enc)
//参数1:字符串内容
//参数2:字符集格式
content = URLDecoder.decode(content, "utf-8");
//"用户名=密码"---通过"="拆分内容
String[] strs = content.split("=");
System.out.println("过滤器中获取到用户信息--->"+strs[0]+"---"+strs[1]);
//strs[0] :用户名
//strs[1] :密码
//调用UserService业务接口
UserService userService = new UserServiceImpl() ;
User user = userService.getUseByUserNameAndPwd(strs[0], strs[1]) ;
//获取HttpSession
HttpSession session = request.getSession();
if(user!=null){
session.setAttribute("user" ,user) ;
//重定向到首页
response.sendRedirect(request.getContextPath()+"/jsp/index.jsp");
}else{
//user没有找到
//放行
chain.doFilter(request,response);
}
}else{
//放行
chain.doFilter(request,response) ;
}
}else{
//没有cookie
//放行
chain.doFilter(request,response);
}
}
}
jdk工具: 编码器- URLEncoder
编码 public static String encode(String s, String encoing)
String content = user.getUsername() +"="+user.getPassword() ;
content = URLEncoder.encode(content, "utf-8");
Cookie cookie = new Cookie("autouser",content) ;
解码
加密的内容----Jdk解码器URLDecoder--->public static String decode(String s, String enc)
//参数1:字符串内容
//参数2:字符集格式
content = URLDecoder.decode(content, "utf-8");
项目优化,抽取一个公共的BaseServlet
ublic class BaseServlet extends HttpServlet {
@Override
protected void service ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
Class clazz= this . getClass ( ) ;
try {
Object object = clazz. newInstance ( ) ;
String methodName = request. getParameter ( "methodName" ) ;
if ( methodName== null ) {
methodName= "index" ;
}
Method method = clazz. getDeclaredMethod ( methodName,
HttpServletRequest . class , HttpServletResponse . class ) ;
method. setAccessible ( true ) ;
method. invoke ( object, request, response) ;
} catch ( InstantiationException e) {
e. printStackTrace ( ) ;
} catch ( IllegalAccessException e) {
e. printStackTrace ( ) ;
} catch ( NoSuchMethodException e) {
e. printStackTrace ( ) ;
} catch ( InvocationTargetException e) {
e. printStackTrace ( ) ;
}
}
}
多个servlet写成一个方法
表单提交, 必须为post方法
get方式提交会覆盖xxx. . /user? methodName= add
xxx. . /user? username= xx& pasword= XX. . .
1.
修改页面访问的地址
< form method= "post" action= "${pageContext.request.contextPath}/user?methodName=register" id= "formID" >
2. 子类继承Baseservlet
访问后端地址时http: / / localhost: 8080 / Maven_2302_war / user? methodName= add
创建当前类实例, 在baseservlet中完成, 访问谁, 就创建哪个子类对象
3. 注解方式配置地址值@WebServlet ( "/user" )
4. 将该模块的业务改为方法
* 前台用户模块
* /
@WebServlet ( "/user" )
public class UserServlet extends BaseServlet {
public void getAllUsers ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
String cuPage = request. getParameter ( "currentPage" ) ;
String pSize = request. getParameter ( "pageSize" ) ;
int currentPage = Integer . parseInt ( cuPage) ;
int pageSize = Integer . parseInt ( pSize) ;
AdminService adminService = new AdminServiceImpl ( ) ;
PageBean < User > pageBean = adminService. getUserByPage ( currentPage, pageSize) ;
request. setAttribute ( "pb" , pageBean) ;
request. getRequestDispatcher ( "/user/uesr_list.jsp" ) . forward ( request, response) ;
}
jsp动作标签
< % -- jsp动作标签
jsp : forward 请求转发
-- % >
< % -- < jsp: forward page= "/jsp/index.jsp" > < / jsp: forward> -- % >
上下文路径后无内容, 直接访问后端地址/ index主页
< jsp: forward page= "/index" > < / jsp: forward
电商前台首页导航条获取分类信息
1.1ajax异步获取导航条信息
< ul id= "ulDaoHang" class = "nav navbar-nav" >
$ ( function ( ) {
var $ul = $ ( "#ulDaoHang" ) ;
$. ajax ( {
url : "${pageContext.request.contextPath}/category?methodName=getAllCategory" ,
type : "get" ,
success : function ( data ) {
var data = JSON . parse ( data) ;
$ ( data) . each ( function ( ) {
$ul. append ( "" + this . cname+ "(current) " ) ;
} )
} ,
dateType : "json"
} )
} )
1.2异步获取导航条信息servlet
@WebServlet ( "/category" )
public class CategoryServlet extends BaseServlet {
public void getAllCategory ( HttpServletRequest request, HttpServletResponse response) throws IOException {
CategoryService categoryService = new CategoryServiceImpl ( ) ;
List < Category > allCaregorys = categoryService. getAllCaregorys ( ) ;
String jsonStr = JsonUtils . list2json ( allCaregorys) ;
response. getWriter ( ) . write ( jsonStr) ;
}
}
1.3异步获取导航条信息servlce
public class CategoryServiceImpl implements CategoryService {
@Override
public List < Category > getAllCaregorys ( ) {
try {
CategoryDao categoryDao = new CategoryDaoImpl ( ) ;
List < Category > categories = categoryDao. selectAllCategorys ( ) ;
if ( categories!= null || categories. size ( ) > 0 ) {
return categories ;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return null ;
}
}
1.3异步获取导航条信息dao
public class CategoryDaoImpl implements CategoryDao {
@Override
public List < Category > selectAllCategorys ( ) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from category" ;
List < Category > categories = qr. query ( sql, new BeanListHandler < > ( Category . class ) ) ;
return categories;
}
}
点击导航条分类信息,展示商品分页信息
1.1点击链接跳转
var data = JSON. parse ( data) ;
$( data) . each ( function ( ) {
$ul. append ( "" + this . cname+ "(current) " ) ;
} )
} ,
dateType: "json"
1.2根据分类,展示商品分页信息servlet
public void getProductByPage ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
String curPage = request. getParameter ( "curPage" ) ;
String pSize = request. getParameter ( "pSize" ) ;
String cid = request. getParameter ( "cid" ) ;
int currentPage = Integer . parseInt ( curPage) ;
int pageSize = Integer . parseInt ( pSize) ;
ProductService productService = new ProductServiceImpl ( ) ;
PageBean < Product > pb = productService. getProductsByPage ( currentPage, pageSize, cid) ;
System . out. println ( pb) ;
request. setAttribute ( "pb" , pb) ;
request. getRequestDispatcher ( "/jsp/product_list.jsp" ) . forward ( request, response) ;
}
1.3根据分类,展示商品分页信息service
@Override
public PageBean < Product > getProductsByPage ( int currentPage, int pageSize, String cid) {
List < Product > list = null ;
try {
ProductDao productDao = new ProductDaoImpl ( ) ;
int start = ( currentPage- 1 ) * pageSize ;
list = productDao. selectProductByPage ( start, pageSize, cid) ;
int totalCount = productDao. totalCount ( cid) ;
if ( list!= null || list. size ( ) > 0 ) {
return new PageBean < > ( currentPage, pageSize, totalCount, list) ;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return null ;
}
1.4根据分类,展示商品分页信息dao
@Override
public List < Product > selectProductByPage ( int start, int pageSize, String cid) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from product where cid = ? limit ?,?" ;
List < Product > productList = qr. query ( sql, new BeanListHandler < > ( Product . class ) , cid, start, pageSize) ;
return productList;
}
@Override
public int totalCount ( String cid) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select count(pid) from product where cid = ?" ;
Object obj = qr. query ( sql, new ScalarHandler < > ( ) , cid) ;
int totalCount = Integer . parseInt ( String . valueOf ( obj) ) ;
return totalCount;
}
1.5展示数据jsp
< c: forEach items= "${pb.pageList}" var = "p" >
< div class = "col-md-2" >
< a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" >
< img src= "${pageContext.request.contextPath}/${p.pimage}" width= "170" height= "170" style= "display: inline-block;" >
< / a>
< p> < a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" style= 'color:green' > ${ fn : substring ( p. pname, 0 , 6 ) } ... < / a> < / p>
< p> < font color= "#FF0000" > 商城价:& yen; ${ p. shop_price} < / font> < / p>
< / div>
< / c: forEach>
< ! -- 分页 -- >
< div style= "width:380px;margin:0 auto;margin-top:50px;" >
< ul class = "pagination" style= "text-align:center; margin-top:10px;" >
< % --
判断如果是第一页
-- % >
< c: if test= "${pb.currentPage==1}" >
< li class = "disabled" >
< a href= "javascript:void(0)" aria- label= "Previous" > < span aria- hidden= "true" > & laquo; < / span> < / a>
< / li>
< / c: if >
< % -- 判断如果不是第一页-- % >
< c: if test= "${pb.currentPage!=1}" >
< li>
< a href= "${pageContext.request.contextPath}/product?methodName=getProductByPage&curPage=${pb.currentPage-1}&pSize=12&cid=${param.cid}" aria- label= "Previous" > < span aria- hidden= "true" > & laquo; < / span> < / a>
< / li>
< / c: if >
< % -- 遍历页码-- % >
< c: forEach begin= "1" end= "${pb.totalPage}" var = "n" >
< % -- 是否是当前页-- % >
< c: if test= "${pb.currentPage==n}" >
< % -- 是当前页-- % >
< li class = "active" >
< a href= "#" > ${ n} < / a>
< / li>
< / c: if >
< % -- 不是当前页-- % >
< c: if test= "${pb.currentPage!=n}" >
< % -- 不是当前页-- % >
< li>
< a href= "${pageContext.request.contextPath}/product?methodName=getProductByPage&curPage=${n}&pSize=12&cid=${param.cid}" > ${ n} < / a>
< / li>
< / c: if >
< / c: forEach>
电商前台首页获取最新商品和热门商品
获取数据
@WebServlet ( "/index" )
public class IndexServlet extends BaseServlet {
public void index ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
ProductService productService = new ProductServiceImpl ( ) ;
List < Product > newProducts = productService. getNewProducts ( ) ;
List < Product > hostProducts = productService. getHostProducts ( ) ;
if ( newProducts!= null && hostProducts!= null ) {
request. setAttribute ( "newProducts" , newProducts) ;
request. setAttribute ( "hostProducts" , hostProducts) ;
}
request. getRequestDispatcher ( "/jsp/index.jsp" ) . forward ( request, response) ;
}
service层
@Override
public List < Product > getNewProducts ( ) {
List < Product > productList = null ;
try {
ProductDao productDao = new ProductDaoImpl ( ) ;
productList = productDao. selectNewProducts ( ) ;
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return productList;
}
@Override
public List < Product > getHostProducts ( ) {
List < Product > productsList = null ;
try {
ProductDao productDao = new ProductDaoImpl ( ) ;
productsList = productDao. selectNewProducts ( ) ;
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return productsList;
}
dao层
@Override
public List < Product > selectNewProducts ( ) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from product order by pdate asc limit 10;" ;
List < Product > list = qr. query ( sql, new BeanListHandler < > ( Product . class ) ) ;
return list;
}
@Override
public List < Product > selectHostProducts ( ) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from product where is_host=1 limit 10;" ;
List < Product > list = qr. query ( sql, new BeanListHandler < > ( Product . class ) ) ;
return list;
}
展示数据
< % -- 遍历数据-- % >
< c: forEach items= "${newProducts}" var = "p" >
< div class = "col-md-2" style= "text-align:center;height:200px;padding:10px 0px;" >
< a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" >
< % -- 商品图片-- % >
< img src= "${pageContext.request.contextPath}/${p.pimage}" width= "130" height= "130" style= "display: inline-block;" >
< / a>
< % -- 商品名称-- % >
< p> < a href= "{pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" style= 'color:#666' > ${ fn : substring ( p. pname, 0 , 6 ) } ... < / a> < / p>
< % -- 商城价格-- % >
< p> < font color= "#E4393C" style= "font-size:16px" > & yen; ${ p. shop_price} < / font> < / p>
< / div>
< / c: forEach>
jstl函数库:fn
< % @ taglib prefix= "fn" uri= "http://java.sun.com/jsp/jstl/functions" % >
${ fn : substring ( < string> , < beginIndex> , < endIndex> ) }
参数1 : 获取指定的字符串名称
参数2 : 指定开始截取的索引位置 从0 开始
参数3 : 最终索引, 包含endIndex- 1 处
< a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" style= 'color:#666' > ${ fn : substring ( p. pname, 0 , 6 ) } ... < / a>
公共导航条抽取
创建header.jsp
其他页面导入,静态包含指令include,导入的jsp页面不会被单独编译和翻译
<%@include file="header.jsp"%>
电商展示商品详情
点击商品名称或图片超链接跳转商品服务器地址
< a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" >
< img src= "${pageContext.request.contextPath}/${p.pimage}" width= "130" height= "130" style= "display: inline-block;" > < / a>
< p> < a href= "${pageContext.request.contextPath}/product?methodName=getProduct&pid=${p.pid}" style= 'color: #666 '> ${ fn: substring ( p. pname, 0 , 6 ) } . . . </ a> < / p>
1.1展示商品详情,servlet层
public void getProduct ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
String pid = request. getParameter ( "pid" ) ;
ProductService productService = new ProductServiceImpl ( ) ;
Product product = productService. getProduct ( pid) ;
if ( product!= null ) {
request. setAttribute ( "product" , product) ;
}
request. getRequestDispatcher ( "/jsp/product_info.jsp" ) . forward ( request, response) ;
}
1.2展示商品详情service层
@Override
public Product getProduct ( String pid) {
try {
ProductDao productDao = new ProductDaoImpl ( ) ;
Product product = productDao. getProduct ( pid) ;
if ( product != null ) {
return product;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
return null ;
}
1.3展示商品详情dao层
@Override
public Product getProduct ( String pid) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from product where pid=?" ;
Product product = qr. query ( sql, new BeanHandler < > ( Product . class ) , pid) ;
return product;
}
1.4展示商品详情jsp
< div> < strong> ${ product. pname} < / strong> < / div>
< div style= "border-bottom: 1px dotted #dddddd;width:350px;margin:10px 0 10px 0;" >
< div> 编号: ${ product. pid} < / div>
< / div>
< div style= "margin:10px 0 10px 0;" > 商城价: < strong style= "color:#ef0101;" > ¥:${ product. shop_price} < / strong> 市场价: < del> ¥${ product. market_price} < / del>
< / div>
购物车
1.1商品详情页表单提交购物车
< form id= "form" action= "${pageContext.request.contextPath}/cart?methodName=addCartItem2Cart" method= "post" >
< % -- 隐藏域-- % >
< input type= "hidden" name= "pid" value= "${product.pid}" / >
< div class = "col-md-6" >
< div> < strong> ${ product. pname} < / strong> < / div>
< div style= "border-bottom: 1px dotted #dddddd;width:350px;margin:10px 0 10px 0;" >
< div> 编号: ${ product. pid} < / div>
< / div>
< div style= "margin:10px 0 10px 0;" > 商城价: < strong style= "color:#ef0101;" > ¥:${ product. shop_price} < / strong> 市场价: < del> ¥${ product. market_price} < / del>
< / div>
< div style= "margin:10px 0 10px 0;" > 促销: < a target= "_blank" title= "限时抢购 (2014-07-30 ~ 2015-01-01)" style= "background-color: #f07373;" > 限时抢购< / a> < / div>
< div style= "padding:10px;border:1px solid #e7dbb1;width:330px;margin:15px 0 10px 0;;background-color: #fffee6;" >
< div style= "margin:5px 0 10px 0;" > 白色< / div>
< div style= "border-bottom: 1px solid #faeac7;margin-top:20px;padding-left: 10px;" > 购买数量:
< input id= "quantity" readonly name= "count" value= "1" maxlength= "4" size= "10" type= "text" > < / div>
< div style= "margin:20px 0 10px 0;;text-align: center;" >
< a href= "javascript:void(0)" >
< input onclick= "addCartItem()" style= "background-color: #ffd002" value= "加入购物车" type= "button" >
< / a> < / div>
< / div>
< script>
function addCartItem ( ) {
var $form = $ ( "#form" ) ;
$form. submit ( ) ;
}
< / script>
1.2购物车实体
public class Cart {
private Map < String , CartItem > map = new LinkedHashMap < > ( ) ;
private double totalMoney = 0.0 ;
public void addCartItem2Cart ( CartItem cartItem) {
String pid = cartItem. getProduct ( ) . getPid ( ) ;
if ( map. containsKey ( pid) ) {
CartItem oldCartItem = map. get ( pid) ;
oldCartItem. setCount ( oldCartItem. getCount ( ) + 1 ) ;
} else {
map. put ( pid, cartItem) ;
}
totalMoney+= cartItem. getSubTotal ( ) ;
}
public void removeCartItemFormCart ( String pid) {
CartItem cartItem = map. remove ( pid) ;
totalMoney -= cartItem. getSubTotal ( ) ;
}
public void clearCart ( ) {
map. clear ( ) ;
totalMoney = 0.0 ;
}
public Collection < CartItem > getCartItems ( ) {
return map. values ( ) ;
}
public Cart ( ) {
}
public Map < String , CartItem > getMap ( ) {
return map;
}
public void setMap ( Map < String , CartItem > map) {
this . map = map;
}
public double getTotalMoney ( ) {
return totalMoney;
}
public void setTotalMoney ( double totalMoney) {
this . totalMoney = totalMoney;
}
}
1.3购物车项实体
public class CartItem {
private Product product;
private int count;
private double subTotal;
public CartItem ( ) {
}
public Product getProduct ( ) {
return product;
}
public void setProduct ( Product product) {
this . product = product;
}
public int getCount ( ) {
return count;
}
public void setCount ( int count) {
this . count = count;
}
public double getSubTotal ( ) {
return product. getShop_price ( ) * count;
}
}
1.4购物车servlet
package com. ddl. controller ;
import com. ddl. pojo. Cart ;
import com. ddl. pojo. CartItem ;
import com. ddl. pojo. Product ;
import com. ddl. pojo. User ;
import com. ddl. service. ProductService ;
import com. ddl. service. impl. ProductServiceImpl ;
import javax. servlet. annotation. WebServlet ;
import javax. servlet. http. HttpServletRequest ;
import javax. servlet. http. HttpServletResponse ;
import javax. servlet. http. HttpSession ;
import java. io. IOException ;
@WebServlet ( "/cart" )
public class CartServlet extends BaseServlet {
public Cart getCartFromHttpSession ( HttpServletRequest request) {
HttpSession session = request. getSession ( ) ;
Cart cart = ( Cart ) session. getAttribute ( "cart" ) ;
if ( cart== null ) {
cart= new Cart ( ) ;
session. setAttribute ( "cart" , cart) ;
}
return cart;
}
public void addCartItem2Cart ( HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request. getSession ( ) ;
User user = ( User ) session. getAttribute ( "user" ) ;
if ( user== null ) {
response. sendRedirect ( request. getContextPath ( ) + "/jsp/login.jsp" ) ;
return ;
}
String pid = request. getParameter ( "pid" ) ;
String getCount = request. getParameter ( "count" ) ;
ProductService productService = new ProductServiceImpl ( ) ;
Product product = productService. getProduct ( pid) ;
CartItem cartItem = new CartItem ( ) ;
int count = Integer . parseInt ( getCount) ;
cartItem. setCount ( count) ;
cartItem. setProduct ( product) ;
Cart cart = getCartFromHttpSession ( request) ;
cart. addCartItem2Cart ( cartItem) ;
response. sendRedirect ( request. getContextPath ( ) + "/jsp/cart.jsp" ) ;
}
public void ClearCart ( HttpServletRequest request, HttpServletResponse response) throws IOException {
Cart cart = getCartFromHttpSession ( request) ;
cart. clearCart ( ) ;
request. getSession ( ) . removeAttribute ( "cart" ) ;
response. sendRedirect ( request. getContextPath ( ) + "/jsp/cart.jsp" ) ;
}
public void delCartItem ( HttpServletRequest request, HttpServletResponse response) throws IOException {
String pid = request. getParameter ( "pid" ) ;
Cart cart = getCartFromHttpSession ( request) ;
cart. removeCartItemFormCart ( pid) ;
response. sendRedirect ( request. getContextPath ( ) + "/jsp/cart.jsp" ) ;
}
}
1.5购物车jsp展示数据
< c: if test= "${ empty cart}" >
< h2> 亲, 空空如也~ ~ ~ , 请< a href= "${pageContext.request.contextPath}/index" > 购物< / a>> < / h2>
< / c: if >
< c: if test= "${not empty cart}" >
< div style= "margin:0 auto; margin-top:10px;width:950px;" >
< strong style= "font-size:16px;margin:5px 0;" > 购物车信息< / strong>
< table class = "table table-bordered" >
< tbody>
< tr class = "warning" >
< th> 图片< / th>
< th> 商品< / th>
< th> 价格< / th>
< th> 数量< / th>
< th> 小计< / th>
< th> 操作< / th>
< / tr>
< % -- 遍历每一个购物车项
el表达式 可以操作javaBean
快速ognl对象图导航语言操作bean属性
${ 域中的属性名. 实体的bean属性} -- - 域对象. getAttribute ( "属性名" ) . getXXX ( )
访问getXXX ( ) 方法
-- % >
< c: forEach items= "${cart.cartItems}" var = "bean" > < % -- bean代表每一个购物车项-- % >
< tr class = "active" >
< td width= "60" width= "40%" >
< input type= "hidden" name= "id" value= "22" >
< img src= "${pageContext.request.contextPath}/${bean.product.pimage}" width= "70" height= "60" >
< / td>
< td width= "30%" >
< a target= "_blank" > ${ bean. product. pname} < / a>
< / td>
< td width= "20%" >
¥${ bean. product. shop_price}
< / td>
< td width= "10%" >
< input type= "text" value= "${bean.count}" maxlength= "4" size= "10" >
< / td>
< td width= "15%" >
< span class = "subtotal" > ¥${ bean. subTotal} < / span>
< / td>
< td>
< a href= "javascript:void(0)" onclick= "delCartItem('${bean.product.pid}')" class = "delete" > 删除< / a>
< / td>
< / tr>
< / c: forEach>
< / tbody>
< / table>
< / div>
< div style= "margin-right:130px;" >
< div style= "text-align:right;" >
< em style= "color:#ff6600;" >
登录后确认是否享有优惠& nbsp; & nbsp;
< / em> 赠送积分: < em style= "color:#ff6600;" > ${ cart. totalMoney} < / em> & nbsp; 商品金额: < strong style= "color:#ff6600;" > ¥${ cart. totalMoney} 元< / strong>
< / div>
< / c: if >
< / div>
< div style= "text-align:right;margin-top:10px;margin-bottom:10px;" >
< a href= "${pageContext.request.contextPath}/cart?methodName=ClearCart" id= "clear" class = "clear" > 清空购物车< / a>
< a href= "${pageContext.request.contextPath}/order?methodName=submitOrder" >
< input type= "submit" width= "100" value= "提交订单" name= "submit" border= "0" style= "background-color:#E66B1A" / >
< / a>
< / div>
< / div>
< / div>
购物车中提交订单—产生订单数据–展示订单
1.1 点击提交订单超链接–发送请求
${pageContext.request.contextPath}/order?methodName=generateOrder"
展示order_info的数据
<%--遍历每一个订单项
Order实体里面---List getList()
el表达式 操作list属性
--%>
${bean.product.pname}
¥${bean.product.shop_price}
${bean.count}
¥${bean.subtotal}
商品金额: ¥${order.total}
1.2 OrderServlet 订单后端访问地址
@WebServlet ( "/order" )
public class OrderServlet extends BaseServlet {
public void generateOrder ( HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException {
User user = ( User ) request. getSession ( ) . getAttribute ( "user" ) ;
if ( user== null ) {
response. sendRedirect ( request. getContextPath ( ) + "/jsp/login.jsp" ) ;
return ;
}
Order order = new Order ( ) ;
order. setOid ( UUIDUtils . getId ( ) ) ;
order. setOrdertime ( new Date ( ) ) ;
Cart cart = ( Cart ) request. getSession ( ) . getAttribute ( "cart" ) ;
order. setTotal ( cart. getTotalMoney ( ) ) ;
OrderItem orderItem = null ;
for ( CartItem cartItem: cart. getCartItems ( ) ) {
orderItem = new OrderItem ( ) ;
orderItem. setItemid ( UUIDUtils . getId ( ) ) ;
orderItem. setCount ( cartItem. getCount ( ) ) ;
orderItem. setSubtotal ( cartItem. getSubTotal ( ) ) ;
orderItem. setProduct ( cartItem. getProduct ( ) ) ;
orderItem. setOrder ( order) ;
List < OrderItem > list = order. getList ( ) ;
list. add ( orderItem) ;
}
order. setUser ( user) ;
OrderService orderService = new OrderServiceImpl ( ) ;
orderService. addOrder ( order) ;
request. getSession ( ) . removeAttribute ( "cart" ) ;
request. setAttribute ( "order" , order) ;
request. getRequestDispatcher ( "/jsp/order_info.jsp" ) . forward ( request, response) ;
}
}
1.3 OrderService订单业务接口实现
public class OrderServiceImpl implements OrderService {
@Override
public void addOrder ( Order order) {
try {
OrderDao orderDao = new OrderDaoImpl ( ) ;
DruidJdbcUtils . setAutoCommit ( ) ;
orderDao. insertOrder ( order) ;
for ( OrderItem orderItem: order. getList ( ) ) {
orderDao. insertOrderItem ( orderItem) ;
}
DruidJdbcUtils . commitAndClose ( ) ;
} catch ( SQLException throwables) {
try {
DruidJdbcUtils . rollbackAndClose ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
throwables. printStackTrace ( ) ;
}
}
}
1.4 Orderdao:订单数据访问接口层实现
public class OrderDaoImpl implements OrderDao {
@Override
public void insertOrder ( Order order) throws SQLException {
QueryRunner qr = new QueryRunner ( ) ;
String sql = "insert into orders values(?,?,?,?,?,?,?,?)" ;
int count = qr. update (
DruidJdbcUtils . getConnection ( ) ,
sql, order. getOid ( ) ,
order. getOrdertime ( ) ,
order. getTotal ( ) ,
order. getState ( ) ,
order. getAddress ( ) ,
order. getUser ( ) . getName ( ) ,
order. getTelephone ( ) ,
order. getUser ( ) . getUid ( ) ) ;
}
@Override
public void insertOrderItem ( OrderItem orderItem) throws SQLException {
QueryRunner qr = new QueryRunner ( ) ;
String sql = "insert into orderitem values(?,?,?,?,?)" ;
int count = qr. update (
DruidJdbcUtils . getConnection ( ) ,
sql,
orderItem. getItemid ( ) ,
orderItem. getCount ( ) ,
orderItem. getSubtotal ( ) ,
orderItem. getProduct ( ) . getPid ( ) ,
orderItem. getOrder ( ) . getOid ( ) ) ;
}
}
1.5订单实体
public class Order {
private String oid;
private Date ordertime;
private double total;
private int state;
private String address ;
private String name;
private String telephone;
private User user ;
private List < OrderItem > list = new LinkedList < > ( ) ;
public Order ( ) {
}
public String getOid ( ) {
return oid;
}
public List < OrderItem > getList ( ) {
return list;
}
public void setList ( List < OrderItem > list) {
this . list = list;
}
public void setOid ( String oid) {
this . oid = oid;
}
public Date getOrdertime ( ) {
return ordertime;
}
public void setOrdertime ( Date ordertime) {
this . ordertime = ordertime;
}
public double getTotal ( ) {
return total;
}
public void setTotal ( double total) {
this . total = total;
}
public int getState ( ) {
return state;
}
public void setState ( int state) {
this . state = state;
}
public String getAddress ( ) {
return address;
}
public void setAddress ( String address) {
this . address = address;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public String getTelephone ( ) {
return telephone;
}
public void setTelephone ( String telephone) {
this . telephone = telephone;
}
public User getUser ( ) {
return user;
}
public void setUser ( User user) {
this . user = user;
}
}
1.6订单项实体
public class OrderItem {
private String itemid;
private int count;
private double subtotal;
private Product product;
private Order order;
public OrderItem ( ) {
}
public String getItemid ( ) {
return itemid;
}
public void setItemid ( String itemid) {
this . itemid = itemid;
}
public int getCount ( ) {
return count;
}
public void setCount ( int count) {
this . count = count;
}
public double getSubtotal ( ) {
return subtotal;
}
public void setSubtotal ( double subtotal) {
this . subtotal = subtotal;
}
public Product getProduct ( ) {
return product;
}
public void setProduct ( Product product) {
this . product = product;
}
public Order getOrder ( ) {
return order;
}
public void setOrder ( Order order) {
this . order = order;
}
}
查询用户订单列表-分页展示
1.1点击链接跳转后端地址
< a href= "${pageContext.request.contextPath}/order?methodName=getOrderListByPage¤tPage=1&pageSize=3" > 订单列表< / a>
1.2查询用户订单列表servlet
public void getOrderListByPage ( HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException {
User user = ( User ) request. getSession ( ) . getAttribute ( "user" ) ;
if ( user == null ) {
response. sendRedirect ( request. getContextPath ( ) + "/jsp/login.jsp" ) ;
return ;
}
String cPage = request. getParameter ( "currentPage" ) ;
String pPage = request. getParameter ( "pageSize" ) ;
int currentPage = Integer . parseInt ( cPage) ;
int pageSize = Integer . parseInt ( pPage) ;
OrderService orderService = new OrderServiceImpl ( ) ;
PageBean < Order > pageBean = orderService. getOrderByPage ( currentPage, pageSize, user) ;
request. setAttribute ( "pb" , pageBean) ;
for ( Order order : pageBean. getPageList ( ) ) {
System . out. println ( order. getOid ( ) ) ;
}
request. getRequestDispatcher ( "/jsp/order_list.jsp" ) . forward ( request, response) ;
}
1.3查询用户订单列表servlce层
@Override
public PageBean < Order > getOrderByPage ( int currentPage, int pageSize, User user) {
try {
OrderDao orderDao = new OrderDaoImpl ( ) ;
List < Order > list = orderDao. getOrderByPage ( currentPage, pageSize, user) ;
int count = orderDao. getTotalCount ( user) ;
System . out. println ( list) ;
PageBean < Order > pageBean= new PageBean < > ( currentPage, pageSize, list, count) ;
System . out. println ( pageBean) ;
if ( list!= null || list. size ( ) > 0 ) {
return pageBean;
}
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
} catch ( InvocationTargetException e) {
e. printStackTrace ( ) ;
} catch ( IllegalAccessException e) {
e. printStackTrace ( ) ;
}
return null ;
}
1.4查询用户订单列表dao层
@Override
public List < Order > getOrderByPage ( int currentPage, int pageSize, User user) throws SQLException , InvocationTargetException , IllegalAccessException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select * from orders where uid =? order by ordertime desc limit ?,?" ;
List < Order > orderList = qr. query ( sql, new BeanListHandler < > ( Order . class ) ,
user. getUid ( ) ,
( currentPage - 1 ) * pageSize,
pageSize) ;
sql = "select * from orderitem oi,product po where oi.pid=po.pid and oid=?" ;
for ( Order order : orderList) {
List < Map < String , Object > > mapOfOrderItem = qr. query ( sql, new MapListHandler ( ) , order. getOid ( ) ) ;
for ( Map < String , Object > map : mapOfOrderItem) {
OrderItem orderItem = new OrderItem ( ) ;
Product product = new Product ( ) ;
BeanUtils . populate ( product, map) ;
BeanUtils . populate ( orderItem, map) ;
orderItem. setProduct ( product) ;
List < OrderItem > list = order. getList ( ) ;
list. add ( orderItem) ;
}
}
return orderList;
}
@Override
public int getTotalCount ( User user) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "select count(oid) from orders where uid=?" ;
Object obj = qr. query ( sql, new ScalarHandler < > ( ) , user. getUid ( ) ) ;
int count = Integer . parseInt ( String . valueOf ( obj) ) ;
return count;
}
支付宝支付
1.1配置
public class AlipayConfig {
public static String return_url = "http://yuqx65.natappfree.cc/test08_war_exploded/aliPayReturnUrlServlet" ;
public static String notify_url = "http://yuqx65.natappfree.cc/test08_war_exploded/notify" ;
public static String app_id = "2021000122685092" ;
public static String alipay_public_key = "xxx" ;
public static String merchant_private_key= "xxx" ;
public static String sign_type = "RSA2" ;
public static String charset = "utf-8" ;
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do" ;
}
< ! -- 加入支付宝的SDK-- >
< dependency>
< groupId> com. alipay. sdk< / groupId>
< artifactId> alipay- sdk- java< / artifactId>
< version> 4.12 .4 . ALL< / version>
< / dependency>
@WebServlet ( "/aliPayReturnUrlServlet" )
public class AliPayReturnUrlServlet extends HttpServlet {
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
PrintWriter out = response. getWriter ( ) ;
Map < String , String > params = new HashMap < String , String > ( ) ;
Map < String , String [ ] > requestParams = request. getParameterMap ( ) ;
for ( Iterator < String > iter = requestParams. keySet ( ) . iterator ( ) ; iter. hasNext ( ) ; ) {
String name = ( String ) iter. next ( ) ;
String [ ] values = ( String [ ] ) requestParams. get ( name) ;
String valueStr = "" ;
for ( int i = 0 ; i < values. length; i++ ) {
valueStr = ( i == values. length - 1 ) ? valueStr + values[ i]
: valueStr + values[ i] + "," ;
}
params. put ( name, valueStr) ;
}
try {
boolean signVerified = AlipaySignature . rsaCheckV1 (
params,
AlipayConfig . alipay_public_key,
AlipayConfig . charset,
AlipayConfig . sign_type) ;
if ( signVerified) {
String out_trade_no = new String ( request. getParameter ( "out_trade_no" ) . getBytes ( "ISO-8859-1" ) , "UTF-8" ) ;
String trade_no = new String ( request. getParameter ( "trade_no" ) . getBytes ( "ISO-8859-1" ) , "UTF-8" ) ;
String total_amount = new String ( request. getParameter ( "total_amount" ) . getBytes ( "ISO-8859-1" ) , "UTF-8" ) ;
OrderService orderService = new OrderServiceImpl ( ) ;
Order order = orderService. getOrderByOid ( out_trade_no) ;
order. setState ( 1 ) ;
orderService. updateOrderState ( order) ;
request. setAttribute ( "order" , order) ;
request. getRequestDispatcher ( "/jsp/success.jsp" ) . forward ( request, response) ;
} else {
out. println ( "验签失败" ) ;
}
} catch ( AlipayApiException e) {
e. printStackTrace ( ) ;
}
}
protected void doPost ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
doGet ( request, response) ;
}
1.2jsp
< form id= "payForm" action= "${pageContext.request.contextPath}/order?methodName=pay" method= "post" >
< % -- 隐藏域-- % >
< input type= "hidden" name= "oid" value= "${order.oid}" / >
< tr class = "active" >
< td width= "60" width= "40%" >
< input type= "hidden" name= "id" value= "22" >
< img src= "${pageContext.request.contextPath}/${bean.product.pimage}" width= "70" height= "60" >
< / td>
< td width= "30%" >
< a target= "_blank" > ${ bean. product. pname} < / a>
< / td>
< td width= "20%" >
¥${ bean. product. shop_price}
< / td>
< td width= "10%" >
${ bean. count}
< / td>
< td width= "15%" >
< span class = "subtotal" > ¥${ bean. subtotal} < / span>
< / td>
< / tr>
< / form>
< script>
function btn_pay ( ) {
var form = $ ( "#payForm" ) ;
form. submit ( ) ;
}
< / script>
1.3订单支付servlet
public void pay ( HttpServletRequest request, HttpServletResponse response) {
String oid = request. getParameter ( "oid" ) ;
OrderService orderService = new OrderServiceImpl ( ) ;
Order order = orderService. getOrderByOid ( oid) ;
try {
AlipayClient alipayClient = new DefaultAlipayClient (
AlipayConfig . gatewayUrl,
AlipayConfig . app_id,
AlipayConfig . merchant_private_key,
"json" ,
AlipayConfig . charset,
AlipayConfig . alipay_public_key,
AlipayConfig . sign_type) ;
AlipayTradePagePayRequest alipayRequest =
new AlipayTradePagePayRequest ( ) ;
alipayRequest. setReturnUrl ( AlipayConfig . return_url) ;
alipayRequest. setNotifyUrl ( AlipayConfig . notify_url) ;
alipayRequest. setBizContent ( "{\"out_trade_no\":\"" + order. getOid ( ) + "\","
+ "\"total_amount\":\"" + order. getTotal ( ) + "\","
+ "\"subject\":\"" + "数码产品" + "\","
+ "\"body\":\"" + "手机和电脑相关" + "\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}" ) ;
String result = alipayClient. pageExecute ( alipayRequest) . getBody ( ) ;
response. getWriter ( ) . write ( result) ;
response. getWriter ( ) . flush ( ) ;
response. getWriter ( ) . close ( ) ;
} catch ( AlipayApiException | IOException e) {
e. printStackTrace ( ) ;
}
}
1.4订单支付service dao
@Override
public void updateOrderState ( Order order) {
try {
OrderDao orderDao = new OrderDaoImpl ( ) ;
orderDao. updateOrderFroState ( order) ;
} catch ( SQLException throwables) {
throwables. printStackTrace ( ) ;
}
}
@Override
public void updateOrderFroState ( Order order) throws SQLException {
QueryRunner qr = new QueryRunner ( DruidJdbcUtils . getDataSource ( ) ) ;
String sql = "update orders set state =? where oid =?" ;
qr. update ( sql, order. getState ( ) , order. getOid ( ) ) ;
}
文件上传
1.前端-文件上传的表单
上传图片:
enctype="multipart/form-data" 支持多文件上传
必须设置为post提交
上传组件:input type="file"
2. 后端访问接口地址中—>Servlet提供的@MultipartConfig
@MulipartConfig -- -> 会前端文件上传组件 input type= "file" 获取到文件流对象
@WebServlet ( "/upload" )
@MultipartConfig
public class UploadFileServlet extends HttpServlet {
@Override
protected void doGet ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
Part part = request. getPart ( "file" ) ;
String fileName = part. getSubmittedFileName ( ) ;
String realPath = request. getServletContext ( ) . getRealPath ( "/myImage" ) ;
part. write ( realPath+ "/" + fileName) ;
}
@Override
protected void doPost ( HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException {
doGet ( request, response) ;
}
}
Git 分布式版本控制系统
命令行方式使用:
初始化本地库
git init //在指定的文件中出生本地库 ---->文件夹中产生 .git文件
将指定一些文件添加在暂存区中
git add 文件名称.后缀名
git commit 文件 -m '注释:标名当前代码更新的内容是什么'
将本地库的代码推送远程仓库上----新建仓库完成
设置个人签名信息---用户名/邮箱 (设置一次即可,以后不用设置了)---c://users/用户名目录//.gitconfig文件---记录签名信息
需要给当前https远程仓库请求地址,设置别名
git remote add origin(别名名称) http地址
git push origin 主分支名称(默认master) --->第一次使用:弹出一个窗口,设置gitee码云的账户和密码
git log 查看日志
git工作流
git命令
1.git init 初始化本地库
2.git status 查看当前本地库文件的状态:
3.git add 文件名称: 将指定文件添加到暂存区
4.git commit 文件名称 -m '注释' 将暂存区中的文件提交到本地库中
5.git log 查看日志
6.git remote add origin 仓库地址 给远程仓库设置别名origin
7.git push 别名 分支名称(默认master 主分支) :将本地库的代码---推送到远程仓库上
8.git clone 仓库地址: 就是下载远程仓库 的代码
你可能感兴趣的:(java,前端,mysql)
Long类型前后端数据不一致
igotyback
前端
响应给前端的数据浏览器控制台中response中看到的Long类型的数据是正常的到前端数据不一致前后端数据类型不匹配是一个常见问题,尤其是当后端使用Java的Long类型(64位)与前端JavaScript的Number类型(最大安全整数为2^53-1,即16位)进行数据交互时,很容易出现精度丢失的问题。这是因为JavaScript中的Number类型无法安全地表示超过16位的整数。为了解决这个问
LocalDateTime 转 String
igotyback
java 开发语言
importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassMain{publicstaticvoidmain(String[]args){//获取当前时间LocalDateTimenow=LocalDateTime.now();//定义日期格式化器DateTimeFormatterformat
mysql禁用远程登录
igotyback
mysql
去mysql库中的user表里,将host都改成localhost之后刷新权限FLUSHPRIVILEGES;
Linux下QT开发的动态库界面弹出操作(SDL2)
13jjyao
QT类 qt 开发语言 sdl2 linux
需求:操作系统为linux,开发框架为qt,做成需带界面的qt动态库,调用方为java等非qt程序难点:调用方为java等非qt程序,也就是说调用方肯定不带QApplication::exec(),缺少了这个,QTimer等事件和QT创建的窗口将不能弹出(包括opencv也是不能弹出);这与qt调用本身qt库是有本质的区别的思路:1.调用方缺QApplication::exec(),那么我们在接口
DIV+CSS+JavaScript技术制作网页(旅游主题网页设计与制作)云南大理
STU学生网页设计
网页设计 期末网页作业 html静态网页 html5期末大作业 网页设计 web大作业
️精彩专栏推荐作者主页:【进入主页—获取更多源码】web前端期末大作业:【HTML5网页期末作业(1000套)】程序员有趣的告白方式:【HTML七夕情人节表白网页制作(110套)】文章目录二、网站介绍三、网站效果▶️1.视频演示2.图片演示四、网站代码HTML结构代码CSS样式代码五、更多源码二、网站介绍网站布局方面:计划采用目前主流的、能兼容各大主流浏览器、显示效果稳定的浮动网页布局结构。网站程
【华为OD机试真题2023B卷 JAVA&JS】We Are A Team
若博豆
java 算法 华为 javascript
华为OD2023(B卷)机试题库全覆盖,刷题指南点这里WeAreATeam时间限制:1秒|内存限制:32768K|语言限制:不限题目描述:总共有n个人在机房,每个人有一个标号(1<=标号<=n),他们分成了多个团队,需要你根据收到的m条消息判定指定的两个人是否在一个团队中,具体的:1、消息构成为:abc,整数a、b分别代
【加密社】Solidity 中的事件机制及其应用
加密社
闲侃 区块链 智能合约 区块链
加密社引言在Solidity合约开发过程中,事件(Events)是一种非常重要的机制。它们不仅能够让开发者记录智能合约的重要状态变更,还能够让外部系统(如前端应用)监听这些状态的变化。本文将详细介绍Solidity中的事件机制以及如何利用不同的手段来触发、监听和获取这些事件。事件存储的地方当我们在Solidity合约中使用emit关键字触发事件时,该事件会被记录在区块链的交易收据中。具体而言,事件
关于城市旅游的HTML网页设计——(旅游风景云南 5页)HTML+CSS+JavaScript
二挡起步
web前端期末大作业 javascript html css 旅游 风景
⛵源码获取文末联系✈Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业|游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作|HTML期末大学生网页设计作业,Web大学生网页HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScrip
HTML网页设计制作大作业(div+css) 云南我的家乡旅游景点 带文字滚动
二挡起步
web前端期末大作业 web设计网页规划与设计 html css javascript dreamweaver 前端
Web前端开发技术描述网页设计题材,DIV+CSS布局制作,HTML+CSS网页设计期末课程大作业游景点介绍|旅游风景区|家乡介绍|等网站的设计与制作HTML期末大学生网页设计作业HTML:结构CSS:样式在操作方面上运用了html5和css3,采用了div+css结构、表单、超链接、浮动、绝对定位、相对定位、字体样式、引用视频等基础知识JavaScript:做与用户的交互行为文章目录前端学习路线
MYSQL面试系列-04
king01299
面试 mysql 面试
MYSQL面试系列-0417.关于redolog和binlog的刷盘机制、redolog、undolog作用、GTID是做什么的?innodb_flush_log_at_trx_commit及sync_binlog参数意义双117.1innodb_flush_log_at_trx_commit该变量定义了InnoDB在每次事务提交时,如何处理未刷入(flush)的重做日志信息(redolog)。它
node.js学习
小猿L
node.js node.js 学习 vim
node.js学习实操及笔记温故node.js,node.js学习实操过程及笔记~node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记为什么学node.js可以让别人访问我们编写的网页为后续的框架学习打下基础,三大框架vuereactangular离不开node.jsnode.js是什么官网:node.js是一个开源的、跨平台的运行JavaScript的运行
Java 重写(Override)与重载(Overload)
叨唧唧的
Java重写(Override)与重载(Overload)重写(Override)重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如:父类的一个方法申明了一个检查异常IOExceptio
简单了解 JVM
记得开心一点啊
jvm
目录♫什么是JVM♫JVM的运行流程♫JVM运行时数据区♪虚拟机栈♪本地方法栈♪堆♪程序计数器♪方法区/元数据区♫类加载的过程♫双亲委派模型♫垃圾回收机制♫什么是JVMJVM是JavaVirtualMachine的简称,意为Java虚拟机。虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统(如:JVM、VMwave、VirtualBox)。JVM和其他两个虚拟机
关于Mysql 中 Row size too large (> 8126) 错误的解决和理解
秋刀prince
mysql mysql 数据库
提示:啰嗦一嘴,数据库的任何操作和验证前,一定要记得先备份!!!不会有错;文章目录问题发现一、问题导致的可能原因1、页大小2、行格式2.1compact格式2.2Redundant格式2.3Dynamic格式2.4Compressed格式3、BLOB和TEXT列二、解决办法1、修改页大小(不推荐)2、修改行格式3、修改数据类型为BLOB和TEXT列4、其他优化方式(可以参考使用)4.1合理设置数据
1分钟解决 -bash: mvn: command not found,在Centos 7中安装Maven
Energet!c
开发语言
1分钟解决-bash:mvn:commandnotfound,在Centos7中安装Maven检查Java环境1下载Maven2解压Maven3配置环境变量4验证安装5常见问题与注意事项6总结检查Java环境Maven依赖Java环境,请确保系统已经安装了Java并配置了环境变量。可以通过以下命令检查:java-version如果未安装,请先安装Java。1下载Maven从官网下载:前往Apach
Java企业面试题3
马龙强_
java
1.break和continue的作用(智*图)break:用于完全退出一个循环(如for,while)或一个switch语句。当在循环体内遇到break语句时,程序会立即跳出当前循环体,继续执行循环之后的代码。continue:用于跳过当前循环体中剩余的部分,并开始下一次循环。如果是在for循环中使用continue,则会直接进行条件判断以决定是否执行下一轮循环。2.if分支语句和switch分
JVM、JRE和 JDK:理解Java开发的三大核心组件
Y雨何时停T
Java java
Java是一门跨平台的编程语言,它的成功离不开背后强大的运行环境与开发工具的支持。在Java的生态中,JVM(Java虚拟机)、JRE(Java运行时环境)和JDK(Java开发工具包)是三个至关重要的核心组件。本文将探讨JVM、JDK和JRE的区别,帮助你更好地理解Java的运行机制。1.JVM:Java虚拟机(JavaVirtualMachine)什么是JVM?JVM,即Java虚拟机,是Ja
Java面试题精选:消息队列(二)
芒果不是芒
Java面试题精选 java kafka
一、Kafka的特性1.消息持久化:消息存储在磁盘,所以消息不会丢失2.高吞吐量:可以轻松实现单机百万级别的并发3.扩展性:扩展性强,还是动态扩展4.多客户端支持:支持多种语言(Java、C、C++、GO、)5.KafkaStreams(一个天生的流处理):在双十一或者销售大屏就会用到这种流处理。使用KafkaStreams可以快速的把销售额统计出来6.安全机制:Kafka进行生产或者消费的时候会
白骑士的Java教学基础篇 2.5 控制流语句
白骑士所长
Java 教学 java 开发语言
欢迎继续学习Java编程的基础篇!在前面的章节中,我们了解了Java的变量、数据类型和运算符。接下来,我们将探讨Java中的控制流语句。控制流语句用于控制程序的执行顺序,使我们能够根据特定条件执行不同的代码块,或重复执行某段代码。这是编写复杂程序的基础。通过学习这一节内容,你将掌握如何使用条件语句和循环语句来编写更加灵活和高效的代码。条件语句条件语句用于根据条件的真假来执行不同的代码块。if语句‘
python语法——三目运算符
HappyRocking
python python 三目运算符
在java中,有三目运算符,如:intc=(a>b)?a:b表示c取两者中的较大值。但是在python,不能直接这样使用,估计是因为冒号在python有分行的关键作用。那么在python中,如何实现类似功能呢?可以使用ifelse语句,也是一行可以完成,格式为:aifbelsec表示如果b为True,则表达式等于a,否则等于c。如:c=(aif(a>b)elseb)同样是完成了取最大值的功能。
ArrayList 源码解析
程序猿进阶
Java基础 ArrayList List java 面试 性能优化 架构设计 idea
ArrayList是Java集合框架中的一个动态数组实现,提供了可变大小的数组功能。它继承自AbstractList并实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量capacity,表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添
Java爬虫框架(一)--架构设计
狼图腾-狼之传说
java 框架 java 任务 html解析器 存储 电子商务
一、架构图那里搜网络爬虫框架主要针对电子商务网站进行数据爬取,分析,存储,索引。爬虫:爬虫负责爬取,解析,处理电子商务网站的网页的内容数据库:存储商品信息索引:商品的全文搜索索引Task队列:需要爬取的网页列表Visited表:已经爬取过的网页列表爬虫监控平台:web平台可以启动,停止爬虫,管理爬虫,task队列,visited表。二、爬虫1.流程1)Scheduler启动爬虫器,TaskMast
Java:爬虫框架
dingcho
Java java 爬虫
一、ApacheNutch2【参考地址】Nutch是一个开源Java实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。Nutch致力于让每个人能很容易,同时花费很少就可以配置世界一流的Web搜索引擎.为了完成这一宏伟的目标,Nutch必须能够做到:每个月取几十亿网页为这些网页维护一个索引对索引文件进行每秒上千次的搜索提供高质量的搜索结果简单来说Nutch支持分
MongoDB知识概括
GeorgeLin98
持久层 mongodb
MongoDB知识概括MongoDB相关概念单机部署基本常用命令索引-IndexSpirngDataMongoDB集成副本集分片集群安全认证MongoDB相关概念业务应用场景:传统的关系型数据库(如MySQL),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。解释:“三高”需求:①Highperformance-对数据库高并发读写的需求。②HugeStorage-对海量数
python怎么将png转为tif_png转tif
weixin_39977276
发国外的文章要求图片是tif,cmyk色彩空间的。大小尺寸还有要求。比如网上大神多,找到了一段代码,感谢!https://www.jianshu.com/p/ec2af4311f56https://github.com/KevinZc007/image2Tifimportjava.awt.image.BufferedImage;importjava.io.File;importjava.io.Fi
springboot+vue项目实战一-创建SpringBoot简单项目
苹果酱0567
面试题汇总与解析 spring boot 后端 java 中间件 开发语言
这段时间抽空给女朋友搭建一个个人博客,想着记录一下建站的过程,就当做笔记吧。虽然复制zjblog只要一个小时就可以搞定一个网站,或者用cms系统,三四个小时就可以做出一个前后台都有的网站,而且想做成啥样也都行。但是就是要从新做,自己做的意义不一样,更何况,俺就是专门干这个的,嘿嘿嘿要做一个网站,而且从零开始,首先呢就是技术选型了,经过一番思量决定选择-SpringBoot做后端,前端使用Vue做一
JavaScript 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
跳房子的前端
前端面试 javascript 开发语言 ecmascript
在JavaScript中,深拷贝(DeepCopy)和浅拷贝(ShallowCopy)是用于复制对象或数组的两种不同方法。了解它们的区别和应用场景对于避免潜在的bugs和高效地处理数据非常重要。以下是对深拷贝和浅拷贝的详细解释,包括它们的概念、用途、优缺点以及实现方式。1.浅拷贝(ShallowCopy)概念定义:浅拷贝是指创建一个新的对象或数组,其中包含了原对象或数组的基本数据类型的值和对引用数
JAVA·一个简单的登录窗口
MortalTom
java 开发语言 学习
文章目录概要整体架构流程技术名词解释技术细节资源概要JavaSwing是Java基础类库的一部分,主要用于开发图形用户界面(GUI)程序整体架构流程新建项目,导入sql.jar包(链接放在了文末),编译项目并运行技术名词解释一、特点丰富的组件提供了多种可视化组件,如按钮(JButton)、文本框(JTextField)、标签(JLabel)、下拉列表(JComboBox)等,可以满足不同的界面设计
入门MySQL——查询语法练习
K_un
前言:前面几篇文章为大家介绍了DML以及DDL语句的使用方法,本篇文章将主要讲述常用的查询语法。其实MySQL官网给出了多个示例数据库供大家实用查询,下面我们以最常用的员工示例数据库为准,详细介绍各自常用的查询语法。1.员工示例数据库导入官方文档员工示例数据库介绍及下载链接:https://dev.mysql.com/doc/employee/en/employees-installation.h
WebMagic:强大的Java爬虫框架解析与实战
Aaron_945
Java java 爬虫 开发语言
文章目录引言官网链接WebMagic原理概述基础使用1.添加依赖2.编写PageProcessor高级使用1.自定义Pipeline2.分布式抓取优点结论引言在大数据时代,网络爬虫作为数据收集的重要工具,扮演着不可或缺的角色。Java作为一门广泛使用的编程语言,在爬虫开发领域也有其独特的优势。WebMagic是一个开源的Java爬虫框架,它提供了简单灵活的API,支持多线程、分布式抓取,以及丰富的
枚举的构造函数中抛出异常会怎样
bylijinnan
java enum 单例
首先从使用enum实现单例说起。
为什么要用enum来实现单例?
这篇文章(
http://javarevisited.blogspot.sg/2012/07/why-enum-singleton-are-better-in-java.html)阐述了三个理由:
1.enum单例简单、容易,只需几行代码:
public enum Singleton {
INSTANCE;
CMake 教程
aigo
C++
转自:http://xiang.lf.blog.163.com/blog/static/127733322201481114456136/
CMake是一个跨平台的程序构建工具,比如起自己编写Makefile方便很多。
介绍:http://baike.baidu.com/view/1126160.htm
本文件不介绍CMake的基本语法,下面是篇不错的入门教程:
http:
cvc-complex-type.2.3: Element 'beans' cannot have character
Cb123456
spring Webgis
cvc-complex-type.2.3: Element 'beans' cannot have character
Line 33 in XML document from ServletContext resource [/WEB-INF/backend-servlet.xml] is i
jquery实例:随页面滚动条滚动而自动加载内容
120153216
jquery
<script language="javascript">
$(function (){
var i = 4;$(window).bind("scroll", function (event){
//滚动条到网页头部的 高度,兼容ie,ff,chrome
var top = document.documentElement.s
将数据库中的数据转换成dbs文件
何必如此
sql dbs
旗正规则引擎通过数据库配置器(DataBuilder)来管理数据库,无论是Oracle,还是其他主流的数据都支持,操作方式是一样的。旗正规则引擎的数据库配置器是用于编辑数据库结构信息以及管理数据库表数据,并且可以执行SQL 语句,主要功能如下。
1)数据库生成表结构信息:
主要生成数据库配置文件(.conf文
在IBATIS中配置SQL语句的IN方式
357029540
ibatis
在使用IBATIS进行SQL语句配置查询时,我们一定会遇到通过IN查询的地方,在使用IN查询时我们可以有两种方式进行配置参数:String和List。具体使用方式如下:
1.String:定义一个String的参数userIds,把这个参数传入IBATIS的sql配置文件,sql语句就可以这样写:
<select id="getForms" param
Spring3 MVC 笔记(一)
7454103
spring mvc bean REST JSF
自从 MVC 这个概念提出来之后 struts1.X struts2.X jsf 。。。。。
这个view 层的技术一个接一个! 都用过!不敢说哪个绝对的强悍!
要看业务,和整体的设计!
最近公司要求开发个新系统!
Timer与Spring Quartz 定时执行程序
darkranger
spring bean 工作 quartz
有时候需要定时触发某一项任务。其实在jdk1.3,java sdk就通过java.util.Timer提供相应的功能。一个简单的例子说明如何使用,很简单: 1、第一步,我们需要建立一项任务,我们的任务需要继承java.util.TimerTask package com.test; import java.text.SimpleDateFormat; import java.util.Date;
大端小端转换,le32_to_cpu 和cpu_to_le32
aijuans
C语言相关
大端小端转换,le32_to_cpu 和cpu_to_le32 字节序
http://oss.org.cn/kernel-book/ldd3/ch11s04.html
小心不要假设字节序. PC 存储多字节值是低字节为先(小端为先, 因此是小端), 一些高级的平台以另一种方式(大端)
Nginx负载均衡配置实例详解
avords
[导读] 负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦。负载均衡先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解 负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦。
负载均衡
先来简单了解一下什么是负载均衡
乱说的
houxinyou
框架 敏捷开发 软件测试
从很久以前,大家就研究框架,开发方法,软件工程,好多!反正我是搞不明白!
这两天看好多人研究敏捷模型,瀑布模型!也没太搞明白.
不过感觉和程序开发语言差不多,
瀑布就是顺序,敏捷就是循环.
瀑布就是需求、分析、设计、编码、测试一步一步走下来。而敏捷就是按摸块或者说迭代做个循环,第个循环中也一样是需求、分析、设计、编码、测试一步一步走下来。
也可以把软件开发理
欣赏的价值——一个小故事
bijian1013
有效辅导 欣赏 欣赏的价值
第一次参加家长会,幼儿园的老师说:"您的儿子有多动症,在板凳上连三分钟都坐不了,你最好带他去医院看一看。" 回家的路上,儿子问她老师都说了些什么,她鼻子一酸,差点流下泪来。因为全班30位小朋友,惟有他表现最差;惟有对他,老师表现出不屑,然而她还在告诉她的儿子:"老师表扬你了,说宝宝原来在板凳上坐不了一分钟,现在能坐三分钟。其他妈妈都非常羡慕妈妈,因为全班只有宝宝
包冲突问题的解决方法
bingyingao
eclipse maven exclusions 包冲突
包冲突是开发过程中很常见的问题:
其表现有:
1.明明在eclipse中能够索引到某个类,运行时却报出找不到类。
2.明明在eclipse中能够索引到某个类的方法,运行时却报出找不到方法。
3.类及方法都有,以正确编译成了.class文件,在本机跑的好好的,发到测试或者正式环境就
抛如下异常:
java.lang.NoClassDefFoundError: Could not in
【Spark七十五】Spark Streaming整合Flume-NG三之接入log4j
bit1129
Stream
先来一段废话:
实际工作中,业务系统的日志基本上是使用Log4j写入到日志文件中的,问题的关键之处在于业务日志的格式混乱,这给对日志文件中的日志进行统计分析带来了极大的困难,或者说,基本上无法进行分析,每个人写日志的习惯不同,导致日志行的格式五花八门,最后只能通过grep来查找特定的关键词缩小范围,但是在集群环境下,每个机器去grep一遍,分析一遍,这个效率如何可想之二,大好光阴都浪费在这上面了
sudoku solver in Haskell
bookjovi
sudoku haskell
这几天没太多的事做,想着用函数式语言来写点实用的程序,像fib和prime之类的就不想提了(就一行代码的事),写什么程序呢?在网上闲逛时发现sudoku游戏,sudoku十几年前就知道了,学生生涯时也想过用C/Java来实现个智能求解,但到最后往往没写成,主要是用C/Java写的话会很麻烦。
现在写程序,本人总是有一种思维惯性,总是想把程序写的更紧凑,更精致,代码行数最少,所以现
java apache ftpClient
bro_feng
java
最近使用apache的ftpclient插件实现ftp下载,遇见几个问题,做如下总结。
1. 上传阻塞,一连串的上传,其中一个就阻塞了,或是用storeFile上传时返回false。查了点资料,说是FTP有主动模式和被动模式。将传出模式修改为被动模式ftp.enterLocalPassiveMode();然后就好了。
看了网上相关介绍,对主动模式和被动模式区别还是比较的模糊,不太了解被动模
读《研磨设计模式》-代码笔记-工厂方法模式
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
package design.pattern;
/*
* 工厂方法模式:使一个类的实例化延迟到子类
* 某次,我在工作不知不觉中就用到了工厂方法模式(称为模板方法模式更恰当。2012-10-29):
* 有很多不同的产品,它
面试记录语
chenyu19891124
招聘
或许真的在一个平台上成长成什么样,都必须靠自己去努力。有了好的平台让自己展示,就该好好努力。今天是自己单独一次去面试别人,感觉有点小紧张,说话有点打结。在面试完后写面试情况表,下笔真的好难,尤其是要对面试人的情况说明真的好难。
今天面试的是自己同事的同事,现在的这个同事要离职了,介绍了我现在这位同事以前的同事来面试。今天这位求职者面试的是配置管理,期初看了简历觉得应该很适合做配置管理,但是今天面
Fire Workflow 1.0正式版终于发布了
comsci
工作 workflow Google
Fire Workflow 是国内另外一款开源工作流,作者是著名的非也同志,哈哈....
官方网站是 http://www.fireflow.org
经过大家努力,Fire Workflow 1.0正式版终于发布了
正式版主要变化:
1、增加IWorkItem.jumpToEx(...)方法,取消了当前环节和目标环节必须在同一条执行线的限制,使得自由流更加自由
2、增加IT
Python向脚本传参
daizj
python 脚本 传参
如果想对python脚本传参数,python中对应的argc, argv(c语言的命令行参数)是什么呢?
需要模块:sys
参数个数:len(sys.argv)
脚本名: sys.argv[0]
参数1: sys.argv[1]
参数2: sys.argv[
管理用户分组的命令gpasswd
dongwei_6688
passwd
NAME: gpasswd - administer the /etc/group file
SYNOPSIS:
gpasswd group
gpasswd -a user group
gpasswd -d user group
gpasswd -R group
gpasswd -r group
gpasswd [-A user,...] [-M user,...] g
郝斌老师数据结构课程笔记
dcj3sjt126com
数据结构与算法
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
yii2 cgridview加上选择框进行操作
dcj3sjt126com
GridView
页面代码
<?=Html::beginForm(['controller/bulk'],'post');?>
<?=Html::dropDownList('action','',[''=>'Mark selected as: ','c'=>'Confirmed','nc'=>'No Confirmed'],['class'=>'dropdown',])
linux mysql
fypop
linux
enquiry mysql version in centos linux
yum list installed | grep mysql
yum -y remove mysql-libs.x86_64
enquiry mysql version in yum repositoryyum list | grep mysql oryum -y list mysql*
install mysq
Scramble String
hcx2013
String
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
跟我学Shiro目录贴
jinnianshilongnian
跟我学shiro
历经三个月左右时间,《跟我学Shiro》系列教程已经完结,暂时没有需要补充的内容,因此生成PDF版供大家下载。最近项目比较紧,没有时间解答一些疑问,暂时无法回复一些问题,很抱歉,不过可以加群(334194438/348194195)一起讨论问题。
----广告-----------------------------------------------------
nginx日志切割并使用flume-ng收集日志
liyonghui160com
nginx的日志文件没有rotate功能。如果你不处理,日志文件将变得越来越大,还好我们可以写一个nginx日志切割脚本来自动切割日志文件。第一步就是重命名日志文件,不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,linux是靠文件描述符而不是文件名定位文件。第二步向nginx主
Oracle死锁解决方法
pda158
oracle
select p.spid,c.object_name,b.session_id,b.oracle_username,b.os_user_name from v$process p,v$session a, v$locked_object b,all_objects c where p.addr=a.paddr and a.process=b.process and c.object_id=b.
java之List排序
shiguanghui
list排序
在Java Collection Framework中定义的List实现有Vector,ArrayList和LinkedList。这些集合提供了对对象组的索引访问。他们提供了元素的添加与删除支持。然而,它们并没有内置的元素排序支持。 你能够使用java.util.Collections类中的sort()方法对List元素进行排序。你既可以给方法传递
servlet单例多线程
utopialxw
单例 多线程 servlet
转自http://www.cnblogs.com/yjhrem/articles/3160864.html
和 http://blog.chinaunix.net/uid-7374279-id-3687149.html
Servlet 单例多线程
Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的