躬自厚而薄责于人,则远怨矣。 ——《论语》
前言:个人学习内容,记录一下,略显粗浅。
准备:了解前端知识,并下安装好Tomcat,若没有请看上一篇:
Tomcat下载和安装
一、写个servlet
1.先新建个web工程
1.1 先选择web Application 4.0,再选择web服务器
1.2 选择已经下载安装好的Tomcat服务器,并点击OK
1.3 如下,点击next
1.4 创建好项目结构如下
1.5 查看Tomcat配置,一般默认好了,需要修改下访问路径
1.6 点击Deployment,删除下方Application context的路径,然后Apply
启动Tomcat会自动访问index.jsp这个文件路径
1.7 创建一个sevlet文件HelloServlet
1.8 继承于HttpServlet,重写deGet()/doSet()方法
1.9 把 @WebServlet(name = “HelloServlet”) 改成 @WebServlet("/HelloServlet")
1.10 运行Tomcat
1.11 可以看到你的环境配置的信息
这里显示连接成功
1.12 然后会自动访问http://localhost:8080/,其实就是项目里的index.jsp文件
1.13 访问刚才创建的HelloServlet
二、Servlet知识点简单了解
1.web发展
静态web:web服务器是做文件共享的服务器 客户端访问时,请求的就是文件本身动态web:客户端请求时,请求的是一个应用程序,通过这个应用程序给出响应的
2.web服务器
用来管理静态文件还有程序的,让客户端可以通过一个url进行访问
3.Tomcat
Tomcat:web服务器(web容器)
目录:
bin 可执行的程序
conf 配置文件
server.xml 中修改端口号
< Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" / >
lib tomcat的运行环境(java ee程序的环境)
logs tomcat的运行日志
temp 临时文件
webapps 保存web的程序的目录
work tomcat工作中生成的文件的保存目录
发布工程:将编译之后的java工程发布到tomcat的webapps目录的过程
4.Servlet
以单实例多线程运行在服务端的一个java程序
4.1 创建
1. 自定义类 implements Servlet 重写方法
2. 自定义类 extends GenericServlet 重写service方法
3. (以后用这种)自定义类 extends HttpServlet 提供了和http协议相关的一些方法
重写doGet/doPost方法
5.给servlet配置映射路径:
1.注解 @WebServlet("/servlet")
创建好servlet文件,默认的时是name=“servlet”,需要修改一下,2种方式:
2.配置web.xmlbian(太麻烦了,以后都用注解多方便)
web.xml中配置:
<servlet>
<servlet-name>自定义名字</servlet-name>
<servlet-class>servlet的完整类名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>自定义名字</servlet-name>
<url-pattern>/url</url-pattern>
</servlet-mapping>
6.Servlet的生命周期
1.初始化阶段(对象的创建)
默认情况下 客户端第一次去访问servlet时,创建servlet对象,并且调用init方法。
也可以配置num配置 web服务器开启时 直接创建对象 调用init方法啊。
servlet对象谁创建的?
web容器创建
怎么创建的?
反射
2.运行阶段
每次请求servlet时,调用service方法,再根据请求方法(get/post)的不同,分别调用doGet或者doPost方法。 用来处理请求并且给出响应。
3.销毁阶段
web服务器正常关闭时,servlet对象被销毁,销毁之前调用destory方法。
7.接收客户端信息
客户端提交数据至服务端方法:
先写一个页面 form表单 submit按钮提交至servlet的程序
直接访问servlet程序?参数=值&参数=值
单一获取(名字若重复,取第一个值):
String value = request.getParameter(“name”);
多个获取(名字相同,但值有多个):
String[] values = request.getParameterValues(“name”);
全部获取:
Map<String,String[]> map = request.getParameterMap();
8. get请求和post请求
http协议请求方法
get 默认请求方法
调用servlet的doGet方法
请求参数以?参数名=参数值&参数名=参数值… 形式拼接在url的后面 请求参数个数有限的。
一些关键的参数值会保留在历史记录中不安全的。
主要用于获取服务端的结果 一般是用于查询操作(登录除外)。
post
调用servlet的doPost方法
请求参数是放在请求体中 参数的个数无要求的
请求参数是不会保留在历史记录中的安全的
主要用于提交数据至服务端的 而这些数据会对数据库中的表进行修改操作的(增删改)。
9.响应方式
1.response.getWriter()
2.请求转发(服务端跳转) request.getRequestDispatcher(“url”).forword(request,response)
一次请求 路径不发生变化
只能转发本服务器中的请求
可以请求/WEB-INF目录下文件
可以使用request作用域传值
3.重定向(客户端跳转)
response.sendRedirect(“url”);
两次请求 路径发生改变
可以转发服务器外部请求
不可以请求/WEB-INF目录下文件
不可以使用request作用域传值
10. 三大作用域
用于服务端保存数据
request --> HttpServletRequest 一次请求有效
session --> HttpSession 一次会话有效(登录后保存登录用户的)
application --> ServletContext 全局作用域//保存属性
setAttribute(String name,Object value)
//获取属性
Object value = getAttribue(String name)
removeAttribute(String name)
11.cookie和session
cookie:由服务端保存在客户端的信息 key-value
保存在客户端
有效期:默认是一次会话(浏览器打开开始访问->浏览器窗口关闭)
可以调用setMaxAge(int seconds)设置cookie的有效期
response.addCookie()台南佳cookie
有效路径:默认写入cookie的路径的当前目录以及子目录
可以调用setPath("")方法设置路径
session:服务端的HttpSession对象
保存在服务端的
有效期:一次会话 session对象存活时间默认是30分钟 可以配置
12.servlet的线程安全问题
servlet线程安全吗?
不安全
为什么不安全?
因为单实例多线程的
怎么解决?
不要修改全局变量
servlet的属性
在方法中使用的全局变量 session application
一定要修改全局变量时,一定要做好线程同步或者使用线程安全的类
三、简单的登录功能
先演示一下效果:(很简陋,莫笑~)
项目结构:
前端部分:因为没学Jsp,就写html
1.客户端解决表单重复提交问题
在单击提交按钮以后,将提交按钮设置为disabled:true不可用状态,还可以另外增加友好提醒
2.表单数据校验
客户端校验
服务端校验
注册register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
<title>注册</title>
<!--
1.客户端解决表单重复提交问题
在单击提交按钮以后,将提交按钮设置为disabled:true不可用状态,还可以另外增加友好提醒
2.表单数据校验
客户端校验
服务端校验
-->
<script type="text/javascript">
function check() {
//客户端校验
var username = $("[name=username]").val();
var password = $("[name=password]").val();
//username 6-18位 汉字、数字、字母、下划线不能以下划线开头和结尾
if(!/^(?!_)(?!.*?_$)[a-zA-Z0-9_u4e00-u9fa5]/.test(username)){
$("#subInfo").text("用户名不合法,要求 汉字、数字、字母、下划线不能以下划线开头和结尾");
return false;//不提交表单
}
//password 6-18位 非空字符
if(!/^S{6,18}$/.test(password)){
$("#subInfo").text("密码不合法,要求6-18位非空字符");
return false;
}
$("#regBtn").attr("disabled",true);//将submit按钮变为不可用
return true;//一定要添加上return true
}
</script>
</head>
<body>
<!-- onsubmit事件 可以控制要不要提交表单 如果方法返回true 提交 返回false 不提交 -->
<form method="post" action="register" onsubmit="return check()">
<span id="subInfo" style="color:red"></span><br/>
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="注册" id="regBtn"/><br/>
</form>
<div>
<a href="login.html">若已注册,请返回登录</a>
</div>
</body>
</html>
登录login.thml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<body>
<form method="post" action="login">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="checkbox" name="rememberMe" value="1" />记住<br/>
<input type="submit" value="登录"/><br/>
</form>
<div>
<a href="register.html">若未注册,请先注册</a>
</div>
</body>
</body>
</html>
首页HomePage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h3>登录成功!欢迎来到~德莱联盟!</h3>
</body>
</html>
数据库部分
建立数据库,建表,
create table users(
id int auto_increment,
username varchar(20) not null,
password varchar(50),
primary key(id)
)default charset=utf8 ;
后端部分
记得导连接数据库的JAR包
util工具类:连接数据库以及关闭连接
package priv.study.util;
import java.sql.*;
/**
* Description:连接Mysql数据库工具类
*
* @author JiangYuhan
* @Date 2020/12/01 21:46
* @since JDK 1.8
*/
public class JdbcUtil {
/**
* @description: 连接数据库
* @param: []
* @return: java.sql.Connection
* @author: JiangYuhan
* @Date: 2020/12/02 21:08
*/
public static Connection getConnection() throws ClassNotFoundException {
String driver ="com.mysql.cj.jdbc.Driver";
Class.forName(driver);
String url ="jdbc:mysql://127.0.0.1:3306/study?characterEncoding=UTF-8 && serverTimezone=GMT";
String user ="root";
String password = "123456";
Connection con=null;
try{
con = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
System.out.println("与数据库连接失败");
e.printStackTrace();
}
return con;
}
/**
* @description: //与数据库连接关闭(增删改查方法里使用try-with-resources语句,会自动关闭连接,但是无法用于数据库连接池)
* @param: [con, ps]
* @return: void
* @author: JiangYuhan
* @Date: 2020/12/02 21:09
*/
public static void close(Connection con, PreparedStatement ps) {
try{
if(ps!=null) {
ps.close();
}
if(con!=null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection con, PreparedStatement ps, ResultSet rs) {
try {
if(rs!=null) {
rs.close();
}
if(ps!=null) {
ps.close();
}
if(con!=null) {
con.close();
}
} catch (SQLException e) {
System.out.println("关闭失败");
e.printStackTrace();
}
}
}
model包的里User类
package priv.study.model;
import java.io.InputStream;
/**
* Description:用户表,参数:username,password
*
* @author JiangYuhan
* @Date 2020/12/01 21:24
* @since JDK 1.8
*/
public class User {
private Integer id;
private String username;
private String password;
public User() {
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + ''' +
", password='" + password + ''' +
'}';
}
}
接口Dao和实现类UserDao
package priv.study.dao;
import priv.study.model.User;
/**
* Description:实现方法接口
*
* @author JiangYuhan
* @Date 2020/12/01 21:28
* @since JDK 1.8
*/
public interface Dao {
public User select(String username,String password);
public int insert(String username,String password);
}
package priv.study.dao;
import priv.study.model.User;
import priv.study.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Description:实现Dao接口,重写其中的方法
*
* @author JiangYuhan
* @Date 2020/12/01 21:32
* @since JDK 1.8
*/
public class UserDao implements Dao{
/**
* @description: 判断用户是否已经注册,参数:用户名,密码,返回用户信息
* @param: [username,password]
* @return: User
* @author: JiangYuhan
* @Date: 2020/12/01 21:35
*/
@Override
public User select(String username,String password) {
User user = null;
String sql = "select * from users where username= ? and password= md5(?)";
try (Connection con = JdbcUtil.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1,username);
ps.setString(2,password);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
String pass= rs.getString(3);
user = new User(id,name,pass);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
@Override
/**
* @description: 把用户的注册信息插入数据库
* @param: [username, password]
* @return: int
* @author: JiangYuhan
* @Date: 2020/12/01 23:13
*/
public int insert(String username, String password) {
int rows=0;
String sql = "insert into users values(null,?,md5(?))";
try (Connection con = JdbcUtil.getConnection();
PreparedStatement ps = con.prepareStatement(sql)){
ps.setString(1,username);
ps.setString(2,password);
rows = ps.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return rows;
}
}
servlet类业务逻辑
package priv.study.servletdemo;
import priv.study.dao.UserDao;
import priv.study.model.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Description:
*
* @author JiangYuhan
* @Date 2020/12/01 20:21
* @since JDK 1.8
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
/**
* @description: 用户表单提交登录
* @param: [request, response]
* @return: void
* @author: JiangYuhan
* @Date: 2020/12/01 22:39
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset = utf-8");
//1.获取客户端提交的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String rememberMe = request.getParameter("rememberMe");
System.out.println(username);
System.out.println(password);
//2.数据校验
//3.数据库查询
User user = new UserDao().select(username, password);
if (user != null) {
//记录用户的登录状态
request.getSession().setAttribute("user", user);
//前提是一定是登录成功的情况下才能写cookie
//创建cookie对象
Cookie cookieUsername = new Cookie("username", username);
Cookie cookiePassword = new Cookie("password", password);
String rem = "1";
if (rem.equals(rememberMe)) {
//cookie信息的有效期,秒为单位
cookieUsername.setMaxAge(60 * 60 * 24 * 3600);
cookiePassword.setMaxAge(60 * 60 * 24 * 3600);
response.addCookie(cookieUsername);
response.addCookie(cookiePassword);
}
//写到客户端 cookie是以响应头的形式写入到客户端的
response.sendRedirect("/HomePage.html");
} else {
PrintWriter out = response.getWriter();
out.print("用户名不存在或者密码错误!");
out.flush();
out.close();
}
}
}
package priv.study.servletdemo;
import priv.study.dao.UserDao;
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.io.PrintWriter;
/**
* Description:
*
* @author JiangYuhan
* @Date 2020/12/01 23:06
* @since JDK 1.8
*/
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
/**
* @description: 获取用户注册信息,并注册
* @param: [request, response]
* @return: void
* @author: JiangYuhan
* @Date: 2020/12/01 23:07
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset = utf-8");
//1.获取客户端提交的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
//2.数据校验
//3.数据库插入
int rows = new UserDao().insert(username,password);
if (rows > 0) {
//记录用户的登录状态
request.getSession().setAttribute("username", username);
//把首页响应给客户端
response.sendRedirect("/HomePage.html");
} else {
PrintWriter out = response.getWriter();
out.print("注册失败");
//重新注册
response.sendRedirect("/register.html");
out.flush();
out.close();
}
}
}
还想了解更多:Java自学网站
今天学习分享的内容到此为止了,本是想要激励自己学下去,但发现快乐更是知识在于分享!
作为初学者对于Java的理解实在浅薄,如有错误请指正,万分感谢!