Java学习 Servlet

常见服务器

开源:

  • Tomcat
  • jetty
  • resin

收费:

  • WebLogic(oracle)
  • WebSphere(IBM)

Servlet

Servlet∶

  • ServerApplet的简称,是服务器端的程序(代码、功能实现),可交互式的处理客户端发送到服务端的请求,并完成操作响应。
  • 动态网页技术
  • JavaWeb程序开发的基础,JavaEE规范(一套接口)的一个组成部分。

作用

  • 接收客户端请求,完成操作。
  • 动态生成网页(页面数据可变)
  • 将包含操作结果的动态网页响应给客户端。

编写

实现Servlet接口,重写 init(ServletConfig servletConfig) throw ServletException,service(ServletRequest request,ServletResponse response) throws ServletException,IOException,destroy,getServletConfig,getServletInfo方法

配置

配置web.xml

<servlet>
	<servlet-name>别名</selvet-name>
	<servlet-class>类名</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>和上面的别名一致</servlet-name>
	<url-pattern>/myservlet(将来要访问的路径)</url-pattern>
</servlet-mapping>

HTTP协议

什么是HTTP协议

超文本传输协议(HTTP,HyperText TansferProtocol)是互联网上应用最为广泛的一种网络协议,是一个基于请求与响应模式的、无状态的、应用层的协议,运行于TCP协议基础之上。

特点

在这里插入图片描述

流程

  • 客户与服务器建立连接(三次握手)。
  • 客户向服务器发送请求。
  • 服务器接受请求,并根据请求返回相应的文件作为应答。
  • 客户与服务器关闭连接(四次挥手)。

    在这里插入图片描述

常见状态码

在这里插入图片描述

Servlet详解

1、Servlet核心接口和类

在Servlet体系结构中,除了实现Servlet接口,还可以通过继承GenericServlet或 HttpServlet类,完成编写。

1、GenericServlet

GenericServlet抽象类
:GenericServlet使编写Servlet变得更容易。它提供生命周期方法 init和 destroy的简单实现,要编写一般的 Servlet,只需重写抽象service 方法即可。

2、HttpServlet类

HttpServlet是继承GenericServlet的基础上进一步的扩展。提供将要被子类化以创建适用于Web站点的HTTPservlet的抽象类。HttpServet的子类至少必须重写一个方法,该方法通常是以下这些方法之一
一∶doGet,如果 servlet支持HTTP GET请求
二: doPost,用于HTTP POST 请求
三、doPut,用于 HTTP PUT 请求
四、doDelete,用于 HTTP DELETE 请求

3、URL匹配规则

在这里插入图片描述

4、注解匹配

@WebServlet("地址")
常用属性:

name:servlet名字(可选)
value:配置url卢杰,可以配置多个
urlPatterns:配置url路径和value作用一样,不能同时使用
loadOnStartUp:访问优先级,默认值是1.
如果配置了web.xml,也配置了注解,两者不冲突。

2、应用整合

1、request对象

在Servle中用来处理客户端请求需要用doGet或doPost方法的request对象

get和post区别

在这里插入图片描述

### 2、request主要方法



 String getParameter(String name) 根据表单逐渐名称获取提交数据
void setCharacterEncoding(String charset) 指定每个请求的编码

3、解决get中文乱码

在这里插入图片描述

4、post中文乱码

在这里插入图片描述

5、response对象

用于响应客户请求并向客户端输出信息

主要方法

在这里插入图片描述

解决乱码问题
  • 设置服务器端响应的编码格式
  • 设置客户端响应内容的头内容的文件类型及编码格式

response.setContentType(“text/html”,“charset=UTF-8”);

6、简单的示例,实现登录

在这里插入图片描述

以上是目录结构

  • StudentDao .java
package com.lang.servlet.dao;

import com.lang.servlet.entity.Student;

import java.util.List;

public interface StudentDao {
    public int insert(Student student);
    public int delete(String stuname);
    public int update(Student student);
    public Student select(String stuname);
    public List<Student> selectAll();

}

  • StudentDaoImpl .java
package com.lang.servlet.dao.impl;

import com.lang.servlet.dao.StudentDao;
import com.lang.servlet.entity.Student;
import com.lang.servlet.utils.DButils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.swing.plaf.multi.MultiSeparatorUI;
import java.sql.SQLException;
import java.util.List;

public class StudentDaoImpl implements StudentDao {
    private QueryRunner queryRunner=new QueryRunner();
    @Override
    public int insert(Student student) {

        return 0;
    }

    @Override
    public int delete(String stuname) {
        return 0;
    }

    @Override
    public int update(Student student) {
        return 0;
    }

    @Override
    public Student select(String stuname) {
        try {
            System.out.println(DButils.getConnection());
          Student student = queryRunner.query(DButils.getConnection(),"select * from student where stuname=?;",new BeanHandler<Student>(Student.class),stuname);
            return student;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Student> selectAll() {
        try {
            List<Student> students=queryRunner.query(DButils.getConnection(),"select * from student",new BeanListHandler<Student>(Student.class));
            return students;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }
}

  • Student.java
package com.lang.servlet.entity;

public class Student {
    private int stuid;
    private String stuname;
    private String password;
    private String phone;

    public Student() {

    }

    public Student(String stuname, String password, String phone) {
        this.stuname = stuname;
        this.password = password;
        this.phone = phone;
    }

    public Student(int stuid, String stuname, String password, String phone) {
        this.stuid = stuid;
        this.stuname = stuname;
        this.password = password;
        this.phone = phone;
    }

    public int getStuid() {
        return stuid;
    }

    public void setStuid(int id) {
        this.stuid = stuid;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuid=" + stuid +
                ", stuname='" + stuname + '\'' +
                ", password='" + password + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}

  • StudentService.java
package com.lang.servlet.service;

import com.lang.servlet.entity.Student;

import java.util.List;

public interface StudentService {
    public Student login(String stuname, String password);
    public List<Student> showAll();
}

  • StudentServiceImpl
package com.lang.servlet.service;

import com.lang.servlet.dao.StudentDao;
import com.lang.servlet.dao.impl.StudentDaoImpl;
import com.lang.servlet.entity.Student;
import com.lang.servlet.utils.DButils;

import java.util.List;

public class StudentServiceImpl implements StudentService{
    private StudentDao studentDao=new StudentDaoImpl();
    @Override
    public Student login(String stuname, String password) {
        Student result=null;
        try {
            DButils.begin();

            Student student=studentDao.select(stuname);
            if(student!=null){
                if(student.getPassword().equals(password)){
                    result=student;
                }
            }
            DButils.commit();
        } catch (Exception e) {
            DButils.rollback();
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List<Student> showAll() {
        return null;
    }
}

  • LoginServlet.java
package com.lang.servlet.servlet;

import com.lang.servlet.entity.Student;
import com.lang.servlet.service.StudentService;
import com.lang.servlet.service.StudentServiceImpl;

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;
@WebServlet(value = "/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        String stuname= req.getParameter("stuname");
        String password=  req.getParameter("password");

        StudentService studentService=new StudentServiceImpl();
        Student student=studentService.login(stuname,password);

        if(student!=null){
            PrintWriter printWriter=resp.getWriter();
            printWriter.println("<html>");
            printWriter.println("<head>");
            printWriter.println("<meta charset='UTF-8'>");
            printWriter.println("<title> 结果页面</title>");
            printWriter.println("</head>");
            printWriter.println("<body>");
            printWriter.println("<h1>登录成功</h1>");
            printWriter.println("</body>");
            printWriter.println("</html>");
        }else {
            PrintWriter printWriter=resp.getWriter();
            printWriter.println("<html>");
            printWriter.println("<head>");
            printWriter.println("<meta charset='UTF-8'>");
            printWriter.println("<title> 结果页面</title>");
            printWriter.println("</head>");
            printWriter.println("<body>");
            printWriter.println("<h1>登录失败</h1>");
            printWriter.println("</body>");
            printWriter.println("</html>");
        }




    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      doGet(req,resp);
    }
}

  • DButils.java
package com.lang.servlet.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.stream.IntStream;

public class DButils {
    private static DruidDataSource druidDataSource=null;
    private static final ThreadLocal<Connection> THREAD_LOCAL=new ThreadLocal<>();
    static {
        Properties properties=new Properties();
        InputStream inputStream=DButils.class.getResourceAsStream("/database.properties");
        try {
            properties.load(inputStream);
            try {
                druidDataSource=(DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection connection=THREAD_LOCAL.get();
        if (connection==null){
            try {
                connection=druidDataSource.getConnection();
                THREAD_LOCAL.set(connection);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return connection;
    }
    public static void begin(){
        Connection connection=null;
        try {
            connection=getConnection();
            connection.setAutoCommit(false);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    public static void commit(){
        Connection connection=null;

        try {
            connection=getConnection();
            connection.commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(connection,null,null);
        }
    }
    public static void rollback(){
        Connection connection=null;

        try {
            connection=getConnection();
            connection.rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            closeAll(connection,null,null);
        }
    }
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
       try {
           if(connection!=null){
               connection.close();
           }
           if (statement!=null){
               statement.close();
           }
           if(resultSet!=null){
               resultSet.close();
           }
           THREAD_LOCAL.remove();
       }catch (Exception e){
           e.printStackTrace();
       }
    }
}

  • login,html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/servletLearn/login" method="post">
    用户名:<input type="text" name="stuname">
    密码:<input type="password" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>

7、问题

上面的案例,调用业务逻辑和显示结果在一个servlet里,会产生设计问题
不符合单一职能原则,各司其职的思想,不利于后期维护

转发和重定向

转发:作用在服务器端,将请求发送给服务器上的其他资源,以共同完成一次请求的处理

1、页面跳转

在调用业务逻辑的Servlet中

request.getRequestDispatcher("/目标url").forword(request,response);

这种跳转,是在服务器内部跳转,地址栏不发生变化,属于同一次请求。

2、数据传递

forward表示一次请求,实在服务器内部跳转,可以共享同一次request作用域中的数据

  • request作用域
    用于存储数据的空间,作用范围是一次请求有效(一次请求可以经过多次转发)
    • 可以将数据存入request后,在一次请求过程中的任何位置进行获取
    • 可传递任何数据(基本数据类型、对象、数组、集合等)

3、转发的特点

  • 转发是服务器行为
  • 转发是浏览器只做了一次访问请求
  • 转发浏览器地址不变
转发两次跳转之间传输的信息不会丢失,所以可以通过reques进行数据的传递、
  • 转发只能将请求转发给同一个Web应用中的组件

4、重定向

作用在客户端,客户端将请求发送给服务器后,服务器响应给客户端一个新的请求地址,客户端重新发送新请求。此种方式地址会变化,客户端发送了两次请求

页面跳转

response.sendRedirect("目标URI“);

数据传递

  • response没有作用域,两次request请求中的数据无法共享传递数据
  • 通过URI的拼接进行数据传递"webProject/b?username=tom";·
  • 获取数据∶ request.getParameter("username);

特点

  • 重定向是客户端行为。
  • 重定向是浏览器做了至少两次的访问请求。
  • 重定向浏览器地址改变。
  • 重定向两次跳转之间传输的信息会丢失(rcquest范围)。
  • 重定向可以指向任何的资源,包括当前应用程序中的其他资源、同一个站点上的其他应用程序中的资源、其他站点的资源。

Servlet生命周期

1、实例化

当用户第一次访问servlet时,由容器调用Servet的构造器创建具体的servlet对象。也可以在容器启动之后立刻创建实例。使用如下代码可以设置Servlet是否在服务器启动时就创建。

<load-on-startup>1</load-on-startup>

注意∶只执行一次

2、初始化

在初始化阶段,init方法会被调用。这个方法在javax.servlet.Servlet接口中定义。其中,方法以一个ServletConfig类型的对象作为参数。

只执行一次

3、服务

当客户端有一个请求时,容器就会将请求ServletReques与响应ServletResponse对象转给servlet,以参数的形式传给service方法
此方法会执行多次

4、销毁

当Servlet容器停止或者重新启动都会引起销毁Servlet对象并调用destroy方法。

只执行一次
在这里插入图片描述

Servlet特性

线程安全问题

Servlet在访问之后,会执行实例化操作,创建一个Servlet对象。而我们Tomcat容器可以同时多个线程并发访问同一个Servlet,如果在方法中对成员变量做修改操作,就会有线程安全的问题。

在这里插入图片描述
在这里插入图片描述

状态管理

  • HTTP协议是无状态的,不能保存每次提交的信息
  • 如果用户发来一个新的请求,服务器无法知道它是否与上次的请求有联系。
  • 对于那些需要多次提交数据才能完成的Web操作,比如登录来说,就成问题了。

概念

将浏览器与web服务器之间多次交互当作一个整体来处理,并且将多次交互所涉及的数据(即状态)保存下来。

分类

客户端状态管理技术∶将状态保存在客户端。代表性的是Cookie技术。

服务器状态曾理技术∶将状态保存在服务器端。代表性的是session技术(服务器传递sessionID时需要使用Cookie的方式)
和application

Cookie
什么是Cookie
  • Cookie是在浏览器访间web服务器的某个资源时,由Web服务器在HTTP响应消息头中附带传送给浏览器的一小段数据。
  • 一旦web浏览器保存了某个Cookie,那么它在以后每次访间该web服务器时,都应在HTTP请求头中将这个cookie回传给web服务
  • 一个Cookie主要由标识该信息的名称(name)和值(value)组成。

    在这里插入图片描述
创建Cookie
Cookie ck=new Cookie("code",code);
ck.setPath("/项目名/路径名");
ck.setMaxAge(-1); 内存存储,取值3种,>0有效期,单位秒,=0 浏览器关闭 <0内存存储 默认-1
response.addCookie(ck):添加到response对象种,响应式发送给客户端
获取Cookie
Cookie[] cookies=req.getCookies();
        for (Cookie cook:cookies
             ) {
            if(cook.getName().equals("code")){
                code=cook.getValue();
                break;
            }
        }
修改Cookie

要求,cookie的name和路径必须一致,才可以修改。否则就是新建Cookie

编码和解码

在这里插入图片描述

创建带中文的Cookie

在这里插入图片描述

读取带中文的Cookie

在这里插入图片描述

Cookie的优点和缺点
优点
  • 可配置到期规则。
  • 简单性∶Cookie是一种基于文本的轻量结构,包含简单的键值对。
  • 数据持久性∶Cookie默认在过期之前是可以一直存在客户端浏览器上的。
缺点
  • 大小受到限割∶大多数浏览器对Cookie的大小有4K、8K字节的限制。
  • 用户配置为禁用∶有些用户禁用了浏览器或客户端设备接收Cookie的能力,因此限制了这一功能。
  • 潜在的安全风险∶Cookie可能会被暮改。会对安全性造成潜在风险或者导致依赖于Cookie的应用程序失败。

Sesion

  • Sessio用于记录用户的状态。
  • Sesion指的是在一段时间内,单个客户端与web服务器的一连串相关的交互过程
  • 在一个Session中,客户可能会多次请求访问同一个资源,也有可能请求访问各种不同的服务器资源。

原理

服务器会为每一次会话分配一个Session对象
同一个浏览器发起的多次请求,同属于一次会话(Session)

首次使用到Session时,服务器会自动创建Session,并创建Cookie存储Sessionld发送回客户端



## 使用

sesion作用域∶

  • 拥有存储数据的空间,作用范围是一次会话有效
  • 一次会话是使用同一浏览器发送的多次请求。一旦浏览器关闭,则结束会话。
  • 可以将数据存入Session中,在一次会话的任意位置进行获取。
  • 可传递任何数据(基本数据类型、对象、集合、数组)

获取session

HttpSession session=request.getSession();

Session 保存数据

session.setAttribute("key",value);

Session 获取数据

session.getAttribute("key”);

Seesion移除数据

session,removeAttribute("key");

生命周期

  • 开始:第一次使用到的Session的请求产生,创建Session
  • 结束
    • 浏览器关闭,则失效
    • 超时,则失效
      • sessopm.setMaxinactiveInterval(seconds);
        -手工销毁失效:session.invalidate();

ServletContext对象

ServletContext概述

全局对象,也拥有作用域,对应一个Tomcat中的Web应用

当Wweb服务器启动时,会为每一个Web应用程序创建一块共享的存储区域(ServletContext)。

ServletContext在web服务器启动时创建,服务器关闭时销毁。


## 获取方法

  • GenericServlet提供了getServletContext()方法(推荐) this.getServletContext();
  • HttpServletRequest提供了getServletContext()方法
  • HttpSession提供了getServletContext()方法。

作用

获取项目真实路径

获取当前项目在服务器发布的真实路径
servletContext.getRealPath("/"); /代表当前项目

### 获取项目上下文路径

servletContext.getContextPath()

### 全局容器

存储方法和session一样,可以用作计数器

### 特点

唯一性:一个应用对应一个ServletContext

生命周期:只要容器不关闭或者应用不卸载,Servlet就一直存在

过滤器

是处于客户端与服务器目标资源之间的一道过滤技术
在这里插入图片描述

作用

执行地位在Servlet之前,客户端发送请求时,会先经过Fiter,再到达目标Servle中;
响应时,会根据执行流程再次反向执行Fiter
可以解决多个Servlet共性代码的冗余问题(例如∶乱码处理、登录验证)

编写过滤器

Servlet API中提供了一个Filter接口,开发人员编写一个Java类实现了这个接口即可,这个Java类称之为过滤器(Filter)

实现过程

  • 编写Java类实现Fiter接口
  • 在dofFlter方法中编写拦截逻辑
  • 设置拦我路径
  • 依赖FilterChain
    在这里插入图片描述

过滤器配置

在自定义Filter类上使用注解@WebFilter(value=“要拦截的路径”)
xml:

  <filter>
        <filter-name>xml</filter-name>
        <filter-class>com.lang.servlet.filter.ServletFileter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>xml</filter-name>
        <url-pattern>/test</url-pattern>
        <!--填写要拦截的路径-->
    </filter-mapping>

在这里插入图片描述

过滤器优先级

在这里插入图片描述

过滤器应用

过滤乱码
package com.lang.servlet.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/*")
public class ServletFileter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("fileter");
        servletRequest.setCharacterEncoding("UTF-8 ");

        servletResponse.setContentType("text/html;charset=UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

登陆权限
package com.lang.servlet.filter;

import com.lang.servlet.entity.Student;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/*")
public class ServletFileter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("fileter");
        servletRequest.setCharacterEncoding("UTF-8 ");
        HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
        HttpServletResponse httpServletResponse=(HttpServletResponse) servletResponse;
        HttpSession httpSession=httpServletRequest.getSession();
        Student student=(Student) httpSession.getAttribute("stu")
        if (student!= null) {
            filterChain.doFilter(httpServletRequest,httpServletResponse);
        }
        else {
            httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/路径");
        }
    }
    @Override
    public void destroy() {

    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值