经过前几节的学习,我们已经找到之前碰到的问题的原因了。那么下面接着做项目学习。
1 新建dynamic web project
建立时把web.xml也生成下,省的右面再添加。
会询问是否改为java ee环境?no就行,其实改过来也是可以的。这个不重要。
新建完毕后,看下当前的web.xml
欢迎界面不需要,删除即可。
2 流程图
我们开始写代码之前,还是重点关注下这个逻辑流程图,之前编程序都没注意这个,所以才发生错误不知道怎么回事。
web.xml很重要,这里配置了这个工程的入口。我们这个程序实际上是一个servlet程序,前端配合jsp网页展示。所以,入口就是规定servlet的名称及url。当部署在服务器后,我们的页面首先要访问servlet,之后拦截请求后,处理请求并获取参数,之后再传给前端的jsp网页去呈现。
在编写代码时,可以先写servlet,也可以先配置web.xml,也可以先写jsp文件,从逻辑上将,我们先去配置servlet的web.xml更好。
3 配置servlet
这里主要是配置servlet信息,如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>eb1</display-name>
<servlet>
<servlet-name>index</servlet-name>
<servlet-class>com.xxx.xx</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
</web-app>
主要是servlet及其mapping,然后各有两个项。
其中名称需要一致,类就指向之后要新建的类。然后url也可以随便指定,部署后就从这里进入。
4 引入类库
这些类库都是配置好的,直接放入lib即可。放入后,所有类库需要buildpath,项目会自动加入reference libraries.
5 创建实体类
实体类根据数据库的表来创建。对于导航栏,有两个表需要用到:大类表和标签表。
实体类可放入vo包里。由于大类型包含小类型,所以小类型也得建类。
下面是具体实现:
tagl类:
package com.xx.vo;
/**
* 标签类
*
*/
public class Tag {
private int id;
private String name;
private String url;
public Tag() {
// TODO Auto-generated constructor stub
}
public Tag(int id, String name, String url) {
super();
this.id = id;
this.name = name;
this.url = url;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Tag [id=" + id + ", name=" + name + ", url=" + url + "]";
}
}
bigtype类
package com.xx.vo;
import java.util.ArrayList;
import java.util.List;
public class ProductBigType {
private int id;
private String name;
private String remarks;
private List<ProductSmallType> smallTypeList = new ArrayList<ProductSmallType>();
public ProductBigType() {
// TODO Auto-generated constructor stub
}
public ProductBigType(int id, String name, String remarks, List<ProductSmallType> smallTypeList) {
super();
this.id = id;
this.name = name;
this.remarks = remarks;
this.smallTypeList = smallTypeList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public List<ProductSmallType> getSmallTypeList() {
return smallTypeList;
}
public void setSmallTypeList(List<ProductSmallType> smallTypeList) {
this.smallTypeList = smallTypeList;
}
@Override
public String toString() {
return "ProductBigType [id=" + id + ", name=" + name + ", remarks=" + remarks + ", smallTypeList="
+ smallTypeList + "]";
}
}
smalltype类
package com.xx.vo;
public class ProductSmallType {
private int id;
private String name;
private String remarks;
private int bigTypeId;
public ProductSmallType() {
// TODO Auto-generated constructor stub
}
public ProductSmallType(int id, String name, String remarks, int bigTypeId) {
super();
this.id = id;
this.name = name;
this.remarks = remarks;
this.bigTypeId = bigTypeId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public int getBigTypeId() {
return bigTypeId;
}
public void setBigTypeId(int bigTypeId) {
this.bigTypeId = bigTypeId;
}
@Override
public String toString() {
return "ProductSmallType [id=" + id + ", name=" + name + ", remarks=" + remarks + ", bigTypeId=" + bigTypeId
+ "]";
}
}
其中,大类里用到了List和ArrayList,需要引导util包。
6 创建数据库交互类
数据库交互主要是连接,关闭数据库,需要做成静态的,这样就一直存在。
DBUtil类
package com.xx.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 数据库交互类
*
*/
public class DBUtil {
// 主方法 用于测试
public static void main(String[] args) {
try {
DBUtil.getConn();
System.out.println("conn ok...");
} catch (Exception e) {
System.out.println("conn error...");
e.printStackTrace();
}
}
// 加载驱动
static {
try {
Class.forName("com.mysql.jdbc.Driver"); // 反射机制加载驱动
} catch (ClassNotFoundException e) {
System.out.println("error in forName...");
e.printStackTrace();
}
}
// 获取连接
public static Connection getConn() {
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ebuys?useUnicode=true&characterEncoding=utf8","root","1234");
} catch (SQLException e) {
System.out.println("error in DriverManager");
e.printStackTrace();
}
return conn;
}
// 完整关闭
public static void closeAll(Connection conn, PreparedStatement pstmt, ResultSet rs) {
closeResult(rs);
closeState(pstmt);
closeConn(conn);
}
// 关闭连接
private static void closeConn(Connection conn) {
if(null != conn) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("error in close...");
e.printStackTrace();
}
}
}
// 关闭管道
private static void closeState(PreparedStatement pstmt) {
if(null != pstmt) {
try {
pstmt.close();
} catch (SQLException e) {
System.out.println("error in pstmt...");
e.printStackTrace();
}
}
}
// 关闭结果
private static void closeResult(ResultSet rs) {
if(null != rs) {
try {
rs.close();
} catch (SQLException e) {
System.out.println("error in rs...");
e.printStackTrace();
}
}
}
}
这里可以用main主方法来测试下是否能够连接,注意这些都是需要类库支持的,要是忘记引入,会发生错误。
7 创建servlet
现在来编写刚才web.xml规定的servlet,作用是将数据库内的信息传入页面。这里需要进行间接的数据库操作。
package com.xx.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xx.service.ProductBigTypeService;
import com.xx.service.TagService;
import com.xx.service.impl.ProductBigTypeServiceImpl;
import com.xx.service.impl.TagServiceImpl;
import com.xx.vo.ProductBigType;
import com.xx.vo.Tag;
public class InitController extends HttpServlet {
private static final long serialVersionUID = 1L;
// 通过接口及其实例化来降低耦合度 让程序容易拓展
private ProductBigTypeService bigTypeService = new ProductBigTypeServiceImpl();
private TagService tagService = new TagServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 查询类别
List<ProductBigType> bigTypeList = bigTypeService.findAllBigType();
// 查询标签
List<Tag> tagList = tagService.findAll();
// 查询结果放入作用域
req.setAttribute("bigTypeList", bigTypeList);
req.setAttribute("tagLiat", tagList);
//
req.getRequestDispatcher("/index.jsp").forward(req, resp);
}
}
这个类的思路是重写service来处理请求,并转发到index.jsp。处理过程用到了大类列表和标签列表,这就涉及到查询,这个查询是封装在服务的方法里的。
这里涉及的概念较多,服务被写为了接口,也就是可以理解为纯虚函数。具体在impl里实现方法。
大类列表是通过大类服务的获取大类方法实现的,标签列表是通过标签服务的获取标签方法实现的。两者思路是相同的,需要具体实现。
实现的过程中,大类还包括了小类,因此也需要相应的实现小类的服务和方法。
标签的较为简单,是单层的,先看标签的接口
package com.xx.service;
import java.util.List;
import com.xx.vo.Tag;
public interface TagService {
// 查询标签
List<Tag> findAll();
}
其实现是
package com.xx.service.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.xx.service.TagService;
import com.xx.util.DBUtil;
import com.xx.vo.Tag;
public class TagServiceImpl implements TagService {
@Override
public List<Tag> findAll() {
List<Tag> list = new ArrayList<Tag>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConn();
String sql = "SELECT * FROM T_TAG";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
Tag tag = new Tag();
tag.setId(rs.getInt("id"));
tag.setName(rs.getString("name"));
tag.setUrl(rs.getString("url"));
list.add(tag);
}
return list;
} catch (SQLException e) {
System.out.println("error in tagServiceImpl...");
e.printStackTrace();
} finally {
DBUtil.closeAll(conn, pstmt, rs);
}
return null;
}
}
再来看大类接口
package com.xx.service;
import java.util.List;
import com.xx.vo.ProductBigType;
public interface ProductBigTypeService {
// 查询大类信息
List<ProductBigType> findAllBigType();
}
其实现为
package com.xx.service.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.xx.service.ProductBigTypeService;
import com.xx.service.ProductSmallTypeService;
import com.xx.util.DBUtil;
import com.xx.vo.ProductBigType;
import com.xx.vo.ProductSmallType;
public class ProductBigTypeServiceImpl implements ProductBigTypeService {
private ProductSmallTypeService smallTypeService = new ProductSmallTypeServiceImpl();
@Override
public List<ProductBigType> findAllBigType() {
List<ProductBigType> list = new ArrayList<ProductBigType>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConn();
String sql = "SELECT * FROM T_BIGTYPE";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
ProductBigType pbt = new ProductBigType();
pbt.setId(rs.getInt("id"));
pbt.setName(rs.getString("name"));
pbt.setRemarks(rs.getString("remarks"));
List<ProductSmallType> pst = smallTypeService.findByBigTypeId(rs.getInt("id"));
pbt.setSmallTypeList(pst);
list.add(pbt);
}
return list;
} catch (SQLException e) {
System.out.println("error in bigTypeServiceImpl...");
e.printStackTrace();
} finally {
DBUtil.closeAll(conn, pstmt, rs);
}
return null;
}
}
在组合列表时,用到了小类接口,这里需要传入大类的id
package com.xx.service;
import java.util.List;
import com.xx.vo.ProductSmallType;
public interface ProductSmallTypeService {
// 查询当前大类id对应的所有小类
List<ProductSmallType> findByBigTypeId(int bigTypeId);
}
对应的实现是
package com.xx.service.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.xx.service.ProductSmallTypeService;
import com.xx.util.DBUtil;
import com.xx.vo.ProductSmallType;
public class ProductSmallTypeServiceImpl implements ProductSmallTypeService {
@Override
public List<ProductSmallType> findByBigTypeId(int bigTypeId) {
List<ProductSmallType> list = new ArrayList<ProductSmallType>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConn();
String sql = "SELECT * FROM T_SMALLTYPE WHERE BIGTYPEID = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, bigTypeId);
rs = pstmt.executeQuery();
while(rs.next()) {
ProductSmallType pst = new ProductSmallType();
pst.setId(rs.getInt("id"));
pst.setName(rs.getString("name"));
pst.setRemarks(rs.getString("remarks"));
pst.setBigTypeId(bigTypeId);
list.add(pst);
}
return list;
} catch (SQLException e) {
System.out.println("error in ProductSmallTypeServiceImpl...");
e.printStackTrace();
} finally {
DBUtil.closeAll(conn, pstmt, rs);
}
return null;
}
}
这里用到个知识点,就是怎么用通配符写sql语句。
8 写index.jsp
接下来,就可以写jsp了。首先引入css和图片资源,之后新建index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>eb1</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div id="header" class="wrap">
<jsp:include page="common/top.jsp"/>
</div>
<div id="footer">
<jsp:include page="common/footer.jsp"/>
</div>
</body>
</html>
这里用到了jsp里的include指令。分别指向top和footer,先来看footer
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Copyright © 2019 xx inc. All rights reserved.
</body>
</html>
再来看top,使用div来构建出导航栏。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div id="logo">
<img src="images/logo.gif" />
</div>
<div class="help">
</div>
<div class="navbar">
<ul class="clearfix">
<li class="current"><a href="index">首页</a></li>
<c:forEach items="${bigTypeList}" var="bType">
<li>
<a href="productServlet?oper=productType&id=${bType.id}">${bType.name}</a>
</li>
</c:forEach>
</ul>
</div>
</body>
</html>
这里先实现了主导航栏,用了c:foreach的写法。
8 效果展示
下面看下实现效果,使用tomcat部署,打开网页:
也就是说前面写的都是正确的。今天的课程就到这里,接下来接着完善jsp页面和servlet类。