Java学习——servlet简单学习

躬自厚而薄责于人,则远怨矣。 ——《论语》

前言:个人学习内容,记录一下,略显粗浅。

准备:了解前端知识,并下安装好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") ,这就是HelloServlet的映射路径,不需要配置web.xml。然后在doGet()里输出一句"Hello Servlet !!!"

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的理解实在浅薄,如有错误请指正,万分感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值