EasyMall项目
1.项目介绍
a.商城网站:
功能:注册、登录、注册、基础用户名、30天自动登录、全站乱码过滤
2.EasyMall环境搭建
window系统、服务器–tomcat、MyEclipse、mysql
开发环境:jdk1.6
开发内容:开发一个www.easymall.com网站,并且将其配置成一个虚拟主机。在其中添加EasyMall web应用,将其配置为缺省web应用,且配置缺省主页
d.创建虚拟主机www.easymall.com网站
i.在server.xml中添加一个Host标签,内容如下
<Host name="www.easymall.com" appBase="D:/www.easymall.com">
</Host>
ii.修改server.xml中的标签:
<Engine name="Catalina" defaultHost="www.easymall.com">
iii.配置hosts文件,添加内容如下
127.0.0.1 www.easymall.com
e.创建EasyMall项目
发布:
f.准备页面
导入三部分:头部、身体、尾部
g.将头部身体和尾部组合
一个网站的头部和尾部可能需要频繁使用,如果在每一个页面中单独写这些内容,十分不便,而且,将来维护修改的时候,工作量很大。所以将他们抽取成两个单独的页面,在需要的页面中将他们引入
在index.jsp中书写如下内容
<!-- 引入头部 -->
<%-- <%request.getRequestDispatcher("/_head.jsp").include(request, response); %> --%>
<%@include file="/_head.jsp" %>
<!-- 引入尾部 -->
<%-- <%request.getRequestDispatcher("/_foot.jsp").include(request, response); %> --%>
<%@include file="/_foot.jsp" %>
Regist注册实现
1.注册实现
a.创建easymall数据库和表数据
create database easymall;
use easymall;
create table user(
id int primary key auto_increment,
username varchar(100),
password varchar(100),
nickname varchar(100),
email varchar(100)
);
insert into user values(null,'admin','123','炒鸡管理员','admin@tedu.cn');
insert into user values(null,'张飞','123','管理员','admin@tedu.cn');
b.在EasyMall中导入mysql驱动jar包,以及c3p0jar包
c.在src目录下添加c3p0.properties配置文件(以及创建连接的工具包)
d.校验内容
e.用户信息回显
用户的某些信息已经确认,在提交之后,如果页面返回错误提示信息,应该将部分内容回显,便于用户重新需改
i.修改regist.jsp页面
<td class="tds">用户名:</td>
<td><!-- 回显用户名 -->
<input type="text" name="username"
value="<%=request.getParameter("username")==null?"":request.getParameter("username")%>"/>
<span></span>
</td>
添加前台页面的校验
1.添加前台页面校验的意义
如果只做出后台的校验,可以防止无效数据入库,但是仍然不能降低服务器的访问能力,所以如果出现不合理的提交数据,应该在台页面就完成拦截。如此才能降低服务器的访问压力。
可以通过js来完成页面拦截的效果
2.在页面中添加js校验
a.修改form表单添加onsubmit属性
<form action="<%=request.getContextPath() %>/RegistServlet" method="post" onsubmit="return formObj.checkForm()">
b.在所有的input框后边添加span框
<td class="tds">用户名:</td>
<td><!-- 回显用户名 -->
<input type="text" name="username"
value="<%=request.getParameter("username")==null?"":request.getParameter("username")%>"/>
<span></span>
</td>
c.添加js代码
d.前台已经做出校验,后台为何仍需校验
前台页面中的校验只是为了减少无效请求做出的拦截效果,是使用js代码来实现的。并不能够真正防止无效数据信息加入数据库,而后台Java代码当前做出的校验,才是在得到数据库之后,真正的校验操作,在判断数据无效后,可以防止无效数据入库。
e.添加离焦事件
//为username输入框添加鼠标离焦事件
$("input[name='username']").blur(function(){
formObj.checkNull("username", "用户名不能为空");
});
添加验证码图片
1.引入VerfiyCode
2.创建ValidateServlet
3.修改regist.jsp页面
在文档就绪事件中添加如下内容
//等待页面加载完成后,为验证码图片绑定单击事件,更新验证码
$("#img").click(function(){
//变化的时间让验证码变化,如果没变化就没有新的请求
var date=new Date();
var time=date.getTime();
$(this).attr("src","<%=request.getContextPath() %>/ValidateServlet?time="+time);
});
a.添加time参数的原因
浏览器认为每次发送的url地址如果相同,则不需要发送新的请求,为了能够通过单击事件加载新的验证码,需要在url后边添加一个变得参数,保证每一次访问的地址都不相同,这样就会发送请求,ValidateServlet创建并返回最新的验证码
ServletConfig
1.代表web.xml中当前servlet初始化配置信息的对象
2.初始化配置信息
a.获取方式:
i.重写init方法,获取ServletConfig对象,虽然可以得到但是它是一个局部变量,如果要在全局操作,则需要将其转换为全局变量。并且如果有多个servlet都需要获取初始化配置信息,要多次重写init方法,非常不便,不推荐使用。
ii.通过当前对象调用getServletConfig()方法,可以直接获取一个ServletConfig对象,并且可以在任意的位置调用
b.获取ServletConfig对象的方法
this.getServletConfig()
c.获取初始化参数的api
this.getServletConfig().getInitParameter()
3.代码实现
package cn.tedu.SConfig;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//获取当前servlet的初始化配置信息
public class SConfigDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
public ServletConfig config=null;
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
//super.init(config);
this.config=config;
String driver=config.getInitParameter("driver");
System.out.println("driver:"+driver);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// response.setContentType("text/html;charset=utf-8");
// PrintWriter out = response.getWriter();
String d=config.getInitParameter("driver");
System.out.println("driver:"+d);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.tedu.SConfig;
//使用方法直接产生一个servletConfig对象
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SConfigDemo2 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletConfig config=this.getServletConfig();
String driver = config.getInitParameter("driver");
String url = config.getInitParameter("url");
//获取web应用全局配置信息
ServletContext sc = this.getServletConfig().getServletContext();
String name = sc.getInitParameter("name");
System.out.println("name:"+name);
System.out.println("driver:"+driver);
System.out.println("url:"+url);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
b.修改web.xml文件
<servlet>
<servlet-name>SConfigDemo1</servlet-name>
<servlet-class>cn.tedu.SConfig.SConfigDemo1</servlet-class>
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>SConfigDemo2</servlet-name>
<servlet-class>cn.tedu.SConfig.SConfigDemo2</servlet-class>
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>localhost:3306/mydb</param-value>
</init-param>
</servlet>
c.可以在每一个servlet身上添加多个初始化配置信息的参数,通过初始化参数名称依次获取
d.注意:每一个servlet只能获取当前servlet身上的初始化配置信息的参数,其它的servlet无法获取
4.功能二:获取ServletContext对象
this.getServletconfig().getServletContext()
5.ServletContext对象
代表当前web应用的对象
a.ServletContext对象
this.getServletconfig().getServletContext()
this.getServletContext()
b.获取全局初始化配置信息
ServletContext.getInitParameter(String name)
c.功能二:作为域对象使用
i.与对象:如果一个对象身上有一个可以被看见的范围,在这个范围利用对象身上的map实现数据的共享,那么这个对象就可以称之为域对象
ii.域对象的api
setAttribute() 设置域属性
getAttribute() 获取域属性
removeAttribute() 删除域属性
getAttributeNames() 获取全部域属性的名称
iii.生命周期
随着web应用的加载,ServletContext对象创建
随着web应用的销毁,ServletContext对象销毁
iv.作用范围
整个web应用
v.主要功能
在整个web应用的范围内共享数据
代码实现
package cn.tedu.SContext;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//获取全局初始化配置信息
public class SContextDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// response.setContentType("text/html;charset=utf-8");
// PrintWriter out = response.getWriter();
/* //获取ServletContext对象
ServletContext sc = this.getServletConfig().getServletContext();
ServletContext sc1 = this.getServletContext();
//获取全局配置信息
String name = sc.getInitParameter("name");
System.out.println("name:"+name);
String name = sc1.getInitParameter("name");
System.out.println("name>>"+name);
*/
//读取域属性
ServletContext sc=this.getServletContext();
String name=(String) sc.getAttribute("name");
System.out.println("name:>>"+name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.tedu.SContext;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//作为域对象使用---在web应用范围内共享数据
public class SContextDemo2 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();*/
//获取代表web应用的域对象
ServletContext sc=this.getServletContext();
//向域中设置域属性
sc.setAttribute("name", "曹阳");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
web.xml配置
<!-- 当前web应用的全局配置信息 -->
<context-param>
<param-name>name</param-name>
<param-value>value</param-value>
</context-param>
3.获取资源路径
a.相对路径
conf/conf.properties
直接书写要获取的资源路径的名称,再通过File读取,发现读取的路径结果是tomcat启动的目录路径,这个路径是错的,所以在读取文件的时候,不能够直接书写某一个文件的相对路径
b.绝对路径
/conf.properties
使用绝对路径获取资源路径的名称,再通过File读取,读取结果为盘符加上文件名称,从磁盘的根目录寻找对应路径的文件,这种文件读取路径也是错的,所以再读取文件时,不能直接书写绝对路径
c.全路径
书写盘符到文件的全路径名称,的确可以获取到指定路径的文件,但是如果路径稍作修改,获取存放文件的路径发生改变,则所有用到全路径的位置全需要修改,十分不便,所以尽管可以得到正确的路径,但是不推荐使用。
d.ServletContext获取路径
可以获取到从盘符到web应用名称的全路径,在getRealPath()中添加上web应用内文件的相对路径,即可获取到当前文件的全路径名称。这种获取方式获取到的路径是正确的,并且也是动态获取的(如果路径修改,此处获取的路径也会修改)所以推荐使用
e.通过类加载器获取文件路径
使用类的字节码,获取类加载器,再获取src目录,最后读取目录中的某一文件,这个读取方式可以获取到盘符到当前文件的全路径,并且是全部动态获取,乐意便捷的得到文件的路径,所以推荐使用这中方式来获取文件的路径名称。
代码:
package cn.tedu.SContext;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//资源路径问题
public class SContextDemo3 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();*/
//相对路径
//String path="conf.properties";
//绝对路径
//String path="/conf.properties";
//全路径
//String path="D:\\software\\apache-tomcat-7.0.62\\webapps\\day11\\WEB-INF\\classes\\conf.properties";
//类加载器读取src目录下的文件
// String path=SContextDemo3.class.getClassLoader().getResource("conf.properties").getPath();
//ServletContext读取web应用的路径
ServletContext sc=this.getServletContext();
//获取从盘符到当前的web应用目录的路径
String path=sc.getRealPath("\\WEB-INF\\classes\\conf.properties");
File file=new File(path);
//获取所读取文件的全路径名称
String aPath=file.getAbsolutePath();
System.out.println("aPath>>"+aPath);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
二、Ajax
1.ajax概述
Ajax asynchronous js and xml:异步的js和xml
ajax是一个异步请求操作,可以在页面内大部分不变的情况下完成局部刷新的操作。
Ajax是通过js来实现。其中异步请求发送的数据是xml格式的数据
随着技术的发展,ajax发送和接受的数据格式有以下几种:
xml
json 字符串
text 纯文本
ajax —>aj
2.Ajax的运行原理
同步交互:
请求发出,浏览器必须得到响应结果之后,才可以继续发送下一次的请求,再等待过程中,浏览器不能进行任何的操作‘
异步交互:
请求发出,浏览器可以继续进行更多的操作,不必等待响应的结果,仍然可以发送更多的请求,服务器会根据每一个请求一次性做出响应,浏览器在这个过程中可以任意的操作
实践场景:
异步:
搜索框、注册用户名是否存在校验
同步:百度搜索框后边的按钮
异步请求:
优点:用户体验较好,减少服务器访问的压力
缺点:
增加服务器访问的压力(不正常的访问,或者是特殊的访问)
e.javascript实现ajax(四步)
第一步:获取XMLHttpRequest对象
var xmlHttp=ajaxFunction();
function ajaxFunction(){
var xmlHttp;
try{
//现代浏览器(IE7、火狐、谷歌、Safari和Opera)都有内建的XMLHttpRequest对象
xmlHttp=new XMLHttpRequest();
}catch(e){
try{
//IE6
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
//IE5以及更早的版本
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
alert("...");
throw e;
}
}
}
return xmlHttp;
}
第二步:打开与服务器的连接
xmlHttp.open(method,url,async);
method:请求方式get或post
url:要访问服务器中资源的路径
async:是否为异步传输,true表示异步传输,一般为异步
第三部:发送请求
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//通知服务器发送的数据是请求参数
xmlHttp.send("xxx");//注意:如果不给参数可能会造成部分浏览器无法发送请求
参数:
GET 可以是null,因为GET提交参数会拼接在url后面
POST 传入的就是请求参数"username=张飞&psw=123"
第四步:注册监听
在XMLHttpRequest对象的一个事件上注册监听器
onreadystatechange
一共有5个状态
0状态 表示刚创建XMLHttpRequest对象,还未调用open方法
1状态 表示刚调用open方法但是没调用send方法、
2状态 调用完send方法,请求已经开始
3状态 服务器已经开始响应,但是不代表响应结束
4状态 服务器响应结束(通常我们只关心这个状态)
获取xmlHttp对象的状态
var state=xmlHttp.readyState;
获取响应的状态码
var status=xmlHttp.status;
获取服务器响应的内容
var data=xmlHttp.responseText;//得到服务器响应的文本格式的数据
xmlHttp.onreadystatechange=function(){
//当服务器处理完请求之后
if(xmlHttp.status==4){
if(xmlHttp.status==200){
//获取响应数据
var result=xmlHttp.responseText;
result=xmlHttp.responseXML
}
}
}
f.jquery实现Ajax
jquery实现Ajax
i.load方法
$(selector).load(url,data,callback)'
selector:选择器
url:发送请求的url地址
data:可选,向服务器发送的数据key/value数据 如:{"username":"张飞","psw":"123"}
callback:可选,load方法完成后执行的函数
ii.$.get方法
$.get(url,[data],[callback]);
iii.$.ajax方法
$.ajax(url,[data],[async],[callback]);
EasyMall项目–ajax校验用户名
1.Ajax校验用户名
当鼠标离开input[name=‘usrname’]输入框时,会执行js中的离焦事件,可以在离焦事件中添加Ajax代码。离焦事件出发,代码自上而下执行,Ajax也会执行
2.修改regist.jsp页面
$("input[name='username']").blur(function(){
formObj.checkNull("username", "用户名不能为空");
//获取输入框中的值
var username=$(this).val();
//ajax校验用户名是否存在 虚拟路径 动态资源
if(username!=""){
$("#username_msg").load("<%=request.getContextPath()%>/AjaxCheckUsernameServlet",{"username":username});
}
});
3.创建AjaxCheckUsernameServlet.java
package com.easymall.servlet;
//ajax请求,查询数据库中用户名是否已存在
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.easymall.utils.JDBCUtils;
public class AjaxCheckUsernameServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//乱码处理
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//获取请求参数
String username=request.getParameter("username");
//访问数据库用户名是否已存在
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
conn=JDBCUtils.getConnection();
ps=conn.prepareStatement("select * from user where username=?");
ps.setString(1, username);
rs=ps.executeQuery();
if(rs.next()){//用户名已存在,提示更改
response.getWriter().write("<font color='red'>用户名已存在</font>");
}else{//用户名不存在可以使用
response.getWriter().write("用户名可以使用");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCUtils.close(conn, ps, rs);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
修改页面中的资源路径
a.页面中的静态资源都是相对路径,在使用请求转发访问这些资源的时候,可能会导致路径加载错误,为了避免这种错误可以在每一个静态资源的路径之前拼接web应用的虚拟路径。这样在静态资源加载的时候就不会出现路径问题
b.不出现路径问题的原因
在静态资源路径之前拼接上web应用的虚拟路径之后,在某先资源发生跳转时,替换的资源路径就会从web应用的路径开始替换,只要保证这一点,从web应用路径级别设置的静态资源路径就不会出错
c.修改的方式
各个静态资源路径的前面添加如下内容:
<%=request.getContextPath() %>