Java实战|Tomcat+Servlet+Sql开发简单网站,从配置环境开始

课题描述:

Java实验五 Servlet
(继续使用实验四中创建的students数据库和其中的scores表)
使用Tomcat作为Web服务器和Servlet容器,使用SQL Server/MySQL作为数据服务器,从浏览器端发起对Servlet的调用,完成如下任务:
(1)向scores表中插入新的记录,表示录入新学生信息;(注意:学号为主键,插入学号相同的学生要提示错误;如果学号由数据库自动生成除外)
(2)批量录入成绩,即:在一个界面上列出所有学生信息,在同一个界面上成绩还可以重新录入;录入部分或者全部学生成绩后,提交,将所有成绩写入scores表。(没有录入的成绩,可以暂定为0写入scores表)
使用的静态html页面和动态Servlet的个数没有限制。


右侧目录,可以根据进度跳转,正式代码部分点这里。

Eclipse编译器下配置Tomcat

步骤如下,按照步骤肯定可以的。(大概需10-20分钟)

eclipse安装就不用写了吧,

1.下载Tomcat

先看看自己的java是哪一个版本
一般都是java7、8、12;所以安装Tomcat8.5肯定可以用的
好吧还是有更老的版本需要下载tomcat7.0

下载地址:https://tomcat.apache.org/download-80.cgi

下载好解压到随便一个目录,我的是下面这个目录:D:\tomcatresource

2.Eclipse中配置Tomcat,浏览器访问一个简单的jsp页面

Eclipse编译器中按照Tomcat按照这个博客这个博客链接就可以啦。
完全按照这个博客写的一步一步做就可以了,https://blog.csdn.net/yerenyuan_pku/article/details/51830104
上面做完后,用浏览器可能会访问你的网页可能出现404错误码,他的博客没有说清楚,👇

解决方法:修改浏览器访问的url地址
浏览器上访问你的jsp页面的url地址是这样写的:👇

如果网页显示中文乱码👇按这样修改jsp页面,方框里的编码格式改成utf-8

新建Servlet

上面步骤做完,已经能够访问一个JSP静态页面了。
接下来是新建Servlet,来完成动态数据展示。

右键你的项目包,新建,选择servlet。

输入名字后,直接点击Finish,自动生成了servlet文件


Servlet,其实只需要重写doGet方法,把想要的数据加入到response对象中就可以了

比如我append了这么一句话,"My First Hello world page2333"

然后启动servlet,打开浏览器,就可以通过url访问你的servlet了

有可能又出现了404👇



只需要把url地址链接改成 http://localhost:8080/项目名/selvert名/

把Servlet和jsp页面相关联

通过Servlet可以返回你想要的数据到Response对象中;
所以只需要在doGet中,调用实验四的JDBC连接数据库,把获取到数据库的数据,append加入到response对象中就可以了。
然后应该还要把response对象中的数据展示到JSP页面中。


如何把Servlet与JSP页面连接起来呢?也就是如何把response对象中的数据展示到JSP页面中?
比如我想把自己写的Servlet中的,doGet函数获得的数据,返回到JSP静态页面,交给自己编写的学生信息展示JSP静态页面展示数据,该怎么做?
1.需要先用request.setAttribute设置要传递的数据,
2.然后在Servlet使用RequestDispatcher接口来传递数据了,RequestDispatcher可以把响应工作(如展示学生信息)派发给jsp页面、其它Servlet、或者Html页面等。
点这篇博客,把RequestDispatcher原理和应用讲解的很清楚了

发现个bug,selvert会乱码,先不管了

一个简单的测试代码:servlet把一个学生的数据从数据库取出,向jsp页面传递学生数据,jsp页面展示该学生信息

在selvert的doGet函数中请求实验四的students数据库,转发数据到jsp页面,jsp页面展示数据。

测试代码的 整个目录结构是这样的,

其中World.java,这个selvlet中的doGet函数,是这样写的:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("utf-8");
		Connection connection = null; //连接接口实例
		Statement statmment = null; //执行静态sql的接口实例
		PreparedStatement preStatement = null; //执行动态sql的接口实例
		ResultSet resultSet = null; //sql查询的返回数据集合
		String userName = "sa"; //数据库账号
		String passWord = "root"; //数据库密码
		String url = "jdbc:sqlserver://127.0.0.1:1433"; //sqlserver连接地址url
		int sno = 0;
		String name = null;
		String ssex = null;
		int score = 0;
		
		//加载数据库驱动
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//DriverManager接口获取连接
		try {
			connection = DriverManager.getConnection(url,userName,passWord);
			//获取 执行数据库静态SQL语法的接口
			statmment = connection.createStatement();
			if(connection != null) {
				System.out.println("连接成功!");
			}
			//从数据库中 获取一位同学的个人信息
			String querySqlString = ""
					+ "USE students"
					+ "\n"
					+ "SELECT TOP 1* FROM scores"; 
			resultSet = statmment.executeQuery(querySqlString);
			while(resultSet.next()) {
				sno = resultSet.getInt("sno");
				name = resultSet.getString("name");
				ssex = resultSet.getString("ssex");
				score = resultSet.getInt("score");
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//用setAttribute设置传递的数据参数
        request.setAttribute ( "sno", sno) ; 
        request.setAttribute ( "name", name) ; 
        request.setAttribute ( "ssex", ssex) ; 
        request.setAttribute ( "score", score) ; 
        //重要的是getRequestDispatcher 把数据交给jsp页面响应
        request.getRequestDispatcher ( "NewFile.jsp").forward( request , response );//转发到NewFile.jsp,让他去具体响应
	}

自己编写的NewFile.jsp静态页面这样写的:

<%@ 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>
用户学号:${sno} 用户姓名:${name}  用户性别:${ssex} 用户分数:${score}
</body>
</html>

浏览器上访问页面
网页效果:把从数据库获取的数据展示到jsp页面上了

上面是简单的测试,上面的测试代码把一个学生的数据显示到jsp页面了,那么如果像显示多个学生的信息呢,
比如说通过查询数据库,获取了3条学生数据,想把3条数据传递给jsp页面,jsp页面展示这3个学生数据的信息。

需要用jstl的标签c:forEach来遍历

首先需要下载jstl(JSP标准标签库)的jar包,
jstl.jar
standard.jar
下载地址是:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/jakarta-taglibs-standard-1.1.2.zip
然后把这两个jar文件放在项目目录的WEB-INF/lib文件夹里


怎么找到网站项目目录呢?




进入属性窗口,可以看到目录了,点击就能进入项目目录了,把这两个jar文件放在项目目录的WEB-INF/lib文件夹里


然后在jsp页面中加入这句话👇,就可以了 ``` <%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core"%>

![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120132847076-870094979.png)

<br />
selvlet的doGet中这样写👇
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191119225606694-205016549.png)
jsp页面中使用forEach遍历,${变量}指的是把数据套模板传进来;比如这个${users}的变量,指的就是所有用户的数据,而${user}就是单独一个学生的数据,每次for循环中展示一个学生数据。

![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191119225739520-1596092463.png)

jsp真无聊的
jsp真无聊的
jsp真无聊的
各种代码杂糅在一起,现代人都不用jsp了吧

#正式写代码吧
上面的其实可以都不用看的,直接写代码吧

还是先了解一下MVC模式下图👇
详细参考:https://www.runoob.com/design-pattern/mvc-pattern.html
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120200845055-1264493876.png)


<br />
第一题整体项目文件结构是这样的👇
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120160348041-2081717421.png)

SQL Server的数据库是这样的👇
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191121192946741-1221648546.png)


##1.student.java;首先需要设计model用户模型层,对应scores数据表中的学生

student类的属性与scores数据表属性保持一直,并对每个属性写getXxx()和setXxx()方法,这样通过反射机制,才能传递student这个类的信息到jsp页面;
具体原理,现在也不太清楚,先学会骑自行车,有时间再学造轮子。
<br />

Eclipse截图👇
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120160835854-1245620073.png)
<br />

student.java代码贴出来了,方便食用:

//学生类
public class Student{
public int sno;
public String names;
public String ssex;
public int score;

//有参构造函数 初始化实例对象的属性值
public Student(int sno, String name, String ssex, int score) {
	// TODO Auto-generated constructor stub
	this.sno = sno;
	this.names = name;
	this.ssex = ssex;
	this.score = score;
}

public void Student() {
	// TODO Auto-generated constructor stub
}

public String getNames() {
	return this.names;
}

public void setNames(String names) {
	this.names = names;
}

public String getSsex() {
	return this.ssex;
}

public void SetSsex(String ssex) {
	this.ssex = ssex;
}

public int getSno() {
	return this.sno;
}

public void setSno(int sno) {
	this.sno = sno;
}

public int getScore() {
	return this.score;
}

public void setScore(int score) {
	this.score = score;
}

}

##2.MySqlUtil.java,操作数据库的工具类
(可以用实验四的,最好分离成一个文件,方便各个servlet调用)
主要用于,连接sqlserver数据库,查询学生信息,添加学生。

eclipse中部分截图如下👇
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120161159779-602749555.png)
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120161238054-1303531703.png)
<br/>
完整代码如下👇,方便食用:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

//数据库类: 连接、查询、添加数据
public class MySqlUtil{
private Connection connection = null; //连接接口实例
private Statement statmment = null; //执行静态sql的接口实例
private PreparedStatement preStatement = null; //执行动态sql的接口实例
private ResultSet resultSet = null; //sql查询的返回数据集合
private String userName = "sa";
private String passWord = "root";
private String url = "jdbc:sqlserver://127.0.0.1:1433"; //sqlserver连接地址url

public String querySqlString = ""
		+ "USE students"
		+ "\n"
		+ "SELECT * FROM scores";

public String existSqlString = ""
		+ "USE students"
		+ "\n"
		+ "SELECT * FROM scores WHERE scores.sno = ?";

public String insertSqlString = ""
		+ "USE students"
		+ "\n"
		+ "INSERT INTO scores(sno,name,ssex,score) VALUES(?,?,?,?)";

/*
 * MySqlUtil类的构造函数
 * 功能:初始化数据库驱动、连接数据库
 */
public MySqlUtil() throws ClassNotFoundException, SQLException {
	// TODO Auto-generated constructor stub
	//加载数据库驱动
	Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
	//初始化连接数据库
	connection = DriverManager.getConnection(url,userName,passWord);
	//初始化statment执行sql实例对象
	statmment = connection.createStatement();
}

/*
 * queryAllStudent函数
   * 功能:查询所有学生信息 ,把数据库中所有学生实体存入到 数组中
 * @return函数返回值: ArrayList<Student> 集合列表类型
 */
public ArrayList<Student> queryAllStudent() throws SQLException, ClassNotFoundException {
	Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
	//初始化连接数据库
	connection = DriverManager.getConnection(url,userName,passWord);
	//初始化statment执行sql实例对象
	statmment = connection.createStatement();
	ArrayList<Student> resultList = new ArrayList<>();
	resultSet = statmment.executeQuery(querySqlString);
	if(resultSet == null ) return null;
	while(resultSet.next()) {
		int sno = resultSet.getInt("sno");
		String names = resultSet.getString("name");
		String ssex = resultSet.getString("ssex");
		int score = resultSet.getInt("score");
		resultList.add(new Student(sno,names,ssex,score));
	}
	return resultList;
}

/*
 * existBySno查询数据库是否已经存在当前学号
 * @return: true表示存在,false表示不存在
 */
public Boolean existBySno(int sno) {
	resultSet = null;
	try {
		preStatement = connection.prepareStatement(this.existSqlString);
		preStatement.setInt(1, sno);
		resultSet = preStatement.executeQuery();
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	if(resultSet == null) return true;
	return false;
}

/*
 * insertStudent:向数据库中添加学生信息,需要先调用existBySno查询数据库是否已经存在当前学号
 * @params: sno学号,name姓名,ssex性别,score成绩
 */
public Boolean insertStudent(int sno,String name,String ssex,int score) {
	try {
		preStatement = connection.prepareStatement(this.insertSqlString);
		preStatement.setInt(1, sno);
		preStatement.setString(2, name);
		preStatement.setString(3, ssex);
		preStatement.setInt(4, score);
		preStatement.execute();
		return true;
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return false;
	}
	
}

}


##3. insertOne.jsp,视图层(view层),对应问题一:添加一个同学的信息页面
主要就是用form表单,提交学生信息;
那form表单如何实现前端jsp页面向后台发送请求、传递学生数据呢?,只需要form表单的action属性设置为你编写的servlet名称,在这个servlet中可以接收到前端jsp提交的学生信息。servlet如何接收的可以看第四步
![](https://img2018.cnblogs.com/blog/1454456/201911/1454456-20191120161736225-1649557284.png)

完整代码如下👇,方便食用:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core"%>

需求一:添加一个同学的信息
学号:
姓名:
性别:
成绩:
```

4.firstServlet.java,控制层(controller层),编写的servlet代码,从前端jsp页面获取到学生数据,处理第一个问题的添加学生信息的功能。

如何获取到form表单提交的数据?主要就是用request.getParmeter("form表单中字段的name"),得到一个字符串;具体看代码吧

package firstServlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.management.Query;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;

import util.MySqlUtil;
import util.Student;


/**
 * Servlet implementation class firstServlet
 */
@WebServlet("/firstServlet")
public class firstServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static MySqlUtil sqlUtil;
	
    /**
     * @throws SQLException 
     * @throws ClassNotFoundException 
     * @see HttpServlet#HttpServlet()
     */
    public firstServlet() throws ClassNotFoundException, SQLException {
        super();
        this.sqlUtil = new MySqlUtil();
    }
    
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String message = new String(); //消息:是否添加成功
		int sno = Integer.parseInt(request.getParameter("sno")); //request.getParameter获取到表单提交的字段值 //使用Integer.parseInt()方法,把String转换成为int型
		String namess = request.getParameter("name"); //使用Integer.parseInt()方法,把String转换成为int型
		String ssex = request.getParameter("ssex");
		int score = Integer.parseInt(request.getParameter("score"));
		System.out.println(namess + sno + ssex+score);
		if(sqlUtil.existBySno(sno) == false) {
			if(sqlUtil.insertStudent(sno,namess,ssex,score) == true) message = "添加成功!";
			else message = "添加失败,该学号已存在!";
		}else message = "添加失败,该学号已存在!";
		ArrayList<Student> users = new ArrayList<>();
		try {
			//通过调用 之前编写的数据库工具类 查询所有学生信息
			users = sqlUtil.queryAllStudent();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//用setAttribute设置传递的数据参数
		request.setAttribute ( "message", message);
		request.setAttribute ( "users", users);
		//getRequestDispatcher 把studentsData获取到的所有学生数据交给jsp页面响应
		request.getRequestDispatcher ("show.jsp").forward( request , response );//转发到NewFile.jsp,让他去具体响应
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

5.show.jsp,还是视图层,上面的servlet转发响应到这个show页面,展示所有用户信息,c:forEach标签遍历所有学生信息

<%@ page   contentType= "text/html; charset=UTF-8" pageEncoding ="UTF-8" trimDirectiveWhitespaces= "true"
          session ="true" %>
<%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv = "Content-Type" content ="text/html; charset=UTF-8">
<title> 用户列表</title>
</head>
<body>

${message}
<br/>

<c:forEach items="${users}" var="user" >
		<tr>
			 <td align = "center">${user.sno}</td>
			 <td align = "center">${user.names}</td>
			 <td align = "center">${user.ssex}</td>
			 <td align = "center">${user.score}</td>
		 </tr>
		 <br />
</c:forEach>



</body>
</html>

6.网页端效果:

浏览器访问这个地址:http://127.0.0.1:8080/Hello/insertOne.jsp
效果如下👇,

点击提交后👇,form表单提交,访问了firstServlet,firstServlet调用数据库工具类,insert添加form表单传来的学生数据,

再看一下servlet代码逻辑,应该更清楚整个mvc的逻辑和过程👇,servlet就是功能逻辑控制层controller,用来从数据库中取数据、获取jsp前端静态页面传来的form表单学生信息参数;jsp页面就是视图view层静态展示学生信息的页面;student类就是model层;数据库工具类是为了代码灵活性,另外编写的工具包。

写在最后,代码下载

上面是第一个小问的代码和编写思路。
第二个问题,思路和第一个差不多吧,代码比较长就不放出来了。
简单说一下第二问思路,具体实现细节在代码中;
首先浏览器上访问入口servlet,127.0.0.1:8080/Hello/secondServlet,这个secondservlet会从数据库中获取所有学生信息数据,把学生信息users作为参数setAttribute加入到request请求包中,再把响应转发给insertAll.jsp页面;
insertAll.jsp页面使用表单和forEach标签遍历学生信息列出所有学生信息,每个学生对应一个form表单,每个表单有一个提交按钮,点提交按钮可以向updateServlet提交当前学生的新数据;
updateServlet.java的逻辑就是从数据库中修改学生信息,如果修改成功了,返回修改成功的message,转发响应到showServlet,showServlet再获取所有用户信息,转发到insertAll.jsp页面,形成一个页面和servlet的周期循环。。。。反正用jsp和servlet跳来跳去,感觉很混乱。。

全部代码可以点击下载(仅供学习参考)👉,链接:https://pan.baidu.com/s/1Q6hY5RTZC1gJitt7zjAHhQ 提取码:Q9Jn
下载解压后,把Hello这个文件夹导入到Eclipse中,直接runserver运行就可以了,先确认数据库名字、账号密码,和数据表字段是不是和我的一样https://jingyan.baidu.com/article/46650658e8fb8bf549e5f835.html


就这样,浏览器端页面虽然比较丑,但是麻雀虽小,五脏俱全,主要是理解mvc吧,以后的javaWeb框架比如springmvc、springboot也都是mvc这种设计模式 Tomcat+Servlet+Sql,感觉完全可以开发一个小的毕设项目了。 jsp页面写得太烦了,各种代码杂糅在一起,现代人基本都不用了吧。现在比较流行前后端分离,后端返回数据接口,前端请求接口和渲染数据,

就这样,实验做完了要和jsp说拜拜了。
要考试了,博客暂时不更了,最后希望这篇博客对你有所帮助吧。

放两个资料,适用于考研和java校招,fighting!

关于后端java路径:

1.书籍,https://github.com/sorenduan/awesome-java-books
2.路径,https://github.com/xingshaocheng/architect-awesome

关于考研:

计算机408统考学长笔记(浙大版): 链接:https://pan.baidu.com/s/1gyPb3uWSSgNtx9ljYtoTvA 提取码:b924
计算机408思维导图: 链接:https://pan.baidu.com/s/1wtMM12SKeJyF22uwywePSw 提取码:791N

posted @ 2019-11-15 10:04  fishers  阅读(3216)  评论(3编辑  收藏  举报