版权声明:如需转载或引用请声明原文网址 https://blog.csdn.net/u013087359/article/details/81844990
1.Servlet
1.1 web.xml
<!-- 默认首页,从上到下依次查找,如果找到则显示,找不到则继续往下找 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<!-- servlet名称 -->
<servlet-name>MyServlet</servlet-name>
<!-- Servlet的完整路径 -->
<servlet-class>com.servlet.MyServlet</servlet-class>
<!-- 初始化变量,可以在Servlet的inti()被访问 -->
<init-param>
<param-name>var</param-name>
<param-value>我是变量值</param-value>
</init-param>
<!-- 在Tomcat启动时就创建本Servelt,值越小优先级越大 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 这里的servlet名称对应上面的servlet名称-->
<servlet-name>MyServlet</servlet-name>
<!-- 浏览器访问servlet的url -->
<!-- 多个url-pattern从上到下查找 -->
<!-- 1.完全匹配方式,必须以/开头 -->
<url-pattern>/MyServlet</url-pattern>
<!-- 2.目录模糊匹配,必须以/开头,这里只需输入/ABC就能匹配,后面可以输入任何东西 -->
<url-pattern>/ABC/*</url-pattern>
<!-- 3.后缀名模糊匹配,不能使用/开头,以.jsp结尾的url都能匹配 -->
<url-pattern>*.jsp</url-pattern>
<!-- 4.任意匹配,所有url都能匹配到 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
1.2 HttpServlet
package com.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//Servlet由Tomcat创建,默认是首次访问本Servlet创建
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//init()在Servlet创建时访问,因为Servlet只会创建一次,所以init()也只会被访问一次
public void init(ServletConfig config) throws ServletException {
//获取web.xml的servlet-name
String servletName=config.getServletName();
//获取web.xml的init-param
String var=config.getInitParameter("var");
ServletContext sc= config.getServletContext();
System.out.println(servletName);
System.out.println(var);
}
//Tomcat关闭时会执行一次
public void destroy() {
}
//每次请求都会访问该方法
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是service");
}
//service()方法根据get请求访问doGet()方法
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是doGet");
}
//service()方法根据get请求访问doPost()方法
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是doPost");
}
}
1.3登录例子
- login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/Web01/LoginServlet" method="post">
用户名:<input type="text" name="username"><br>
密码:<inputtype="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
- LoginServlet
package com.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.domain.User;
import com.util.C3P0Util;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置请求和响应的编码
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
//获取参数值
String username=request.getParameter("username");
String password=request.getParameter("password");
//构建sql语句
String sql="select * from user where username=? and password=?";
//执行查询
QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
User user=null;
try {
user= qr.query(sql, new BeanHandler<>(User.class),username,password);
} catch (SQLException e) {
e.printStackTrace();
}
//根据查询结果判断安是否登录成功
if(user==null) {
out.print("登录失败!用户名与密码不匹配!!!");
}else {
out.println("<h1>登录成功</h1>");
out.print(user);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.ServletContext
ServletContext是Web应用的上下文对象,封装了有关应用的信息,一个Web应用只有一个ServletContext,随着项目启动而存在,随着项目停止而销毁。
2.1 获取ServletContext对象
//1.使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();
//2.使用request获取ServletContext
ServletContext context=request.getServletContext();
2.2 获取web.xml全局变量
- web.xml
<web-app>
<!-- 在web-app节点下定义全局变量 -->
<context-param>
<param-name>globalVar</param-name>
<param-value>我是全局变量</param-value>
</context-param>
</web-app>
- ContextServletServlet
public class ContextServletServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在Servlet中可以直接获取ServletContext对象
ServletContext context= this.getServletContext();
//获取web.xml全局变量
String value=context.getInitParameter("globalVar");
System.out.println(value);
}
2.3 获取物理路径
//使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();
//getRealPath()参数是相对与网站的路径,按照发布到Tomcat中的路径为准,与Eclipse文件结构无关
String realPath=context.getRealPath("WEB-INF/classes/c3p0-config.xml");
System.out.println(realPath);
2.4 域对象
//ServletContext域对象存储的数据可以被所有Web动态资源访问(共享)
//把数据online_count存放到ServletContext中
context.setAttribute("online_count", 0);
//从ServletContext中取出数据online_count
int count=(int)context.getAttribute("online_count");
3. Response
3.1 重定向
- 重定向是来回两次请求响应
- 地址栏会改变
- 重定向会先执行sendRedirect()后面的代码再跳转
- 可以重定向站外资源
//重定向方式1
//设置302状态码
response.setStatus(302);
//设置响应头的Location值
response.setHeader("Location", "http://www.baidu.com");
//重定向方式2
//重定向中以/开头是相对于服务器的,所以需要手动加上网站名称
response.sendRedirect("/Web02/TestServlet");
//等待5秒后跳转
response.setHeader("refresh", "5;url=http://www.baidu.com");
3.2 设置字符编码防止乱码
//设置字符串编码
response.setCharacterEncoding("UTF-8");
//设置文件类型和字符编码,要在输出内容前设置编码才生效
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("你好");
3.3 文件下载
// 获取客户端传递过来的要下载的文件名
String filename = request.getParameter("filename");
// 解决get请求的中文乱码
filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8");
// 设置文件的MIME
response.setContentType(this.getServletContext().getMimeType(filename));
/* ↓ ↓ ↓兼容下载文件中文名乱码↓ ↓ ↓ */
String encodeFilename="";
String userAgent = request.getHeader("User-Agent");
if (userAgent.indexOf("MSIE")!=-1 || userAgent.indexOf("Trident")!=-1 || userAgent.indexOf("Edge")!=-1 ) {
// IE浏览器
encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");
} else if (userAgent.contains("Firefox")) {
// 火狐浏览器
encodeFilename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器(IE10+,Edge,谷歌测试都成功) ,空格在转码时会变成+,所以需要替换回去
encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");
}
/* ↑ ↑ ↑ 兼容下载文件中文名乱码 ↑ ↑ ↑ */
// 告知浏览器下载的附件和文件名
response.setHeader("Content-Disposition", "attachment;filename=" + encodeFilename);
// 获取文件的物理路径
String realPath = this.getServletContext().getRealPath("/imgs/" + filename);
// 把文件写出到客户端
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));
OutputStream os = response.getOutputStream();
int len;
byte[] bs = new byte[1024];
while ((len = bis.read(bs)) != -1) {
os.write(bs, 0, len);
}
os.close();
bis.close();
4.Request
4.1 获取请求行信息
//地址栏网址:http://localhost:6060/Web03/RequestServlet?key=name&value=zhangsan
// GET
String method=request.getMethod();
// http://localhost:6060/Web03/RequestServlet
StringBuffer url=request.getRequestURL();
// /Web03/RequestServlet
String uri=request.getRequestURI();
// /Web03
String contextPath=request.getContextPath();
// /RequestServlet
String servletPath=request.getServletPath();
// key=name&value=zhangsan
String queryString=request.getQueryString();
//获取客户端的IP地址
String ip=request.getRemoteAddr();
//获取客户端的主机名
String host=request.getRemoteHost();
//获取客户端的端口号
int port=request.getRemotePort();
4.2 获取请求头信息
// 获取浏览器信息
String userAgent = request.getHeader("User-Agent");
if (userAgent.indexOf("MSIE") != -1 || userAgent.indexOf("Trident") != -1 || userAgent.indexOf("Edge") != -1) {
System.out.println("我是IE浏览器");
} else if (userAgent.contains("Firefox")) {
System.out.println("我是火狐浏览器");
} else {
System.out.println("我是其他浏览器");
}
// 获取访问来源网址
String referer=request.getHeader("referer");
if(referer!=null&&referer.startsWith("http://localhost:6060/Web03")) {
out.print("正常访问");
}else {
out.print("站外访问,盗链访问");
}
4.3 获取请求参数值
//解决post请求参数的中文乱码问题
request.setCharacterEncoding("UTF-8");
//获取查询字符串参数的值
String operate=request.getParameter("operate");
//解决get请求参数或查询字符串中文乱码问题
operate=new String(operate.getBytes("ISO-8859-1"),"UTF-8");
System.out.println(operate);
//1.获取表单参数的值
String username=request.getParameter("username");
System.out.println(username);
//2.获取拥有多个值的参数
String[] hobby=request.getParameterValues("hobby");
for(String s : hobby) {
System.out.println(s);
}
//3.获取所有参数的名称
Enumeration<String> names=request.getParameterNames();
while(names.hasMoreElements()) {
System.out.println(names.nextElement());
}
System.out.println("------------------------------");
//4.获取所有的参数名称和参数值
Map<String, String[]> parameterMap=request.getParameterMap();
for (Entry<String,String[]> entry : parameterMap.entrySet()) {
String key=entry.getKey();
for (String value : entry.getValue()) {
System.out.println("key:"+key+",value:"+value);
}
}
}
4.4 请求转发
请求转发:客户端发送请求到服务器端某一个处理程序,该程序把处理权转发给另一个程序,最好把处理结果响应给客户端
- 转发过程浏览器只发送了一次请求
- 原处理程序和被转发的处理程序的Request对象是共用的
- 地址栏不会改变
- 转发等同于一个普通方法,所以执行到forward()方法会马上去执行被转发的处理程序的代码,执行完毕后再执行原处理程序forward()后面的代码
- 不能转发站外资源
public class Servlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getParameter("username");
//输出zhangsan
System.out.println(username);
//在请求域中存储数据
request.setAttribute("data", "mydata");
//在网站内部访问站内资源不需要以网站名称开头
//转发时把request和response传递给下一个Servlet,所以下一个Servlet也可以从request中获取同样的信息
request.getRequestDispatcher("/Servlet2").forward(request, response);
}
public class Servlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//这里的数据跟Servlet1的数据是一样的
String username=request.getParameter("username");
//从请求域中获取数据
String data=(String)request.getAttribute("data");
//从请求域中移除数据
request.removeAttribute("data");
//输出zhangsan
System.out.println(data);
//输出mydata
System.out.println(username);
}
}
4.5 Request域对象
- 只在单次请求中数据共享(请求转发也有效)
- 代码参考4.3例子
5. 总结区别
5.1 重定向与转发区别
- 重定向两次请求,转发一次请求
- 重定向地址栏的地址变化,转发地址不变
- 重新定向可以访问外部网站 转发只能访问内部资源
- 转发的性能要优于重定向
5.2 客户端访问服务器端资源与服务器端访问站内资源的路径区别
- 前端页面所有访问服务器端资源都要在路径前面加上网站名称(
/网站名称/XXX
) - 服务器端资源访问站内资源不需要加上网站名称(
/XXX
),包括各种静态资源,转发资源 - 重定向需要加上网站名称,因为重定向是先响应到客户端,再次发起的请求