Tomcat给java提供的原生的进行web开发的api。
网页分为静态页面和动态页面。
静态页面:页面内容始终是固定不变的。
动态页面:页面内容随着输入参数的不同而改变。
第一个Servlet程序:
1.创建项目
首次使用maven会从中央仓库下载一些依赖,耐心等待,或者配置国内镜像。
2.引入依赖
Maven Repository: servlet (mvnrepository.com)
找到3.x版本,该版本和tomcat8.x版本匹配:
复制上述代码,将其复制到项目中的porm.xml配置文件中:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
4.编写代码
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("hello");
}
}
5.打包程序
在porm.xml文件中修改配置:
找到图示打包程序,双击运行,或者右键点击运行:
打包成功:
左侧target目录下生成刚才打好的包:
6.部署
将刚才的war包复制到tomcat的webapps目录下,启动tomcat。
7.验证
使用IDEA上的插件,简化上述步骤,方便开发阶段进行验证:
1.新增一个运行时配置
2.设置tomcat所在的路径:
3.运行
如果运行产生乱码问题,修改编码格式:
验证:
查看端口使用进程:
Servlet常用api介绍:
servlet生命周期:
开始的时候,执行init()方法;每次收到请求的时候,执行service();销毁之前,执行destroy()。
另外几种方法的测试:
@WebServlet("/method")
public class MethodServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
resp.getWriter().write("doGet");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPut");
resp.getWriter().write("doPut");
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doDelete");
resp.getWriter().write("doDelete");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost");
resp.getWriter().write("doPost");
}
}
构造http请求:
1.使用postman
2.ajax()
HttpServletRequest介绍:
示例:
```
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置返回数据的格式
resp.setContentType("text/html");
//用stringBuilder将api返回结果拼装起来,并返回到页面
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(req.getMethod());
stringBuilder.append("<br>");
stringBuilder.append(req.getProtocol());
stringBuilder.append("<br>");
stringBuilder.append(req.getRequestURI());
stringBuilder.append("<br>");
stringBuilder.append(req.getContextPath());
stringBuilder.append("<br>");
stringBuilder.append(req.getQueryString());
stringBuilder.append("<br>");
stringBuilder.append("<br>");
stringBuilder.append("<br>");
stringBuilder.append("<br>");
//获取到header(报头)中的每一个键值对
Enumeration<String> Headers = req.getHeaderNames();
while(Headers.hasMoreElements()){
String head = Headers.nextElement();
//req.getHeader() 传入key,获得对应的value
stringBuilder.append(head + ": " + req.getHeader(head) +"<br>");
}
resp.getWriter().write(stringBuilder.toString());
}
}
```
运行结果:
前端给后端传参的方式:
1.通过get方法里的query string来传递:
示例:学生id和老师id studentId=10&teacherId=20
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
StringBuilder stringBuilder = new StringBuilder();
/*//通过queryString字符串获取
String queryString = req.getQueryString();
String[] strings = queryString.split("&");
//获取学生id
String[] student = strings[0].split("=");
String studentId = student[1];
stringBuilder.append(studentId);
stringBuilder.append("<br>");
//获取老师id
String[] teacher = strings[1].split("=");
String teacherId = teacher[1];
stringBuilder.append(teacherId);
stringBuilder.append("<br>");*/
//通过参数获取
String studentId = req.getParameter("studentId");
String teacherId = req.getParameter("teacherId");
resp.getWriter().write("studentId" + "=" + studentId + " " + "teacherId" + "=" + teacherId);
}
}
运行结果:
2.通过post方法,form表单来传递数据
@WebServlet("/postParameter")
public class PostParameter extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
StringBuilder stringBuilder = new StringBuilder();
String studentId = req.getParameter("studentId");
String teacherId = req.getParameter("teacherId");
resp.getWriter().write("studentId" + "=" + studentId + " " + "teacherId" + "=" + teacherId);
}
}
3.通过post方法,json格式来传递数据
json格式:
{ "classId":10, "teacherId":20 }
@WebServlet("/postParameter2")
public class PostParameter2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取到整个body的内容,并将其返回到页面
//得到body中内容的长度
int length = req.getContentLength();
byte[] buffer = new byte[length];
InputStream inputStream = req.getInputStream();
inputStream.read(buffer);
String string = new String(buffer,0,length,"utf8");
resp.getWriter().write(string);
}
}
通过postman发送数据:
通过ajax()发送:
运行结果:
刚才的代码得到的是整个json,并没有获得键值对,我们通过第三方库jackson来解析json数据:
1)引入依赖:
maven仓库中找到依赖
将其复制到porm.xml文件中:
修改代码:
类中的属性名必须和json中的键值对一一匹配,不一致时会报错:
HttpServletResponse介绍:
代码示例:服务器版的表白墙
创建新的maven项目,从maven仓库导入servlet,jackson,mysql依赖:
创建目录:
加入配置文件:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
添加服务器:
导入前端代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表白墙</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container{
width: 600px;
margin: 0 auto;
}
h1{
margin-top: 10px;
text-align: center;
}
p{
margin: 10px 0;
color: #666;
text-align: center;
}
.row{
display: flex;
justify-content: center;
align-items: center;
height: 40px;
}
.row span{
align-items: center;
width: 80px;
}
.row input{
width: 200px;
height: 30px;
}
button{
color: white;
background-color: orange;
width: 280px;
height: 34px;
border: none;
border-radius: 5px;
}
button:active{
background-color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>表白墙</h1>
<p>输入内容后点击提交按钮,内容将显示在网页中</p>
<div class="row">
<span>谁:</span>
<input type="text" class="input1">
</div>
<div class="row">
<span>对谁:</span>
<input type="text" class="input2">
</div>
<div class="row">
<span>说什么:</span>
<input type="text" class="input3">
</div>
<div class="row">
<button id="submit">提交</button>
</div>
<div class="row">
<button id="reverse">撤销</button>
</div>
</div>
<script>
let containerDiv = document.querySelector('.container');
let button = document.querySelector('#submit');
button.onclick = function(){
//获取输入框的内容
let inputs = document.querySelectorAll('input');
let from = inputs[0].value;
let to = inputs[1].value;
let message = inputs[2].value;
//输入框有一个为空直接结束
if(from == '' || to == '' || message == ''){
return;
}
//构造新输出
let resultDiv = document.createElement('div');
resultDiv.className = 'row message';
resultDiv.innerHTML = from + ' 对 ' + to + ' 说:' + message;
containerDiv.appendChild(resultDiv);
//清空输入框
for(let elem of inputs){
elem.value = '';
}
}
//撤销
let reverse = document.querySelector('#reverse');
reverse.onclick = function(){
let outputs = document.querySelectorAll('.message');
containerDiv.removeChild(outputs[outputs.length - 1]);
}
</script>
</body>
</html>
前后端约定,以json字符串来发送数据,Post方法向后端发送数据并存储到数据库中,Get方法查询数据库,得到数据返回给前端。
1.修改前端代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表白墙</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container{
width: 600px;
margin: 0 auto;
}
h1{
margin-top: 10px;
text-align: center;
}
p{
margin: 10px 0;
color: #666;
text-align: center;
}
.row{
display: flex;
justify-content: center;
align-items: center;
height: 40px;
}
.row span{
align-items: center;
width: 80px;
}
.row input{
width: 200px;
height: 30px;
}
button{
color: white;
background-color: orange;
width: 280px;
height: 34px;
border: none;
border-radius: 5px;
}
button:active{
background-color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>表白墙</h1>
<p>输入内容后点击提交按钮,内容将显示在网页中</p>
<div class="row">
<span>谁:</span>
<input type="text" class="input1">
</div>
<div class="row">
<span>对谁:</span>
<input type="text" class="input2">
</div>
<div class="row">
<span>说什么:</span>
<input type="text" class="input3">
</div>
<div class="row">
<button id="submit">提交</button>
</div>
<div class="row">
<button id="reverse">撤销</button>
</div>
</div>
<!-- 引入jquery -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
let containerDiv = document.querySelector('.container');
let button = document.querySelector('#submit');
button.onclick = function(){
//获取输入框的内容
let inputs = document.querySelectorAll('input');
let from = inputs[0].value;
let to = inputs[1].value;
let message = inputs[2].value;
//输入框有一个为空直接结束
if(from == '' || to == '' || message == ''){
return;
}
//构造新输出
let resultDiv = document.createElement('div');
resultDiv.className = 'row message';
resultDiv.innerHTML = from + ' 对 ' + to + ' 说:' + message;
containerDiv.appendChild(resultDiv);
// [新增部分]将数据传送给后端
let body = {
from:from,
to:to,
message:message
}
$.ajax({
type:'post',
url:"message",
//将js对象转为json字符串
contentType:'applocation/json;charset=utf8',
data:JSON.stringify(body),
success:function(body){
}
})
//清空输入框
for(let elem of inputs){
elem.value = '';
}
}
//撤销
let reverse = document.querySelector('#reverse');
reverse.onclick = function(){
let outputs = document.querySelectorAll('.message');
containerDiv.removeChild(outputs[outputs.length - 1]);
$.ajax({
type:'delete',
url:'message',
success:function(body){
}
})
}
//[新增部分]刷新页面时从服务器获取数据并显示
$.ajax({
type:'get',
url:'message',
success:function(body){
//此处的body就是从服务器获得的json字符串,jquery的ajax可以自动将其转为js对象
for(let message of body){
let containerDiv = document.querySelector('.container');
let resultDiv = document.createElement('div');
resultDiv.className = 'row message';
resultDiv.innerHTML = message.from + ' 对 ' + message.to + ' 说:' + message.message;
containerDiv.appendChild(resultDiv);
}
}
})
</script>
</body>
</html>
2.创建数据库并包装数据库
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: ZWQ
* Date: 2023-08-15
* Time: 16:25
*/
public class DBUtil {
//实现对数据库的封装
private static DataSource dataSource = new MysqlDataSource();
static{
//数据库初始化
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java106?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
```
```
3. 后端代码
import com.fasterxml.jackson.databind.ObjectMapper;
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 java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;
/**
- Created with IntelliJ IDEA.
- Description:
- User: ZWQ
- Date: 2023-08-15
- Time: 15:59 */
@WebServlet("/message") public class WallServlet extends HttpServlet { private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//该方法主要是从数据库中查询数据并返回给前端页面
resp.setContentType("application/json; charset=utf8");
objectMapper.writeValue(resp.getWriter(),load());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//该方法主要是向数据库存数据
//将前端给的json字符串转为message对象
Message message = objectMapper.readValue(req.getInputStream(),Message.class);
save(message);
resp.setStatus(200);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
//数据库增加代码
private void save(Message message){
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "insert into message values(?,?,?)";
statement = connection.prepareStatement(sql);
//第一个参数对应占位符的位置,第二个参数是要插入的数据
statement.setString(1,message.from);
statement.setString(2,message.to);
statement.setString(3,message.message);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
//数据库查询代码
private List<Message> load(){
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Message> messageList = new ArrayList<>();
try {
connection = DBUtil.getConnection();
String sql = "select * from message";
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while(resultSet.next()){
Message message = new Message();
message.from = resultSet.getString("from");
message.to = resultSet.getString("to");
message.message = resultSet.getString("message");
messageList.add(message);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return messageList;
}
}
class Message{ public String from; public String to; public String message; }
Session
session是服务器的存储机制,专门用来存储用户的身份信息。