创建项目



Servlet原理


编写Servlet

package com.yang.servlet;
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;
/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/4 14:19
 */
public class MyServlet extends HttpServlet {
    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.print("MyServlet is Mapping Successfully");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

映射Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="4.0"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         metadata-complete="true">

    <!--注册Servlet-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <!--指定Servlet类-->
        <servlet-class>com.yang.servlet.MyServlet</servlet-class>
    </servlet>
    <!--给定访问路径-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <!--指定访问路径-->
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>

</web-app>

配置项目路径

测试

建立子项目的方式建立也可以,可以参考 https://blog.nowcoder.net/n/1af78e06fe594514b258307227e8ce33

映射方式

一对一

    <!--注册Servlet-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <!--指定Servlet类-->
        <servlet-class>com.yang.servlet.MyServlet</servlet-class>
    </servlet>
    <!--给定访问路径-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <!--指定访问路径-->
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>

一对多

    <!--注册Servlet-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <!--指定Servlet类-->
        <servlet-class>com.yang.servlet.MyServlet</servlet-class>
    </servlet>
    <!--给定访问路径-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <!--指定访问路径-->
        <url-pattern>/MyServlet01</url-pattern>
    </servlet-mapping>
        <!--注册Servlet-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <!--指定Servlet类-->
        <servlet-class>com.yang.servlet.MyServlet</servlet-class>
    </servlet>
    <!--给定访问路径-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <!--指定访问路径-->
        <url-pattern>/MyServlet02</url-pattern>
    </servlet-mapping>

通配 *

    <!--注册Servlet-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <!--指定Servlet类-->
        <servlet-class>com.yang.servlet.MyServlet</servlet-class>
    </servlet>
    <!--给定访问路径-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <!--指定访问路径-->
        <url-pattern>/MyServlet/*</url-pattern>
    </servlet-mapping>

注解简化Servlet配置

利用上下文,数据共享

package com.yang.servlet;


import javax.servlet.ServletContext;
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;

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/4 14:19
 */
public class MyServlet extends HttpServlet {
    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.print("MyServlet is Mapping Successfully");
        //获取上下文   servletContext可以保存一些数据
        ServletContext servletContext = this.getServletContext();
        String username="Vis.Yang";
        //将一个数据保存在了servletContext中,名字为:name,值为"username"
        servletContext.setAttribute("name",username);



    }

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

package com.yang.servlet;

import javax.servlet.ServletContext;
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;

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/5 21:17
 */
public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String name = (String) servletContext.getAttribute("name");
        PrintWriter writer = resp.getWriter();
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        writer.print(name);

    }

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

获取初始化参数

<context-param>
        <param-name>paramName</param-name>
        <param-value>jdbc:mysql://localhost:3306/databaseName</param-value>
</context-param>

package com.yang.servlet;

import com.sun.org.apache.bcel.internal.generic.NEW;

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

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/5 22:04
 */
public class GetParameter extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取初始化参数
        ServletContext servletContext = this.getServletContext();
        String initParameter = servletContext.getInitParameter("paramName");
        resp.getWriter().print(initParameter);
    }

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



HttpServletRequest  接收请求
//获取客户机IP地址  String remoteAddr = req.getRemoteAddr(); System.out.println(remoteAddr)

package com.yang.servlet;


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;


/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/4 14:19
 */
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.print("MyServlet is Mapping Successfully");
        //获取请求时的完整路径(从http开始,到"?"前面结束)
        String url = request.getRequestURL() + "";
        System.out.println("获取请求时的完整路径:" + url);
        //获取请求时的部分路径(从项目的站点名开始,到"?"前面结束)
        String uri = request.getRequestURI();
        System.out.println("获取请求时的部分路径:" + uri);
        //获取请求时的参数字符串(从"?"后面开始,到最后的字符串)
        String queryString = request.getQueryString();
        System.out.println("获取请求时的参数字符串:" + queryString);
        //获取请求方式(Get/Post)
        String method = request.getMethod();
        System.out.println("获取请求方式:"+method);
        //获取当前协议版本(Http/1.1)    protocol  /ˈproʊtəkɑːl/
        String protocol = request.getProtocol();
        System.out.println("获取当前协议版本:"+protocol);
        //获取项目站点名(项目对外访问路径)
        String contextPath = request.getContextPath();
        System.out.println("获取项目站点名:"+contextPath);

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
package com.yang.servlet;


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;


/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/4 14:19
 */
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.print("MyServlet is Mapping Successfully");
        /*获取请求的参数*/
        //获取指定名称的参数值
        String uname = request.getParameter("uname");
        String pwd = request.getParameter("pwd");
        System.out.println("浏览器传来的用户名:"+uname+"以及密码:"+pwd);
        //获取指定名称的所有参数值(用于复选框传值)
        String[] hobbies = request.getParameterValues("hobby");
        if (hobbies!=null&&hobbies.length>0){
            for (String hobby : hobbies) {
                System.out.println(hobby);
            }
        }

    }

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

获取请求头

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //获取请求头
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            //根据名称获取请求头的值
            String value = req.getHeader(name);
            System.out.println(name+"  :  "+value);
        }
    }

结果:

host  :  localhost:8080
connection  :  keep-alive
cache-control  :  max-age=0
sec-ch-ua  :  "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile  :  ?0
upgrade-insecure-requests  :  1
user-agent  :  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
accept  :  text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site  :  none
sec-fetch-mode  :  navigate
sec-fetch-user  :  ?1
sec-fetch-dest  :  document
accept-encoding  :  gzip, deflate, br
accept-language  :  zh-CN,zh;q=0.9

通常这样操作,不用获取全部



获取请求体


获取请求参数通用方法







POST请求乱码问题


表单提交出错404解决办法

https://blog.nowcoder.net/n/c80472eac248433bac452b91520e9dd5

请求转发:一种在服务器内部的资源跳转方式

RequestDispatcher requestDispatcher = req.getRequestDispatcher("/s02"); requestDispatcher.forward(req, resp);
package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/7 11:24
 */
@WebServlet("/s01")
public class MyServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MyServlet被访问了");
        //转发Servlet02
        req.getRequestDispatcher("/s02").forward(req, resp);

        //RequestDispatcher requestDispatcher = req.getRequestDispatcher("/s02");
        //requestDispatcher.forward(req, resp);

    }


}
package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/7 11:24
 */
@WebServlet("/s02")
public class Servlet02 extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet02也被访问了");
    }


}


特点: 浏览器访问地址栏不发生变化  只能转发到当前服务器内部资源中 转发使用的是同一次请求

数据共享


package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name MyServlet
 * @date 2021/8/7 11:24
 */
@WebServlet("/s01")
public class MyServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("msg","MyServlet's Data");
        req.getRequestDispatcher("/s02").forward(req,resp);
    }


}
package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name Servlet02
 * @date 2021/8/7 11:24
 */
@WebServlet("/s02")
public class Servlet02 extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object msg = req.getAttribute("msg");
        System.out.println(msg);
               //打印的是MyServlet中request里保存的数据
    }


}

HttpServletResponse 处理请求

重定向:资源跳转方式

package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name 重定向
 * @date 2021/8/7 11:24
 */
@WebServlet("/s01")
public class MyServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MyServlet is visited");
        //设置状态码,
        resp.setStatus(302);
        //设置响应头location
        resp.setHeader("location","/s02");

    }


}
package com.yang.servlet;

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;

/**
 * @author Vis.Yang
 * @project_name
 * @date 2021/8/7 11:24
 */
@WebServlet("/s02")
public class MyServlet02 extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MyServlet02 is visited too");
    }


}

简化重定向

//设置状态码 //resp.setStatus(302); //设置响应头location //resp.setHeader("location","/s02");  resp.sendRedirect("/s02");

特点:地址栏改变 可以访问其他站点(服务器)的资源  重定向是两次请求


路径



package com.yang.servlet;


import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author Vis.Yang
 * @project_name 重定向
 * @date 2021/8/7 11:24
 */
@WebServlet("/s01")
public class MyServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请参数,文件名称
        String filename = req.getParameter("filename");
        //2.使用字节输入流加载文件进内存
        //2.1 找到文件的服务器路径
        ServletContext servletContext = this.getServletContext();
        String realPath = servletContext.getRealPath("/img/" + filename);
        //2.2 用字节流关联
        FileInputStream fileInputStream = new FileInputStream(realPath);
        //3.设置HttpServletResponse 的响应头
        //获取文件的mime类型
        String mimeType = servletContext.getMimeType(filename);
        resp.setHeader("content-type", mimeType);
        resp.setHeader("content-disposition", "attachment;filename=" + filename);
        //4.将输入流的数据写出到输出流
        ServletOutputStream outputStream = resp.getOutputStream();
        byte[] buff = new byte[1024 * 8];
        int len = 0;
        while ((len = fileInputStream.read(buff)) != -1) {
            outputStream.write(buff, 0, len);
        }
        fileInputStream.close();
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Download</title>
</head>
<body>
<a href="/s01?filename=1.jpg">点击下载图片</a>
<a href="/s01?filename=1.flv">点击下载视频</a>
</body>
</html>

jsp   

jsp代码不外露,安全


注意点:

  • 表达式结尾没有分号
  • 表达式可以是常量、变量、表达式或方法调用(要有返回值)
  • 使用 out.print( ) 将结果输出,以字符串的形式显示在页面上
<%@ page language="java" import="java.util.*"
	contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>声明 变量 方法</title>
<%!
	/* 声明 变量 方法 */
	int count = 0;

	int count(int i) {
		i += 1;
		return i;
	}
%>

</head>
<body>
	i=<%=count(count)%>
	<% out.print("打印到屏幕"); %>
	<% out.print("打印到屏幕i="+count(count)); %>
</body>
</html>

<body>
	i=<%=count(count)%>
	<% 
	out.print("打印到screen"); 
	%>
	<%
	out.print("打印到screen i="+count(count)); 
	System.out.println("打印到Console i="+count(count));
	%>
</body>
<%!
    /* 声明 变量 方法 */
    int count = 0;
%>
全局变量
-------------------------------------------
<%
int count = 0;
>%
局部变量
<% 
    out.print("打印到screen"); 
    /* 页面添加换行 out.print("<br>"); */
    out.print("<br>"); 
%>
<%--
jsp注释 浏览器不可见
 <%!
	/* 声明 变量 方法 */
	int count = 0;

	int count(int i) {
		i += 1;
		return i;
	}
%> 
--%>
<%-- jsp注释 --%>

实际开发中,大量Java代码夹杂在静态页面里,不好维护与查看,后期将使用El表达式和Jstl标签库,减少java代码