Servlet简介
1.
Servlet简介
1.
添加商品
要进行商品的添加处理,需要
1. 查询到所有的商品分类
2. 查询到商品标注信息
建立IGoodsDAO 接口
·继承IDAO
建立GoodsDAOImpl
·继承AbstractDAO
·实现IGoodsDAO接口
搭建项目开发环境
1. IDAO公共父接口
2. 项目工具类
- DatabaseConnection
- ServiceProxy
- DAOFactory
- ServiceFactory
- AbstractDAO
3. WEB目录下建立upload/goods文件夹,用于保存上传的图片
4. 将"nophoto.jpg"图片拷贝到upload/goods目录下
5. 建立一个pages/plugins目录,保存所有的组件程序
- 分页的两个组件
- 操作完成后的一个包含页面
6. 建立css js目录,将样式拷贝进来
7. 将Tomcat的Servlet-api.jar, jsp-api.jar等驱动程序配置到lib文件夹下
8. 建立一个基础的模板页面
- pages/plugins目录中建立 include_javascript.jsp (将要导入的页面配置到此)
9. 建立相应的VO类
·Item类
·Goods类
·Tag类
数据表
1. 商品分类表(item)
- 商品分类ID: iid number
- 商品分类名称:title varchara(50)
2. 商品标签表(tag)
- 标签编号:tid number
- 标签名称:title varchar(50)
3. 商品信息表(goods)
- 商品编号(序列生成)gid number
- 商品分类ID
- 商品名称:title varchar(50)
- 价格:price number
- 商品图片:photo varchar(100)
- 约束
constraint pk_gid primary key(gid)
constraint fk_iid foreign key(iid) references item(iid)
4. 商品-标记的关系表(goods_tag)
- gid
- tid
constraint fk_gid foreign key(gid) references goods(gid) on delete cascade.
constraint fk_tid foreign key(tid) references tag(tid)
实际开发中对于图片的保存形式有两种
1. 直接在数据表设置一个blob类型的字段,将图片使用二进制数据写入,读取时也通过二进制数据流读取
- 缺点:代码复杂,且不通用
- 优点:数据库备份人员省事,只需要备份一个数据库
2. 在数据表的相关字段上保留的是一个文件的名称,所有的文件都自动保存在指定目录,如果需要,再直接使用<img>标签进行加载
- 缺点:数据库备份人员需要备份数据库和文件内容
- 优点:程序简单
数据库设计
powerdesigner进行数据库设计
-- 删除数据表
DROP TABLE item PURGE ;
DROP TABLE tag PURGE ;
DROP SEQUENCE goods_seq ;
-- 创建数据表
CREATE TABLE item(
iid NUMBER ,
title VARCHAR2(50) ,
CONSTRAINT pk_iid PRIMARY KEY(iid)
) ;
CREATE TABLE tag(
tid NUMBER ,
title VARCHAR2(50) ,
CONSTRAINT pk_tid PRIMARY KEY(tid)
) ;
CREATE SEQUENCE goods_seq ;
CREATE TABLE goods (
gid NUMBER ,
title VARCHAR2(50) ,
price NUMBER ,
photo VARCHAR2(100) ,--保存的是图片的名称
iid NUMBER ,
CONSTRAINT pk_gid10 PRIMARY KEY(gid) ,
CONSTRAINT fk_iid FOREIGN KEY(iid) REFERENCES item(iid)
) ;
CREATE TABLE goods_tag(
gid NUMBER ,
tid NUMBER ,
CONSTRAINT fk_gid11 FOREIGN KEY(gid) REFERENCES goods(gid) ON DELETE CASCADE ,
CONSTRAINT fk_tid11 FOREIGN KEY(tid) REFERENCES tag(tid)
) ;
-- 测试数据
INSERT INTO item(iid,title) VALUES (1,'图书音像') ;
INSERT INTO item(iid,title) VALUES (2,'办公用品') ;
INSERT INTO item(iid,title) VALUES (3,'家居生活') ;
INSERT INTO item(iid,title) VALUES (4,'厨房家电') ;
INSERT INTO item(iid,title) VALUES (5,'电子设备') ;
INSERT INTO tag(tid,title) VALUES (1,'高端') ;
INSERT INTO tag(tid,title) VALUES (2,'奢华') ;
INSERT INTO tag(tid,title) VALUES (3,'性价比高') ;
INSERT INTO tag(tid,title) VALUES (4,'免费') ;
INSERT INTO tag(tid,title) VALUES (5,'耐用') ;
-- 提交事务
COMMIT ;
实际开发中,会在项目中搭建一个图片服务器
商品信息管理
- 核心目的:练习单表CRUD + 分页 + 上传
- 功能描述
· 所有商品都需要有保存分类(暂时一级分类)
· 进行商品添加要求输入(商品名称,价格,图片)
· 商品添加时为其设置特性(下拉框)
· 要求进行分页控制
for(int i=0; i<smart.getFiles().getCount(); i++){
if(smart.getFiles().getFile(i).getSize()>0){
//为上传文件重命名
String fileName = UUID.randomUUID()+smart.getFiles().getFile(i).getFileExt();
//如果不使用SmartUpload的save()方法,需要使用完整路径保存文件
String filePath = this.getServletContext().getRealPath("/upload/")+fileName;
smart.getFiles.getFile(i).saveAs(filePath);
}
}
为上传文件重命名
问题:SmartUpload使用的最大问题是上传的文件名称是原始的文件名,很难保证使用之中不会出现重名覆盖问题
解决:使用UUID类实现文件的重命名(要实现自动重命名,就不能使用SmartUpload的save()方法来保存文件)
判断是否有文件上传
if(smart.getFiles().getSize()>0)
判断上传文件的数量
if(smart.getFiles().getFile(x).getSize()>0)
取得上传附加信息
所有的上传操作的处理都是通过SmartUpload实现的
可以通过SmartUpload可以取得
判断是否有文件上传
if(smart.getFiles().getSize()>0)
判断上传文件的数量
if(smart.getFiles().getFile(x).getSize()>0)
上传组件使用
1. WEB-INF的lib目录下导入包
- jsp-api.jar
- servlet-api.jar
- SmartUpload.jar
2. WEB目录下新建upload.html
- 编写文件表单
3. 使用SmartUpload进行接收,保存上传文件信息,假设所有的上传文件保存在“upload”目录之中
4. 实现文件上传
SmartUpload组件的使用步骤
- 实例化SmartUpload类对象
- 初始化上传操作
- 接收所有的上传文件数据
- 进行数据保存
此时文件虽然已经上传,但是由于表单被enctype="multipart/form-data"封装,无法使用request.getParameter(), request.getParameterValues(), request.getParameterNames()获取参数信息,必须使用SmartUpload的内置方法来处理
//以下方法必须写在smart.upload();执行之后
//接收单个参数
smart.getRequest().getParameter(String name)
//接收一组参数
smart.getRequest().getParameterValues(String name)
//接收全部参数名称
smart.getRequest().getParameterNames()
SmartUpload上传组件
HTML中有个文件选择框
<input type="file" />
选中文件的目的是为了进行上传的操作处理,需要编写文件上传操作
如果要进行文件的上传,所有的数据要按照二进制的模式进行处理,必须修改表单的提交模式
提交页面是JSP页面,需要使用request对象接收所有的上传内容
要接收二进制数据,需要使用流来完成
//得到上传的输入流
public ServletInputStream getInputStream();
面试:请写出JSP中的九个内置对象
pageContext : javax.servlet.jsp.PageContext
- 常用方法:
//设置和取得属性
public void setAttribute(String name, Object value)
public void getAttribute(String name)
- pageContext对象只能在jsp页面使用,并且可以使用forward,include等指令操作,可以操作九个内置对象
request: javax.servlet.http.HttpServletRequest
- 作用:服务器端接收客户端发送来的请求数据,请求的数据可能是表单数据和头信息
- 常用方法
//设置和取得属性
public void setAttribute(String name, Object value)
public Object getAttribute(String name)
//取得提交参数
public String getParameter(String name)
public String[] getParameterValues(String name)
//取得所有请求参数的名称
public Enumeration<String> getParameterNames();
//设置请求编码
public void setCharacterEncoding(String charset);
//取得上下文路径
public String getContextPath();
//取得全部的Cookie数据
public Cookie[] getCookies();
response: javax.servlet.http.HttpServletResponse
- 作用:服务器端对客户端的回应处理
- 常用方法
//设置头信息
public void setHeader(String name, String value)
//设置Cookies
public void addCookies(Cookie c);
//取得输出流
public Writer getWriter();
//设置回应编码
public void setCharacterEncoding(String charset);
session: javax.servlet.http.HttpSession
- 作用:主要进行用户的登录检测处理
- 常用方法:
//设置和取得属性
public void setAttribute(String name, Object value)
public void getAttribute(String name)
- session失效
public void invalidate();
application: javax.servlet.ServletContext
- 作用:进行整个WEB上下文的处理操作
- 常用方法
//取得真实路径
public String getRealPath(String path);_
config: javax.servlet.ServletConfig
- 作用:可以取得web.xml文件里面配置的初始化参数内容
- 常用方法:
//取得初始化参数
public String getInitParameter(String param);
out: javax.servlet.jsp.JspWriter
exception: java.lang.Throwable
page: java.lang.Object
面试:请写出JSP中的九个内置对象
pageContext : javax.servlet.jsp.PageContext
- 常用方法:
//设置和取得属性
public void setAttribute(String name, Object value)
public void getAttribute(String name)
- pageContext对象只能在jsp页面使用,并且可以使用forward,include等指令操作,
request: javax.servlet.http.HttpServletRequest
response: javax.servlet.http.HttpServletResponse
session: javax.servlet.http.HttpSession
application: javax.servlet.ServletContext
config: javax.servlet.ServletConfig
out: javax.servlet.jsp.JspWriter
exception: java.lang.Throwable
page: java.lang.Object
pageContext对象
最主要的用处是进行属性的操作,需要结合MVC设计模式使用
pageContext的特点
1. pageContext只允许在JSP页面上使用
2. pageContext可以实现四种属性范围的设置
3. 可以直接支持标签指令处理
- 跳转;
public abstract void forward(String path)
- 包含:
public abstract void include(String path)
4. 可以直接操作九个内置对象
取得request对象
abstract ServletRequest getRequest()
取得response对象
abstract ServletResponse getResponse();
取得session对象
abstract HttpSession getSession()
取得application对象
abstract ServletContext getServletContext();
有了pageContext对象实际就意味着可以操作JSP页面的一切内容,但现在-使用最多的环境是设置和取得属性
config内置对象
WEB安全性问题
整个WEB开发中,有一种Tomcat的Bug
在每个项目中,都存在一个WEB-INF的文件夹,这个文件夹不可能在WEB目录中出现,所以是安全的(但不能访问)
如果要想访问WEB-INF目录下的JSP文件,必须修改web.xml文件的配置。新增如下代码:
config内置对象
1. 对应类型:javax.servlet.ServletConfig
2. 取得初始化参数的方法
String getInitParameter(String name)
网站计数器
指的是如果有用户来访问,对访问记录加1操作
需要考虑几种情况
1. 保证计数器的有效性,不管服务器是否被重新启动,计数都应该保留(建议使用文件保留整个的访问次数)
- 项目下新建count.txt文件,内容设置为“0”
2. 考虑网站可能并发性较高。用户非常多,可以使用BigInteger来处理数字
3. 在用户首次访问的时候需要进行计数,所以此时可以利用HttpSession接口中的isNew()方法,作用是用户首次方法(没有JESSIONID)则返回true,否则返回false
编写网站计数器
500:程序错误
读取文件内容
1. 拼凑filena
applicationn对象
· java.servlet.ServletContext
· 表示的是整个的WEB上下文(可以理解为表示整个WEB容器)
作用:
可以获取根路径
String path = application.getRealPath(String path);
String path = this.getServletContext().getRealPath(String path);
单表CRUD
用任意一张数据表实现数据的增删改查
1. 编写数据库脚本
2. 开发要求
- 用户ID必须是email或者手机号码
- 性别只能是男或者女
- 学历信息:小学,初中,普高,大学专科,大学本科,硕士,博士,博士后
3. 开发数据库连接类
package cn.mldn.dbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
//定义JDBC常量
public static final String DBDRIVER = "com.mysql.jdbc.Driver";
public static final String DBURL = "jdbc:mysql://localhost:3302/project?useUnicode=true&characterEncoding=utf-8";
public static final String DBUSER = "root";
public static final String DBPWD = "123456";
public static Connection get(){
Connection conn = threadLocal.get();
try {
if(conn==null){
conn = rebuildConnection();
threadLocal.set(conn);
}
return conn;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void close(){
Connection conn = threadLocal.get();
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static Connection rebuildConnection() throws Exception{
Class.forName(DBDRIVER);
return DriverManager.getConnection(DBURL, DBUSER, DBPWD);
}
}
4. 开发VO类
5. 开发DAOFactory工厂类(用于获取DAO层对象)
验证码生成之后保存在session中