创建项目
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代码

京公网安备 11010502036488号