Servlet和jsp学习

1:基本概念

API 应用程序编程接口 源码 字节码 帮助文档
JAVASE 标准版本,SUN为程序员提供的基础库:IO,集合,线程
源码 在 JAVA_HOME\src.zip
字节码在 JRE_HOME\lib\rt.jar
JAVAEE 企业版 SUN公司为程序员提供的另一套庞大的类库,帮助与程序员完成企业级的开发。

2:接口的作用

解耦合,降低程序的耦合度,提高程序的扩展力。

3:系统架构的分类

C/S 与 B/S 架构(特殊的C/S)
B/S
优点:
不需要安装特定的软件,只需要浏览器就可以
升级只需要升级服务器端,升级方便
缺点:
所有数据都集成在服务器端,数据容易丢失,相对来说不安全
速度慢,用户体验差

C/S
优点
速度快,相对安全,用户体验好
界面可以非常炫酷
缺点:
升级麻烦,需要安装特定的客户端软件

4:B/S架构的流程

B/S 架构设计的协议和角色
在这里插入图片描述

5:模拟Servlet服务器

1:定义Servlet规范
2:Servlet程序实现Servlet规范
3:模拟TomCat服务器面向接口进行调用
实现类与xml配置文件

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Scanner;

/**
 * 模拟Tomcat
 */
public class DiaoTom {
    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("服务器启动成功");
        System.out.println("请打开浏览器,输入地址");
        while (true){
            String next = scanner.next();
//        System.out.println("您访问的资源路径是: "+next);
            FileReader fileReader = new FileReader("C:\\Users\\Administrator\\IdeaProjects\\Zhujie\\src\\web.xml");
            Properties properties = new Properties();
            properties.load(fileReader);
            fileReader.close();
            String property = properties.getProperty(next);
            Class<?> aClass = Class.forName(property);
            SerInter serInter = (SerInter)aClass.newInstance(); //不确定生成对象的类型;但是因为这些类都实现了上层的接口,所以可以大胆的强制类型转换
            //接下来面向接口去调用方法
            serInter.service();
        }
    } 
}

6:Servlet 开发目录结构

在这里插入图片描述

在这里插入图片描述

7:如何在Idea中整合Tomcat

注意配置项目的部署名

8:使用Servlet与jdbc连接数据库,查询信息返回网页展示

1)新建index.html,可以直接通过连接进行访问,且在页面上配置超链接,超链接指向Servlet程序
2)配置xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>com.fangjun.javaweb.Listemp</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/system/list</url-pattern>
    </servlet-mapping>
</web-app>

3)java代码连接数据库,返回页面

package com.fangjun.javaweb;

import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;

public class Listemp implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = servletResponse.getWriter();
        writer.print("<html>");
        writer.print("<head>");
        writer.print("    <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />");
        writer.print("    <title>员工信息</title>");
        writer.print("</head>");
        writer.print("<body>");
        writer.print("<h3 align='center'>员工列表</h3>");
        writer.print("<hr width='60%'>");
        writer.print("<table border='1' align='center' width='50%'>");
        writer.print("    <tr align='center'>");
        writer.print("        <th>序号</th>");
        writer.print("        <th>员工编号</th>");
        writer.print("        <th>员工姓名</th>");
        writer.print("        <th>员工薪水</th>");
        writer.print("    </tr>");

        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/learn","root","333");
            String sql="select empno,ename,sal from emp";
            preparedStatement = connection.prepareStatement(sql);
            resultSet=preparedStatement.executeQuery();
            int i=0;
            while (resultSet.next()){
                String empno = resultSet.getString("empno");
                String ename = resultSet.getString("ename");
                String sal = resultSet.getString("sal");
                writer.print("<tr align='center'>");
                writer.print("<th>"+(++i)+"</th>");
                writer.print("<th>"+empno+"</th>");
                writer.print("<th>"+ename+"</th>");
                writer.print("<th>"+sal+"</th>");
                writer.print("</tr>");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        writer.print("</table>");
        writer.print("</body>");
        writer.print("</html>");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

9:Servlet 对象的生命周期

1):什么是生命周期
表示一个java对象从最初被创建到销毁整个过程
2):Servlet对象的生命周期谁管理?
都是有Tomcat(web 容器)去管理
web程序员无权干涉,方法调用等等都是由容器管理
3):默认情况下,Servlet对象在web容器启动阶段不会被实例化。
可以通过特殊手段,去实例化。
怎样在启动阶段,实例化对象?
xml文件中加入

 <load-on-startup>1</load-on-startup>  自然数越小优先级越高,服务器启动阶段实例化Servlet对象

4):测试图片
在这里插入图片描述
在这里插入图片描述
5)结论
描述Servlet对象的生命周期
a:用户在地址栏上输入URL
b:web容器截取请求路径
c:web容器在上下文中找请求路径对应的Servlet对象,这里需要用到web.xml中内容的映射
d:若没有找到对应的Servlet对象
e:通过web.xml文件中的相关配置信息,找到请求路径对应的Servlet对应的完整类名后
f:通过反射机制,调用Servlet的无参数构造方法完成对象的实例化
g:web容器调用Servlet对象的init方法完成初始化操作。
h:web容器调用Servlet对象的service方法提供服务
i:若找到相应的Servlet对象
j:web容器直接调用Servlet对象的service方法提供服务
k:web容器关闭时、webapp重新部署时,该Servlet对象长时间没有用户再次访问时。web容器会将该对象销毁,web容器会调用Servlet对象的destory方法,完成销毁前的准备。

构造方法,init方法,destory方法只执行一次
service 方法只要用户请求一次,就执行一次

Servlet对象在单实例多线程环境下运行。如果Servlet对象中有实例变量,并且涉及到实例变量的修改操作,那么Servlet 对象一定会存在线程安全问题,不建议在Servlet对象中使用实例变量,尽量使用局部变量

10:Servlet对象创建之后,这个对象被存储到哪里?

大多数WEB容器是将Servelet对象以及其对应的url-pattern存储到Map集合中。
在这里插入图片描述

11:Servlet接口中的方法编写什么代码?什么时候使用这些代码?

1)无参数的构造方法
2)init方法
以上两个方法执行时间几乎一致,执行次数只有一次
若系统要求在对象创建的时候执行一段特殊的程序,这段程序尽量写在init方法,不要写在构造方法(可能会导致无参数构造方法不存在)
3)service方法
这个方法必须重写,这个方法完成业务逻辑的处理,请求的处理,以及完成响应,这个方法中的代码最有价值。
4)destory方法
这个方法提供特殊时刻,销毁时自动被容器调用
类加载时需要执行的代码片段,放到哪里?
需要写在静态代码块中

12:javax.servlet.ServletConfig接口

在这里插入图片描述
上面可以看到对象的内存地址不同,这是因为一个Servlet对象就对应一个ServletConfig信息
结论
1)javax.servlet.ServletConfig是一个接口
2)Tomcat服务器实现了Servlet规范,Tomcat服务器专门写了一个ServletConfig接口的实现类。完整的类名是
org.apache.catalina.core.StandardWrapperFacade
参数的类型是一个接口,依旧是面向接口去编程
在这里插入图片描述
3:java web程序员在编程时,一直都是面向Servlet接口去完成调用,不需要关心具体类的实现方式
4);what is Tomcat?
The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies. The Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket specifications are developed under the Java Community Process.
5)ServletConfig接口中有哪些方法?

    String getServletName();
    ServletContext getServletContext();
    String getInitParameter(String var1); //针对下面这个标签里面的内容
    //这个标签的内容是放在<servlet>标签里面的,因为不同的Servlet有着不同的config
    /**
        <init-param>
        <param-name>user</param-name>
        <param-value>root</param-value>
        </init-param>
        */
    Enumeration<String> getInitParameterNames();

6)ServletConfig到底是是什么?
ServletConfig是封装了Servlet对象的配置信息,Servlet对象的配置信息被放到了web.xml文件中

7)将init方法中的ServletConfig参数移动到service方法中?因为业务逻辑主要靠service方法去实现,实现过程中可能会用到ServletConfig参数。
可以在我们自己编写的Servelet类中,设置一个private成员变量,然后在init方法中的局部变量值赋值给成员变量;再结合类中的getServletConfig方法,提供给子类去调用。

13:javax.servlet.ServletContext接口

每一个web工程只有一个上下文对象,说白了就是任何一个Servlet下,都能获取带这个上下文对象。
作用:
配置全局的参数

    <context-param>
        <param-name>username</param-name>
        <param-value>admin</param-value>
    </context-param>

获取web资源:根据工程的相对路径去获得到他的绝对路劲(tomcat服务器中)

servletcontext.getrealPath()
在这里插入图片描述
表单
在这里插入图片描述

获取域对象数据,servletContext本身就是域对象
域对象在 web工程中就是帮助我们存储数据的一个对象

四个不同的域对象,他们的区别是存储范围的不同
在这里插入图片描述
1)javax.servlet.ServletContext 接口是Servlet的规范
2)Tomcat服务器对ServletContext 接口的实现类的完整类名是
org.apache.catalina.core.ApplicationContextFacade
依旧是面向接口编程,不关心具体实现
3)ServletContext 到底是什么东西,什么时候创建,销毁?
ServletContext 翻译为Servlet上下文,一个webApp只有一个ServletContext对象;一个webAPP只有一个web.xml文件
ServletContext在服务器启动阶段被实例化,在服务器关闭时被销毁
ServletContext对应的是web.xml文件,是此文件的代表

ServletContext是所有Servlet对象四周环境的代表,一个webAPP所有servlet对象共享ServletContext的,如果所有Servlet对象想共享数据,可以将数据放到ServletContext中,此数据不建议设计修改的操作,因为ServletContext是一个共享的对象,修改会涉及到线程安全问题
4)ServletContext 接口有哪些常用的方法?


Object getAttribute(String var1);//ServletContext中拿数据
void removeAttribute(String var1);//ServletContext中删除数据
void setAttribute(String var1, Object var2);//向servletcontext中绑定数据

String getInitParameter(String var1); //下面这两个方法主要针对下面这个标签 
/**标签的位置独立于Servlet标签
    <context-param>
        <param-name>username</param-name>
        <param-value>admin</param-value>
    </context-param>
*/
Enumeration<String> getInitParameterNames();
String getRealPath(String var1); //获取web项目根目录下某个文件的绝对路径

5)Servlet ,ServletConfig,ServletContext 三者之前的关系?
一个Servlet 对象对应一个ServletConfig对象;所有的Servlet对象共享一个ServletContext 对象

6)ServletContext 可以完成跨用户去传递数据
模拟两个Servlet程序一个存数据,一个取数据。
Aservlet 存数据到ServlContext

package com.fangjun.java;

import com.fangjun.entity.User;

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class Aservlet implements Servlet {
    private ServletConfig servletConfig;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
    }

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        ServletConfig servletConfig = getServletConfig();
        //调用方法拿到servletConfig上下文内容
        ServletContext servletContext = servletConfig.getServletContext();
        User user = new User();
        user.setName("fangjun");
        user.setUsercode("001");
        servletContext.setAttribute("userobj",user);
//        System.out.println("A's servletContext="+servletContext);
//        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
//        while (initParameterNames.hasMoreElements()){
//            String s = initParameterNames.nextElement();
//            String initParameter = servletContext.getInitParameter(s);
//            System.out.println(s+" "+initParameter);
//        }
//        String realPath = servletContext.getRealPath("/index.html");
//        System.out.println(realPath);
  }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

Bservlet 从ServlContext取得数据

package com.fangjun.java;

import javax.servlet.*;
import java.io.IOException;

public class Bservlet implements Servlet {
    private ServletConfig  servletConfig;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
    }

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        ServletConfig servletConfig = getServletConfig();
        //调用方法拿到servletConfig上下文内容
        ServletContext servletContext = servletConfig.getServletContext();
        Object userobj = servletContext.getAttribute("userobj");
        servletResponse.getWriter().print(userobj);
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

14:关于Tomcat路径问题

第一类:以“/”开始,加webApp的名称:超链接
第二类:以“/”开始,不加webApp的名称:web.xml配置Servlet的url
第二类:不以“/”开始,不加webApp的名称:web.xml配置欢迎界面

超链接

<a href="/webAppname/dosome"> 起点是web项目名字

web.xml中的url-pattern

<url-pattern>/dosome</url-pattern>起点项目名字可以省略,因为地址栏打开的技术默认项目名路径,在此基础上去添加路径

form表单中的action属性 同超链接

getRealPath()返回值 起点项目名字可以省略

15:关于webapp欢迎界面

1)欢迎页面如何设置
在web.xml文件中写入,欢迎页面可以设置多个,越靠上优先级越高

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

2)欢迎页面设置路径不需要以“/”开始,根目录作为初始化目录
在这里插入图片描述
3)注意,Tomcat服务器conf文件下的web.xml是全局配置,这里定义了默认初始页面。如果项目中没有设置,就会采用这个全局配置
在这里插入图片描述

16:Web应用中常用的错误代码

-404 Not Found
-500 Server Inner Error
-200 OK 正常相应对应的状态码
状态码由W3C指定
可以使用下面的标签指定错误页面的展示

    <error-page>
        <error-code>404</error-code>
        <location>/erro/error.html</location>
    </error-page>

17:适配器(Adapter)

1)分析项目中不适应缺省适配器,程序存在哪些缺点?
如果程序只是使用接口中的部分方法,但是要实现更多方法,代码丑陋。
2)关于缺省适配器
下面为实现的流程
接口

package com.fangjun.javase;

public interface Common {
    void m1();
    void m2();
    void m3();
    void m4();
    void m5();
    void m6();
    void m7();
    void m8();
    void m9();
}

缺省适配器,去实现这个接口,后续需要实现的方法改为抽象方法,这个类也定义为抽象类

package com.fangjun.javase;

public abstract class Adapter001 implements Common {

    @Override
    public abstract void m1();

    @Override
    public abstract void m2();

    @Override
    public abstract void m3();

    @Override
    public void m4() {

    }

    @Override
    public void m5() {

    }

    @Override
    public void m6() {

    }

    @Override
    public void m7() {

    }

    @Override
    public void m8() {

    }

    @Override
    public void m9() {

    }
}

业务类A,B去继承这个抽象类,就可以保证使用三个方法,代码更加优雅

package com.fangjun.javase;

public class A extends Adapter001{
    @Override
    public void m1() {

    }

    @Override
    public void m2() {

    }

    @Override
    public void m3() {

    }
}

3)关于设计模式
分类
创建型:解决对象的创建问题
行为型:该模式与方法,行为,算法有关的设计模式
结构型:更多类,更多对象组合成更大的结构解决某个特定的问题
-Gof95:(1995年,四人提出的23种设计模式)
*单例模式
*工厂模式
*适配器模式
*迭代模式
*策略模式
*装饰器模式

18:GenericServlet

GenericServlet作为适配器,提供更多选择
在这里插入图片描述
自己实现的适配器 ,注意为了子类方便使用init方法,这里提供了一个无参数的init()方法,提供给子类Override

package com.fangjun.javaee.servlet;

import javax.servlet.*;
import java.io.IOException;

/**
 * GenericServlet是一个适配器
 * 之后继承GenericServlet 重写service
 */
public abstract class GenericServlet implements Servlet {

    private ServletConfig servletConfig;
    @Override
    public  void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
        this.init(); //这里回去调用子类重写的init()方法
    }

    public void init(){

    }

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    @Override
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
//扩展方法,供子类使用
    public ServletContext getServletContext(){
        return getServletConfig().getServletContext();
    }
}

子类实现

package com.fangjun.javaee.servlet;


import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends javax.servlet.GenericServlet {

    //需求在使用GenericServlet之后,依旧有需要在初始化时候执行一段代码,如何在子类实现这个需求

    /**
     * 如果在初始化时刻,需要执行一段特殊的程序,建议重写无参数的init()方法
     */
    @Override
    public void init() {
        System.out.println("HelloServlet's init method execute!");
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = servletResponse.getWriter();
        writer.print("HELLO WORLD");
    }
}

sun公司帮我们实现了GenericServlet,完整的类名为:javax.servlet.GenericServlet

19:HTTP协议 GET请求与POST请求的区别

1 ) 什么是HTTP协议
超文本传输协议,浏览器与服务器之间的通信协议 该协议是W3C组织负责制定,其实本质上就是数据格式提前制定好了。浏览器和服务器必须按照这种数据格式进行接收和发送。

2)HTTP1.1

3)包括请求协议和相应协议

4)请求协议?包括四部分
请求行:请求方式(POST?GET) 请求路径 协议的版本号
消息报头
空白行:分离消息报头和请求体
请求体

5)响应协议?
状态行:协议版本号 状态码 状态描述信息
响应报头
空白行:分离响应报头和响应体
响应体

6)GET请求与POST请求的区别
6.1)什么时候get?什么时候post?
只有使用表单form,并且将form的响应格式设置为method=“post”,这样才是post请求,除此之外的其他请求都是get请求。
6.2)get请求与post请求的区别?
get请求的请求行:
url?name=value&name=value&name=value…
提交的信息会显示在地址栏
在这里插入图片描述
get请求的请求行:
post请求数据不显示在地址栏上,存在于请求体中,提交格式 name=value&name=value…

在这里插入图片描述
post请求在请求体中提交数据,所以post请求提交的数据没有长度限制;post可以提交大数据;post请求可以提交任何类型的数据,包括影视频,所以文件上传必须要使用post请求。
get请求在请求行上提交数据,所以get请求提交的数据长度有限制;只能提交字符串数据。
Get请求的最终返回结果,会被浏览器收纳;但是post不会。

敏感数据,不是普通的字符串,传送的数据非常多,请求修改服务器端的资源 都需要使用POST

GET请求多数情况下是从服务器中读取数据,这个数据多数情况下是不会发生改变的,最终会被get请求缓存下来。
post请求是为了修改服务器端的资源,但是每一次修改的结果都是不同的,最终结果也没有必要被浏览器缓存下来。
浏览器缓存资源之后,缓存的资源和某个特定的路径绑定在一起,只要浏览器发送相同的路径,这个时候就回去缓存中获取资源,不再访问服务器,以这种方式降低服务器的压力,提高用户的体验。
可以在请求路径后面加时间戳,保证浏览器每次从服务器抓取新的内容。
JS怎样获取毫秒?

20:如何保证前端的请求方式和服务器端需要的请求方式一致?

1)如何在java程序中获取前端发来的请求方式是哪一种?
HTTP请求信息被封装到javax.servlet.http.HttpServletRequest当中,这个类中有一个方法
String getMethod(),可以调用这个方法去获得浏览器端发过来的的请求方式。
public interface HttpServletRequest extends ServletRequest,在调用service方法时也是面向ServletRequest接口去调用子接口中的方法。完成前后端的交互。

package com.fangjun.javaweb;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class http extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest servletRequest1 = (HttpServletRequest) (servletRequest);
        HttpServletResponse servletResponse1 = (HttpServletResponse) (servletResponse);
        servletResponse1.setContentType("text/html;charset=UTF-8");
        String method = servletRequest1.getMethod();
        PrintWriter writer = servletResponse1.getWriter();
        if (method.equals("GET")){
            writer.print("wrong method please use post");
            throw new RuntimeException("wrong method please use post");
        }
        writer.print("login");
    }
}

21:HttpServlet原理(模板方法设计模式)

浏览器发GET方法,如果服务器要求其发POST方法,在java程序中需要报错,程序重写doPost方法;如果服务器对浏览器发送的方法没有其他特殊要求,则直接重写doGet方法

浏览器发POST方法,如果服务器要求其发GET方法,在java程序中需要报错,程序重写
doGet方法;如果服务器对浏览器发送的方法没有其他特殊要求,则直接重写doPost方法

结论:编写一个Servlet类直接去继承HttpServlet,get请求重写doGet,而且重写的方法可以看成是一个main方法。
405-请求不一致
在这里插入图片描述

22: 模板方法设计模式

模板方法设计模式,可以在做到,不改变算法的前提之下,重新定义算法的实现步骤。
算法受到保护,所以模板方法一般使用final修饰
核心的算法不需要每一次去编写。这个核心算法只在模板方法中实现了一次,子方法的实现可以通过子类去完成
在这里插入图片描述
在这里插入图片描述

23:javax.servlet.http.HttpServletRequest

1)继承关系:
public interface HttpServletRequest extends ServletRequest
2)web容器负责实现
3)封装HTTP请求的全部信息
4)HttpServletRequest对象的生命周期:一次请求对应一个request对象。
5)接口中的常用方法

String username = req.getParameter("username"); //key 去拿value对应的一维数组的第一个元素
Map<String, String[]> parameterMap = req.getParameterMap();//拿整个数据对象
Enumeration<String> parameterNames = req.getParameterNames();//拿key
String[] parameterValues = req.getParameterValues();//key 去拿value对应的一维数组的所有元素

//下面三个方法针对的都是request request是怎样的范围?
//一次请求一个request,只能在同一次请求中传递数据
req.setAttribute();
req.getAttribute();
req.removeAttribute();


在这里插入图片描述
数据的转发
Aservlet

package com.fangjun.javaweb;


import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class Aservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        User user = new User();
        user.setId("111");
        user.setName("junjun");
        req.setAttribute("user_obj",user);
        //如何进行转发
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/b"); //中间是
        requestDispatcher.forward(req,resp);//首尾是
    }
}

Bservlet

package com.fangjun.javaweb;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class Bservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        Object user_obj = req.getAttribute("user_obj");
        System.out.println(user_obj);
        writer.print(user_obj);
    }
}

ServletContext 可以跨用户传递数据
ServletRequest 只能在同一个请求中传递数据,不能够进行跨用户进行传递数据,可以跨Servlet传递数据,但是这几个Servlet必须在同一个请求当中,优先考虑ServletRequest。

24:关于中文乱码的解决办法

一:数据保存过程中出现乱码
第一种:在保存之前,数据本身就是乱码,保存到数据库表的时候一定就是乱码
第二种:保存之前不是乱码,但是由于数据库本身不支持简体中文,保存之后出现乱码。

二:数据展示过程中出现乱码(网页上乱码,从服务器发送到浏览器)
解决办法:设置响应的类型,以及字符编码方式。
在java程序中:
servletResponse.setContentType(“text/html;charset=UTF-8”);
在HTML中,设置HTML保存数据的类型

<meta chaset="UTF-8">
<meta content="text/html;charset=UTF-8">

三:数据传递过程中乱码(从浏览器到服务器)
将数据从浏览器发到服务器的时候,服务器收到的数据是乱码。
发送的时候已经乱了,不管哪个国家的文字在浏览器发送给服务器的时候都会采用ISO-8859-1的编码方式发送。
如何解决?
将服务器中接收到数据采用ISO-8859-1的方式解码,回归原来的状态,再给一种支持中文解码方式重新编码组装。
网页上输入的信息肯定是被支持中文编码的编码方式存储了,但是在像浏览器发送数据的时候这些被存储的01被错误的解码了(这里发生错误),可以让浏览器再按照这种错误的编码方式去还原这些01字符串,再使用可以编码中文的编码集去编码这些01序列。
对应的代码

//第一种方式
String dname = res.getParameter("dname");
byte[] byte = dname.getBytes("ISO-8895-1");//解码
String s = new String(byte,"UTF-8");//重新编码,重新编码需要考虑浏览器HTML的编码格式
//第二种方式 只能对post请求奏效,直接让req对请求体中的数据采用和浏览器相同的方式进行解码
servletRequest.setCharacterEncoding("UTF-8"); 
//第三种方式:直接修改server.xml文件;只对get请求奏效
//在Connector标签中添加 URIEncoding="UTF-8"
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

25:Servlet 的线程安全问题

1)什么时候存在线程安全问题?
-多线程并发
-有共享数据
-共享数据有修改的操作

2)servlet 在单实例多线程的环境下运行的

3)JVM中哪些变量会存在线程安全问题
-常量不会被修改,所以常量不存在线程安全问题
- 局部变量的内存空间不共享,一个线程一个栈
- 所有线程共享一个堆
- 所有线程共享一个方法区

4)线程的安全问题不仅仅出现在JVM中,也有可能发生在数据库中,例如:多个线程共享同一张表,并且同时去修改表中的一些记录,这些记录存在线程安全问题,如何解决?
- 第一种方案是在java程序中使用synchronized关键字,强制线程安全
- 行级锁(悲观锁)
- 事物隔离级别
- 乐观锁
5)怎么解决Servlet线程安全问题?
-不适应实例变量,使用局部变量
-如果必须要使用实例变量,可以考虑将线程对象变成多例对象
-线程排队机制

26:转发与重定向

两种方式
1)转发

request.getRequestDispatcher("/b").forward(request,response);

2)重定向(两次请求) 服务器重新响应新的地址给浏览器,之后浏览器使用新的地址向服务器发送了全新的请求;代码为302
重定向后的路径是全新的request
response.sendRedirect() 新的完整路径,保留项目名称

response.sendRedirect(request.getContextPath()+"/b");
  1. 转发和重定向的相同点与不同点
    相同点:都可以完成资源的跳转
    不同点:
    ·转发是request触发 重定向是response 触发
    ·转发是一次请求,浏览器上的地址栏不发生变化
    -重定向是两次请求,浏览器上的地址会发生改变
    -重定向的路径需要加项目名
    -转发是在本项目内部完成资源啊跳转,重定向是可以完成跨APP跳转资源

4)跳转的下一个资源是什么?
可以是服务器中的其他任何资源

5) 什么时候使用转发?什么时候采用重定向?
跨APP 重定向
同一个request 转发
重定向可以解决浏览器刷新问题

6)重定向的原理?
点击一个超链接,到最终网页停下来,这个过程可能是多次请求

27:重定向解决页面的刷新问题

测试结果:数据库中的表没有增加
在这里插入图片描述

package com.fangjun.jdbc;
/**
 * 用户点击保存数据到数据库
 */
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
import java.util.ResourceBundle;

public class login extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //com.mysql.jdbc.Driver
        req.setCharacterEncoding("UTF-8");
        String ucode = req.getParameter("ucode");
        String uname = req.getParameter("uname");
        Connection connection=null;
        PreparedStatement statement =null;
        ResourceBundle db = ResourceBundle.getBundle("db");
        String driver = db.getString("driver");
        String url = db.getString("url");
        String user = db.getString("user");
        String password = db.getString("password");
        int count=0;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, user, password);
            connection.setAutoCommit(false);
            statement = connection.prepareStatement("insert into t_user(usercode,username) values (?,?)");
            statement.setString(1,ucode);
            statement.setString(2,uname);
            count= statement.executeUpdate();
            connection.commit();
        } catch (Exception e) {
            if (connection!=null){
                try {
                    connection.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }
        if (count==1){
            // 转发重定向
           // req.getRequestDispatcher("/success.html").forward(req,resp);
            resp.sendRedirect("/J2EE/success.html");
        }
    }
}

28:Servelet实现登录

package com.fangjun.javaee;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
import java.util.ResourceBundle;

public class login extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String name = req.getParameter("name");
        String password = req.getParameter("password");
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;
        ResourceBundle db = ResourceBundle.getBundle("db");
        String driver = db.getString("driver");
        String url = db.getString("url");
        String user = db.getString("user");
        String pass = db.getString("password");
        boolean flag=false;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url,user,pass);
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement("select *from t_user where username=? and password=?");
            preparedStatement.setString(1,name);
            preparedStatement.setString(2,password);
            resultSet=preparedStatement.executeQuery();
            if (resultSet.next()){
                flag=true;
            }
            connection.commit();
        } catch (Exception e) {
            if (connection!=null){
                try {
                    connection.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
            e.printStackTrace();
        }finally {
            if (resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        if (flag){
            System.out.println("success");
            System.out.println(req.getContextPath());
            resp.sendRedirect(req.getContextPath()+"/success.html"); //注意路径名称的完成
        }else{
            System.out.println("error");
            resp.sendRedirect(req.getContextPath()+"/error.html");
        }
    }
}

29:Cookie详解

会话状态保存在客户端硬盘
1)Cookie是什么?
Cookie可以保存会话状态,但是这个会话状态是保存在客户端上。
只有Cookie被清楚,或者Cookie失效,这个会话状态就没有了
Cookie是保存在浏览器客户端的。
Cookie可以保存在浏览器的缓存中,浏览器关闭Cookie消失
Cookie也可以保存在客户端的硬盘上,浏览器关闭Cookie还在,除非Cookie失效。
2)Cookie实现的功能常见有哪些?
十天免登陆,保留商品在购物车中
3)在java中Cookie被当做类来处理,使用New运算符号,可以创建Cookie对象,而且Cookie由两部分组成,分别是Cookie的name和value,这两者都是String类型。
4)在java中如何创建cookie

        Cookie cookie = new Cookie("username", "zhangsan");
        Cookie cookie1 = new Cookie("password", "123");
        resp.addCookie(cookie);
        resp.addCookie(cookie1);

5)服务器可以发送多个Cookie

6)默认情况下保存在浏览器的缓存中,只要浏览器不关闭,Cookie永远存在。

7)请求路径与Cookie与紧密关联,不同请求路径会提交不同的Cookie
在这里插入图片描述

8)通过设置Cookie的有效时长,以保证Cookie保存到硬盘文件中。

cookie1.setMaxAge()

30:HttpSession详解

31:3.0 Servlet新特性

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值