一.创建项目
1.创建web项目,起名为netctoss 1.png2.png
3.png
2.导入Tomcat中的jar包
-
高亮选中项目->鼠标右键->Properties
3.png
3.在pom.xml中导入相关jar包
<!-- 数据库连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- 连接oracle数据库 -->
<dependency>
<groupId>com.jslsolucoes</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
</dependency>
<!-- JSTL标签 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
二.资费查询的图解分析
4.png分析:首先连接oracle数据库,然后查询数据库中cost的表的信息,然后通过servlet去查询资费,并转发到jsp(这里面规定访问路径为/findCost.do)
三.查询功能
1.在src/main/resource目录下创建db.properties配置文件,并书写相应的配置信息
# db connection parameters
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=system
pwd=oracle
# datasource parameters
initsize=1
maxsize=2
2.在src/main/java目录下创建util包,在包下创建DBUtil工具类,用来读取db.properties配置文件中的参数,并实现连接、失败、回滚的方法.
注:这里要使用连接池对象
package util;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
public class DBUtil {
//连接池对象-由DBCP提供
private static BasicDataSource ds;
static {
Properties p = new Properties();
try {
p.load(DBUtil.class.getClassLoader()
.getResourceAsStream("db.properties"));
//读取参数
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String user = p.getProperty("user");
String pwd = p.getProperty("pwd");
String initsize = p.getProperty("initsize");
String maxsize = p.getProperty("maxsize");
//创建连接池
ds = new BasicDataSource();
//设置参数
//使用这个参数注册驱动
ds.setDriverClassName(driver);
//使用这3个参数创建连接
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pwd);
//使用其他参数管理连接
ds.setInitialSize(new Integer(initsize));
ds.setMaxActive(new Integer(maxsize));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(
"加载db.properties失败", e);
}
}
public static Connection getConnection()
throws SQLException {
return ds.getConnection();
}
/**
* 由连接池创建的连接,连接的close方法
* 被连接池重写了,变为了归还连接的逻辑,
* 即:连接池会将连接的状态设置为空闲,
* 并清空连接中所包含的任何数据.
*/
public static void close(Connection conn) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"归还连接失败", e);
}
}
}
public static void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("回滚失败",e);
}
}
}
}
3.在src/main/java目录下创建entity实体类包,在包下创建Cost类,添加成员方法并生成setter和getter方法
package entity;
import java.io.Serializable;
import java.sql.Timestamp;
public class Cost implements Serializable {
// 因为封装类型可以为null
// 主键
private Integer costId;
private String name;
// 基本时长
private Integer baseDuration;
// 基本费用
private Double baseCost;
// 单位费用
private Double unitCost;
// 状态(枚举): 0-开通;1-暂停;
private String status;
// 资费说明
private String descr;
// 创建时间
private Timestamp creatime;
// 开通时间
private Timestamp startime;
// 资费类型(枚举):1-包月;2-套餐;3-计时;
private String costType;
public Integer getCostId() {
return costId;
}
public void setCostId(Integer costId) {
this.costId = costId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getBaseDuration() {
return baseDuration;
}
public void setBaseDuration(Integer baseDuration) {
this.baseDuration = baseDuration;
}
public Double getBaseCost() {
return baseCost;
}
public void setBaseCost(Double baseCost) {
this.baseCost = baseCost;
}
public Double getUnitCost() {
return unitCost;
}
public void setUnitCost(Double unitCost) {
this.unitCost = unitCost;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescr() {
return descr;
}
public void setDescr(String descr) {
this.descr = descr;
}
public Timestamp getCreatime() {
return creatime;
}
public void setCreatime(Timestamp creatime) {
this.creatime = creatime;
}
public Timestamp getStartime() {
return startime;
}
public void setStartime(Timestamp startime) {
this.startime = startime;
}
public String getCostType() {
return costType;
}
public void setCostType(String costType) {
this.costType = costType;
}
}
4.在src/main/java目录下创建dao的包,在包下创建CostDao类,用来查找cost中的对象信息,并返回集合
package dao;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import entity.Cost;
import util.DBUtil;
public class CostDao implements Serializable {
public List<Cost> findAll() {
Connection conn = null;
try {
conn = DBUtil.getConnection();
String sql =
"select * from cost_bao "
+ "order by cost_id";
Statement smt =
conn.createStatement();
ResultSet rs = smt.executeQuery(sql);
List<Cost> list = new ArrayList<Cost>();
while(rs.next()) {
Cost c = new Cost();
c.setCostId(rs.getInt("cost_id"));
c.setName(rs.getString("name"));
c.setBaseDuration(rs.getInt("base_duration"));
c.setBaseCost(rs.getDouble("base_cost"));
c.setUnitCost(rs.getDouble("unit_cost"));
c.setStatus(rs.getString("status"));
c.setDescr(rs.getString("descr"));
c.setCreatime(rs.getTimestamp("creatime"));
c.setStartime(rs.getTimestamp("startime"));
c.setCostType(rs.getString("cost_type"));
list.add(c);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(
"查询资费失败", e);
} finally {
DBUtil.close(conn);
}
}
}
对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的.
5.在src/main/java目录下创建web的包,在包下创建MainServlet类并继承HttpServlet和实现转发到jsp
package web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.CostDao;
import entity.Cost;
public class MainServlet extends HttpServlet {
@Override
protected void service(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
//获取访问路径
String path = req.getServletPath();
//根据规范(图)处理路径
if("/findCost.do".equals(path)) {
findCost(req,res);
} else {
throw new RuntimeException("没有这个页面");
}
}
//查询资费
protected void findCost(
HttpServletRequest req,
HttpServletResponse res) throws ServletException, IOException {
//查询所有的资费
CostDao dao = new CostDao();
List<Cost> list = dao.findAll();
//将请求转发到jsp
req.setAttribute("costs", list);
//当前:/netctoss/findCost.do
//目标:/netctoss/WEB-INF/cost/find.jsp
req.getRequestDispatcher(
"WEB-INF/cost/find.jsp").forward(req, res);
}
}
四种访问路径的区别:
req.getContextPath()//获取项目名
req.getServletPath()//获取访问路径
req.getRequestURI()//获取绝对路径
req.getRequestURL()//获取完整路径
6.完成web.xml中的配置信息
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>web.MainServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
7.在src->main->webapp->WEB-INF下创建cost文件,并在cost文件下创建find.jsp文件,并且把之前写好的静态页(fee_list)代码粘贴到find.jsp文件中
8.在src->main->webapp下把images和style资源导入进来,部署项目到tomcat服务器上,在网址上进行访问
9.资源不显示是因为导入资源路径有问题,那么需要在jsp中引入资源的路径把
../
去掉6.png
10.导入Libraries->jstl->META_INF->c.tld标签
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
11.使用EL表达式获取数据,使用JSTL对数据进行遍历
<c:forEach items="${costs}" var="c">
<tr>
<td>${c.costId}</td>
<td><a href="fee_detail.html">${c.name}</a></td>
<td>${c.baseDuration}</td>
<td>${c.baseCost}</td>
<td>${c.unitCost}</td>
<td>${c.creatime}</td>
<td>${c.startime}</td>
<td>
<c:if test="${c.status==0}">开通</c:if>
<c:if test="${c.status==1}">暂停</c:if>
</td>
<td>
<input type="button" value="启用" class="btn_start" onclick="startFee();" />
<input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" />
<input type="button" value="删除" class="btn_delete" onclick="deleteFee();" />
</td>
</tr>
</c:forEach>
7.png
12.格式化jsp上显示的时间,如图所示,创建时间显示的数据带毫秒 8.png
注:使用fmt.tld下的 formatDate
<td> <fmt:formatDate value="${c.creatime}" pattern="yyyy-MM-dd HH:mm:ss"/> </td>
四.问题解析
1.在jsp上引用样式文件和图片为什么没写../?
浏览器在加载网页时获取图片,这个是加载的网页和图片的相对关系,加载的网页的访问路径是/netctoss/findCost.do(浏览器不知道这件事),图片的访问路径/netctoss/images/logo.png,故相对路径是不加../的
2.为什么要将jsp放在WEB-INF下?
WEB-INF是具有保护功能的,它可以保护内部的资源,避免该资源被直接访问,需要通过转发才能访问.将jsp放到WEB-INF下,就是要保护它,避免它被直接访问,从而丢掉数据来源,导致报错
3.为什么要将静态资源放在webapp下 ?
静态资源是浏览器直接访问的,不存在转发,所以直接放在webapp下就可以,不需要放在WEB-INF里面
4.为什么jsp上有2处声明了编码?
<%@page pageEncoding="utf-8"%>
pageEncoding是给服务器翻译jsp时用的
<meta charset="utf-8">
meta中的编码是给浏览器加载HTML时用的
网友评论