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