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

余生长醉 提交于 2020-05-07 17:48:13

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

<br /> 右侧目录,可以根据进度跳转,<a href="https://www.cnblogs.com/fisherss/p/11864592.html#%E6%AD%A3%E5%BC%8F%E5%86%99%E4%BB%A3%E7%A0%81%E5%90%A7">正式代码部分点这里。</a>

#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按照这个博客<a target="_blank" href="https://blog.csdn.net/yerenyuan_pku/article/details/51830104">这个博客链接</a>就可以啦。 完全按照这个博客写的一步一步做就可以了,https://blog.csdn.net/yerenyuan_pku/article/details/51830104 上面做完后,用浏览器可能会访问你的网页可能出现404错误码,他的博客没有说清楚,👇

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

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

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

右键你的项目包,新建,选择servlet。 输入名字后,直接点击Finish,自动生成了servlet文件 <br />

Servlet,其实只需要重写doGet方法,把想要的数据加入到response对象中就可以了 比如我append了这么一句话,"My First Hello world page2333" 然后启动servlet,打开浏览器,就可以通过url访问你的servlet了

有可能又出现了404👇 <br /> 只需要把url地址链接改成 http://localhost:8080/项目名/selvert名/

#把Servlet和jsp页面相关联 通过Servlet可以返回你想要的数据到Response对象中; 所以只需要在doGet中,调用实验四的JDBC连接数据库,把获取到数据库的数据,append加入到response对象中就可以了。 然后应该还要把response对象中的数据展示到JSP页面中。 <br /> 如何把Servlet与JSP页面连接起来呢?也就是如何把response对象中的数据展示到JSP页面中? 比如我想把自己写的Servlet中的,doGet函数获得的数据,返回到JSP静态页面,交给自己编写的学生信息展示JSP静态页面展示数据,该怎么做? 1.需要先用request.setAttribute设置要传递的数据, 2.然后在Servlet使用RequestDispatcher接口来传递数据了,RequestDispatcher可以把响应工作(如展示学生信息)派发给jsp页面、其它Servlet、或者Html页面等。 <a href="https://www.cnblogs.com/lulipro/p/7471987.html" target="_blank">点这篇博客,把RequestDispatcher原理和应用讲解的很清楚了</a> <br />

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

###一个简单的测试代码:servlet把一个学生的数据从数据库取出,向jsp页面传递学生数据,jsp页面展示该学生信息 在selvert的doGet函数中请求<a href="https://www.cnblogs.com/fisherss/p/11831089.html" target="_blank">实验四的students数据库</a>,转发数据到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个学生数据的信息。 <br /> ###需要用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文件夹里 <br /> 怎么找到网站项目目录呢? <br /> 进入属性窗口,可以看到目录了,点击就能进入项目目录了,把这两个jar文件放在项目目录的WEB-INF/lib文件夹里

<br /> 然后在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

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

SQL Server的数据库是这样的👇

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

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

Eclipse截图👇 <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中部分截图如下👇 <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如何接收的可以看第四步

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

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix= "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>需求一:添加一个同学的信息</title>
</head>
<body>
<form action="firstServlet" method="post" >
	学号:<input type="text" name = "sno" title="填写学号"></input>
	<br/>
	姓名:<input type="text" name = "name" title="填写姓名"></input>
	<br/>
	性别:<input type="radio" name = "ssex" value="boy" title="填写性别"></input>
			<input type="radio" name = "ssex" value="girl" title="填写性别"></input>
	<br/>
	成绩:<input type="text" name = "score" title="分数"></input>
	<br/>
	<input type="submit" value="提交"/> 
</form>
</body>
</html>

##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跳来跳去,感觉很混乱。。 <br />

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

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

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

放两个资料~,适用于考研和java校招,fighting!~ ###关于后端java路径: 1.<a href="https://github.com/sorenduan/awesome-java-books" target="_blank">书籍,</a>https://github.com/sorenduan/awesome-java-books
2.<a href="https://github.com/xingshaocheng/architect-awesome" target="_blank">路径,</a>https://github.com/xingshaocheng/architect-awesome ###关于考研: <a href="https://pan.baidu.com/s/1gyPb3uWSSgNtx9ljYtoTvA" target="_blank">计算机408统考学长笔记(浙大版):</a> 链接:https://pan.baidu.com/s/1gyPb3uWSSgNtx9ljYtoTvA 提取码:b924 <a href="https://pan.baidu.com/s/1wtMM12SKeJyF22uwywePSw" target="_blank">计算机408思维导图:</a> 链接:https://pan.baidu.com/s/1wtMM12SKeJyF22uwywePSw 提取码:791N

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!