JavaWeb
使用Java开发Web服务的技术,统称为JavaWeb。
B/S与C/S模式
B/S:Browser/Server 浏览器/服务器模式
用户只需要一个浏览器即可访问服务器
C/S:Clint/Server 客户端/服务器模式
用户需要下载客户端才能访问服务器
网站
用户通过浏览器访问某个域名或IP地址时,浏览到的综合性页面
实际就是发布在服务器上的一个应用程序,用户通过浏览器访问该程序。
网页
网站中的一个页面
静态页面:所有人看到的数据都一致
动态页面:不同的人看到的页面中的数据不一致
JavaWeb就是B/S模式下的软件开发,开发综合性的服务网站。
网络服务器
部署Web项目的平台。
Tomcat
由Apache、Sun和其他公司及个人共同开发的web服务器。
免费、开源、轻量级,在中小型系统中普遍被使用。
是开发和调试Web项目的首选。
下载
选择合适的版本下载。当前Java版本是1.8,所以选择9.x版本的tomcat下载
下载成功后,无需安装,直接解压到某个盘下即可。
解压后的目录
目录结构
目录名称 |
作用 |
bin |
保存一些tomcat相关的可执行文件,如startup.bat等 |
conf |
保存tomcat的配置文件,如server.xml中可以修改默认的端口号 |
lib |
保存tomcat运行时所需的jar文件 |
logs |
保存tomcat运行日志 |
temp |
保存tomcat运行时产生的临时文件 |
webapps |
保存发布在tomcat服务器上的应用程序 |
work |
保存tomcat运行时产生的编译后的文件 |
Maven
用于结构化管理jar文件的工具。
通过在Maven项目中加入某个jar文件的依赖,让其自动从Maven云仓库中下载对应的jar文件。
使用IDEA创建基于Maven的Web项目
1.新建webapp模板
2.设置项目名称和路径
3.设置Maven配置文件
Maven默认的配置文件会从官网下载jar文件,速度较慢,并且下载的jar文件默认会保存在c盘。
这里在D盘的根目录下新建了一个MavenRepository的本地仓库,用于保存下载的jar文件,并且设置国内的镜像下载。
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!--这个根路径可以更改-->
<localRepository>D:\MavenRepository\maven_jar</localRepository>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
<profiles>
</profiles>
</settings>
如果IDEA版本没有这个选项,暂时跳过,等待项目创建成功后进入主界面进行设置。
主界面进入设置
4.从Maven云仓库中搜索所需的jar文件
选择合适的版本
复制Maven依赖代码
5.粘贴到项目中的pom.xml文件中的dependencies标签中
如果下载失败,修改版本再次刷新尝试,如果一直不成功,删除groupId对应的本地目录后刷新尝试。
6.在src目录下新建编写类的java目录
7.修改项目的web.xml版本为4.0
8.配置tomcat服务器
9.部署创建好的项目到Tomcat服务器中
至此,启动tomcat服务器,会自动打开浏览器访问默认项目路径,项目自动打开会访问位于webapp目录下名为index的页面,如果没有index页面,会出现404页面,表示index页面不存在。
解决Tomcat控制台乱码
在文件的最后加入-Dfile.encoding=utf-8后重启
HTTP状态码
用特定数字表示状态。https://http.cat/
常见状态码 |
含义 |
200 |
成功 |
404 |
资源未找到 |
500 |
服务器内部错误 |
405 |
方法不允许 |
Servlet
Server+Applet 运行在服务器上的程序
编写Servlet的步骤
1.在项目中导入Servlet相关依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
2.在项目的java目录下,创建一个类,继承HttpServlet,重写doGet和doPost方法
通常用户无论发送的是get还是post请求,实际都会执行同一件事情。
为了不将代码重复写两遍,可以在doPost方法中调用doGet方法或在doGet方法中调用doPost方法
package com.hqyj.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* Servlet是运行在服务器上的应用程序
* 编写一个Servlet的步骤
* 1.创建一个类型,继承HttpServlet
* 2.重写doGet和doPost方法
* 3.在web.xml中设置请求该Servlet的URL地址
* */
public class FirstServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
//只需编写一遍代码
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
//为了不重复编写代码,在这get中调用post或在post中调用get
doPost(req, resp);
}
}
3.在web.xml中设置Servlet的请求映射
<!--声明一个Servlet-->
<servlet>
<!--自定义Servlet的名称-->
<servlet-name>firstServlet</servlet-name>
<!--Servlet类所在完整路径(全限定名)-->
<servlet-class>com.hqyj.servlet.FirstServlet</servlet-class>
</servlet>
<!--设置某个Servlet的请求映射-->
<servlet-mapping>
<!--指定要设置映射的Servlet-->
<servlet-name>firstServlet</servlet-name>
<!--设置请求映射,以/开头-->
<url-pattern>/first</url-pattern>
</servlet-mapping>
4.访问Servlet
至此,重启tomcat,访问"项目上下文地址/first",就表示访问FirstServlet类。
如果是通过浏览器地址栏访问,相当于get请求,执行servlet中的doGet方法
解决控制台打印中文乱码
三层架构
在软件开发中,并不是将所有功能都交给一个类去实现,而是要将其进行分层,从而达到"高内聚、低耦合"的目的。
低耦合是指降低各个模块之间的关联程度,这样便于开发和维护,每个模块各司其职。
高内聚是指每个模块内的功能不可再分。
比如要用积木拼出来一辆车,不要把所有积木放在一起拼,这样其中一部分出现问题,就会影响到其他地方。
最好的做法是先将车的各个组件拼接完成(解耦),每个组件都是完整的不可再分的整体(高内聚),最终再把各个组件拼接到一起。
这样便于发现问题解决问题,不影响其他模块。
通常所说的三层架构中的三层,是指“数据访问层、业务逻辑层和视图表现层”
数据访问层,用于连接数据库,对数据做增删改查的操作
业务逻辑层,用于处理业务逻辑,在适当的情况下调用数据访问层中的方法
视图表现层,用于展示数据和提供用户输入数据的渠道,在适当的情况下调用业务逻辑层中的方法
![](https://i-blog.csdnimg.cn/blog_migrate/64e25e073d3e5c889cd3ce45aaff0848.jpeg)
访问服务器的某个URL
在浏览器的地址栏中输入对应的URL,属于GET提交
使用a标签,在href中输入对应的URL,属于GET提交
使用form表单,在action中输入对应的URL,通过method修改提交方式为GET或POST
页面向服务端提交数据的方式
使用form表单的name属性显示提交
<form action="http://localhost:8080/day1/hero" method="get">
<input type="text" name="username">
<input type="submit">
</form>
提交的数据会暴露在浏览器的地址栏中
使用form表单的name属性隐式提交
<form action="http://localhost:8080/day1/hero" method="post">
<input type="text" name="username">
<input type="submit">
</form>
提交的数据不会暴露在浏览器的地址栏中
通过"?参数名=值"方式提交
在地址栏中输入URL的时候,末尾加入这部分
https://www.baidu.com/s?wd=hello
在a标签的href属性中加入这部分,如果有多个参数,通过&拼接
<a href="https://www.baidu.com/s?wd=hello&a=1&b=2">访问</a>
服务器端获取页面传递的数据
以上任何方式提交到服务器的数据,都可以使用以下方式获取。
String str=request.getParameter("name名或?后的参数名");
class TestServlet extends HttpServlet{
doGet(HttpServletRequest req,HttpServletResponse resp){
//获取表单提交的数据req.getParameter("表单中某个表单元素的name值");
String username = req.getParameter("username");
}
doPost(HttpServletRequest req,HttpServletResponse resp){
doGet();
}
}
表单提交数据注意事项
表单通过action提交设置的路径,如果要在路径中传递参数,只能使用post方式提交
<form action="xxxxx?参数=值" method="post">
</form>
使用get方式提交,无法识别action路径中的参数,如果要传递参数,使用隐藏域
<form action="xxxxx" method="get">
<input type="hidden" name="参数名" value="参数值">
</form>
解决请求和响应的中文乱码
//在servlet的doGet或doPost所有代码之前中加入
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
使用Servlet实现单表的增删改查
数据库脚本文件
/*
Navicat Premium Data Transfer
Source Server : localhost_3306
Source Server Type : MySQL
Source Server Version : 80029
Source Host : localhost:3306
Source Schema : gamedb
Target Server Type : MySQL
Target Server Version : 80029
File Encoding : 65001
Date: 03/01/2023 14:46:16
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for hero
-- ----------------------------
DROP TABLE IF EXISTS `hero`;
CREATE TABLE `hero` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '姓名',
`position` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '定位',
`sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '男' COMMENT '性别',
`price` int NOT NULL DEFAULT 4800 COMMENT '价格',
`shelf_date` date NULL DEFAULT NULL COMMENT '上架日期',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
实体类entity
实体的属性名保持和表的字段名一致,使用驼峰命名法
package com.hqyj.entity;
public class Hero {
private int id;
private String name;
private String position;
private String sex;
private int price;
private String shelfDate;
/*
全参构造方法用于查询
*/
public Hero(int id, String name, String position, String sex, int price, String shelfDate) {
this.id = id;
this.name = name;
this.position = position;
this.sex = sex;
this.price = price;
this.shelfDate = shelfDate;
}
/*
不带id的构造方法用于添加
*/
public Hero(String name, String position, String sex, int price, String shelfDate) {
this.name = name;
this.position = position;
this.sex = sex;
this.price = price;
this.shelfDate = shelfDate;
}
//省略get/set/toString
}
数据操作类dao
package com.hqyj.dao;
import com.hqyj.entity.Hero;
import com.hqyj.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class HeroDao {
Connection conn;
PreparedStatement pst;
ResultSet rs;
/*
* 查询所有
* */
public List<Hero> queryAll() {
ArrayList<Hero> list = new ArrayList<>();
conn = DBUtil.getConn();
try {
pst = conn.prepareStatement("select * from hero");
rs = pst.executeQuery();
while (rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
String position = rs.getString(3);
String sex = rs.getString(4);
int price = rs.getInt(5);
String shelfDate = rs.getString(6);
Hero hero = new Hero(id, name, position, sex, price, shelfDate);
list.add(hero);
}
} catch (Exception e) {
System.out.println("查询所有异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return list;
}
/*
* 添加
* */
public boolean addHero(Hero hero) {
conn = DBUtil.getConn();
String sql = "insert into hero values(null,?,?,?,?,?)";
try {
pst = conn.prepareStatement(sql);
pst.setString(1, hero.getName());
pst.setString(2, hero.getPosition());
pst.setString(3, hero.getSex());
pst.setInt(4, hero.getPrice());
pst.setString(5, hero.getShelfDate());
return pst.executeUpdate() > 0;
} catch (SQLException e) {
System.out.println("添加异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return false;
}
/*
* 删除
* */
public boolean delete(int id) {
conn = DBUtil.getConn();
try {
pst = conn.prepareStatement("delete from hero where id=?");
pst.setInt(1, id);
return pst.executeUpdate() > 0;
} catch (SQLException e) {
System.out.println("删除异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return false;
}
/*
* 根据id查询
* */
public Hero findById(int id) {
conn = DBUtil.getConn();
try {
pst = conn.prepareStatement("select * from hero where id=?");
pst.setInt(1, id);
rs = pst.executeQuery();
if (rs.next()) {
String name = rs.getString(2);
String position = rs.getString(3);
String sex = rs.getString(4);
int price = rs.getInt(5);
String shelfDate = rs.getString(6);
Hero hero = new Hero(id, name, position, sex, price, shelfDate);
return hero;
}
} catch (Exception e) {
System.out.println("根据id查询异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return null;
}
/*
* 修改
* */
public boolean update(Hero updateHero) {
conn = DBUtil.getConn();
try {
pst = conn.prepareStatement("update hero set name=?,position=?,sex=?,price=?,shelf_date=? where id=?");
pst.setString(1, updateHero.getName());
pst.setString(2, updateHero.getPosition());
pst.setString(3, updateHero.getSex());
pst.setInt(4, updateHero.getPrice());
pst.setString(5, updateHero.getShelfDate());
pst.setInt(6, updateHero.getId());
return pst.executeUpdate() > 0;
} catch (SQLException e) {
System.out.println("修改异常" + e);
} finally {
DBUtil.release(conn, pst, rs);
}
return false;
}
}
控制层/表现层servlet
package com.hqyj.servlet;
import com.hqyj.dao.HeroDao;
import com.hqyj.entity.Hero;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServl