tomcat-jsp-servlet


准备

tomcat windows startup.bat shutdown.bat
mac下: startup.sh shutdown.sh

tomcat的运行依赖 JAVA_HOME系统环境变量

tomcat输入地址后 localhost:8080 默认是访问的是ROOT工程
当有工程名时,默认访问index界面

idea 整合 tomcat



创建项目

创建好的web工程

src目录 存放自己编写的java源代码
web目录 专门用来存放web工程的资源文件,比如 html页面、css文件、js文件等等

WEB-INF目录 是一个受服务器保护的目录,浏览器无法访问此目录的内容
WEB-INF/web.xml 它是整个动态web工程的配置描述文件,可以配置很多web工程的组件,比如: servelet程序、filter过滤器、session超时等等
WEB-INF/lib文件夹 用来存放第三方的jar包,IDEA还需要自己配置导入



修改访问路径

Application context是工程路径
更改这里就可以了

修改运行端口号

热部署

Servlet

什么是servlet

  1. servlet是javaEE规范之一。规范就是接口
  2. servlet是javaWeb三大组件之一。三大组件就是servlet程序、filter过滤器、listener监听器
  3. servlet是运行在服务器上的java小程序,他可以接收客户端发过来的请求并相应数据给客户端

手动实现servle程序

  1. 编写一个类去实现Servlet接口
  2. 实现service方法、处理请求并相应数据
  3. 到web.xml配置servlet程序的访问地址

com.kcl.servlet.HelloServlet

点击查看代码
package com.kcl.servlet;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloServlet 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 {
        System.out.println("hello servlet被访问了");
    }

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

    @Override
    public void destroy() {

    }
}

web.xml配置servlet

点击查看代码
    
    
        
        HelloServlet
        
        com.kcl.servlet.HelloServlet
    


    
    
        HelloServlet
        /hello
    

访问
http://localhost:9517/superkcl/hello

servlet生命周期

  1. 执行servlet构造器方法(自己创建)
  2. 执行init初始化方法
  3. 执行servciefangfa
  4. 执行destroy方法

第一第二步是在创建servlet时被调用
每次调用接口,都会执行service 方法
工程停止时会调用destory方法

HttpservletRequest 继承 ServletRequest

    //处理请求并响应
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("hello servlet被访问了");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String method = request.getMethod();
        System.out.println(method);
    }

GET

开发时不继承Servlet接口而是其子类HttpServlet方式实现

public class HelloServlet2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       // super.doGet(req, resp);
        System.out.println("helloservlet 2 doGet方法");
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //super.doPost(req, resp);
        System.out.println("helloservlet 2 doPost方法");
    }

}

使用idea创建servlet程序

在包目录下点击右键 new->Create new Servlet

配置一下ServletMapping即可

Servlet类继承体系

servlet实现类: GenericServlet实现servlet接口,对servlet接口做了很多空实现
并持有一个ServletConfig类的引用。并对ServletConfig的使用做一些方法。

HttpServlet继承GenericServlet类
HttpServlet是抽象类,主要实现service方法
实现servcie方法,和我们的理解差不多 req.getMethod();
doGet() doPost()负责抛异常

ServletConfig类

三大作用

  1. 可以获取servlet程序的别名servlet-name的值
  2. 获取初始化参数init-param
  3. 获取servletContext对象
    
        
        HelloServlet
        
        com.kcl.servlet.HelloServlet
        
            username
            root
        
        
            url
            jdbc:mysql://localhost:3306/test
        
    
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");

        //1. 可以获取servlet程序的别名servlet-name的值
        System.out.println(servletConfig.getServletName());
        //2. 获取初始化参数init-param
        System.out.println(servletConfig.getInitParameter("username"));
        System.out.println(servletConfig.getInitParameter("url"));
        //3. 获取servletContext对象
        System.out.println(servletConfig.getServletContext());

    }

servlet程序默认是第一次访问的时候创建,servletConfig是每个servlet程序创建时,就创建一个对应的servletConfig对象

继承HttpServlet也可以

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        ServletConfig servletConfig = this.getServletConfig();
        String servletName = servletConfig.getServletName();
        System.out.println(servletName);
    }

ServletContext类

  1. servletContext是一个接口,表示servlet上下文对象
  2. 一个web工程只有一个servletContext对象实例!!!
  3. ServletContext对象是一个域对象
    域对象,是可以像Map一样存取数据的对象,叫域对象
    这里的域指的是存取数据的操作范围
    --- 存数据 取数据 删除数据
    Map put() get() remove()
    域对象 setAttribute() getAttribute() removeAttribute()

ServletContext类的四个作用

  1. 获取web.xml中配置的上下文参数context-param
  2. 获取当前的工程路径,格式: /工程路径
  3. 获取工程部署后在服务器硬盘上的绝对路径
  4. 像map一样存取数据

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 获取web.xml中配置的上下文参数context-param
        ServletContext servletContext = getServletContext();
        System.out.println("username" + servletContext.getInitParameter("username"));
        System.out.println(servletContext.getInitParameter("password"));

        //2. 获取当前的工程路径,格式: /工程路径
        System.out.println(servletContext.getContextPath()); // /superkcl

        //3. 获取工程部署后在服务器硬盘上的绝对路径
        System.out.println(servletContext.getRealPath("/")); //斜杠解析为:http://ip:port/工程名/
        // D:\编程软件\idea2020.1.2\myFile\testTomcat04\out\artifacts\testTomcat04_war_exploded\
        //映射到web目录
        System.out.println(servletContext.getRealPath("/css"));
        //D:\编程软件\idea2020.1.2\myFile\testTomcat04\out\artifacts\testTomcat04_war_exploded\css


        //4. 像map一样存取数据
        servletContext.setAttribute("key01","value01");
        System.out.println(servletContext.getAttribute("key01"));


    }

不同servlet中只要存储了,都可以取到的
在web项目停止后才会销毁。

HttpServletRequet

public interface HttpServletRequest extends ServletRequest
ServletRequest也是一个接口
常用方法
getRequestURI() 获取请求资源路径
getRequestURL() 获取绝对路径
getRemoteHost() 获取客户端ip地址
getHeader() 获取请求头
getParameter() 获取请求的参数
getParameterValues() 获取请求的参数(多个值的时候使用)
getMethod() 获取请求的方式GET或POST
setAttribute(key,val) 设置域数据
getAttribute(key) 获取域数据
getRequestDispatcher() 获取请求转发对象

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //getRequestURI() 获取请求资源路径
        //URI => /superkcl/contextServlet
        System.out.println("URI => "+ request.getRequestURI());


        //getRequestURL() 获取绝对路径
        //URL => http://localhost:9517/superkcl/contextServlet
        System.out.println("URL => "+request.getRequestURL());


        //getRemoteHost() 获取客户端ip地址
        //RemoteHost => 0:0:0:0:0:0:0:1
        System.out.println("RemoteHost => "+ request.getRemoteHost());


        //getHeader() 获取请求头
        //Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
        System.out.println(request.getHeader("User-Agent"));



        //getParameter() 获取请求的参数
        String username = request.getParameter("username");
        System.out.println("username => " + username);
        String password = request.getParameter("password");
        System.out.println("password => " + password);
        String[] hobby = request.getParameterValues("hobby");
        System.out.println("hobby => " + Arrays.asList(hobby));



        //getParameterValues() 获取请求的参数(多个值的时候使用)

        //getMethod() 获取请求的方式GET或POST
        //请求的方式 => GET
        System.out.println("请求的方式 => " + request.getMethod());



        //setAttribute(key,val) 设置域数据
        //getAttribute(key) 获取域数据
        //getRequestDispatcher() 获取请求转发对象


    }
  
用户名:
密码:
兴趣爱好:java cpp js
        //getParameter() 获取请求的参数
        String username = request.getParameter("username");
        System.out.println("username => " + username);
        String password = request.getParameter("password");
        System.out.println("password => " + password);
        String[] hobby = request.getParameterValues("hobby");
        System.out.println("hobby => " + Arrays.asList(hobby));

post请求也是同样的道理
post请求会出现中文乱码
request.setCharacterEncoding("UTF-8");
在获取请求参数之前调用才有效

get请求不会出现中文乱码

请求转发

服务器接收到请求后,从一个资源跳转到另一个资源的操作叫请求转发
......
req.setAttribute只在请求域中有效
servlet1
RequsetDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2")
requestDispatcher.forward(req,resp)
servlet2
处理自己的业务

特点:
1.浏览器地址栏没有变化
2.他们是一次请求
3.他们共享Request域中的数据
4.可以转发到WEB-INF目录下
浏览器是反问不到WEB-INF目录的
dispatcher可以访问到!"/WEB-INF/form.html"
5.是否可以访问到项目以外的网址? 不可以! 默认是访问当前项目下

base标签作用

/的不同含义

  1. 如果被浏览器解析 a标签 得到的地址就是 http://ip:port/
  2. 如果被服务器解析,得到的地址就是 http://ip:port/工程路径
    /servlet
    servletContext.getRealPath("/")
    request.getRequestDispatcher("/")
    特殊情况:

response.sendRediect("/")
请求重定向,把斜杠发送给浏览器解析。得到http://ip:port

HttpServletResponse

类似于HttpServletRequst,每次请求进来,都会创建一个response对象传递给servlet使用

两个流

字节流-getOutputStream();常用于下载,传递二进制数据
字符流 getWriter() 常用于回传字符串(常用)
两个流只能使用一个
使用了字节流,就不能再使用字符流,否则就会报错

public class ResponseIOServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        ServletOutputStream outputStream = resp.getOutputStream();
        //error
    }
}

字符流

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.write("response kcl");
    }

but写中文会乱码

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        //通过响应头,设置浏览器也是用UTF-8
        resp.setHeader("Content-Type","text/html; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("response kcl 寇春雷");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        //一行代码同时设置服务器和客户端都使用UTF-8
        resp.setContentType("text/html; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("response kcl 寇春雷");
    }

请求重定向

客户端请求服务器,服务器返回一个新地址,旧地址废弃
1.浏览器地址栏会发生变化
2.两次请求
3.不共享request域中的数据
4.不能访问WEB-INF下的资源
5.可以重定向至其他网站

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

        //设置响应状态码302,表示重定向
        resp.setStatus(302);
        //设置响应头设置新的地址在哪里
        resp.setHeader("Location","http://localhost:9517/superkcl/hello"); //绝对地址
        
    }

另外一种方法
resp.sendRedirect("http://localhost:9517/superkcl/hello");