经过前几节的学习,我们已经找到之前碰到的问题的原因了。那么下面接着做项目学习。
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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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();@Overrideprotected 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 {@Overridepublic 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();@Overridepublic 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 {@Overridepublic 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类。