热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

web基础2servlet入门1(request,response)

web基础2-servlet入门1(request,response)一、Servlet1.1servlet简介Servlet就是sun公司开发动态web的一门技术Sun在这些AP

web基础2-servlet入门1(request,response)

一、Servlet


1.1 servlet简介



  • Servlet就是sun公司开发动态web的一门技术



  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成3个步骤:



    • 编写一个类,实现servlet接口

    • 把开发好的Servlet注册在web.xml中

    • 把开发好的JAVA类部署到web服务器中



把实现了Servlet接口的java程序叫做servlet


1.2 第一个servlet-HelloServlet


servlet在sun公司有两个默认继承类,Httpservlet,GenericServlet



1.2.1 构建父子工程。(也可以不用父子工程)

构建一个普通的maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立module了。这个空的工程就是maven主工程。详细见1.3


1.2.2 Maven环境优化



  • 修改web.xml为最新的,换头

  • 将maven的结构搭建完毕


1.2.3 编写一个servlet程序



  • 编写一个普通类

  • 实现一个servlet接口,我们这里直接继承Httpservlet


idea中查看继承关系树

方法一:

ctrl+H

方法二:

ctrl+alt+U


1.2.4 编写servlet映射

为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接的web服务器,所以我们需要:



  • 在web服务器中注册我们写的servlet



  • 还需要给他一个浏览器能够访问的路径。





helloServlet
com.happy.servlet.HelloWorld


helloServlet

/hello


1.2.5 配置tomcat

注意:配置项目发布的路径即可


1.3 关于maven 父子工程的理解

注意:有时候用idea创建子项目的时候,parent标签会丢失,注意检查项目

父项目中会有


servlet-01

子项目中会有


PureMavenWeb
org.example
1.0-SNAPSHOT

父项目中的java子项目可以直接使用,而子项目中的父项目不能使用。同多态一样。


二、servlet原理


三、Mapping问题


3.1 一个Servlet请求可以指定一个映射路径



helloServlet
com.happy.servlet.HelloWorld


helloServlet

/hello


3.2 一个Servlet可以指定多个映射路径


helloServlet
com.happy.servlet.HelloWorld


helloServlet

/hello


helloServlet

/hello2


3.3 一个Servlet可以指定通用映射路径


helloServlet

/hello/*


3.4 自定义后缀实现请求映射

注意:前面不能加映射的路径,如/hello/*.do


helloServlet
com.happy.servlet.HelloWorld


helloServlet

*.do


3.5 默认请求路径(兜底)


helloServlet
com.happy.servlet.HelloWorld


helloServlet

/*


3.6 优先级匹配

指定了固有的映射路径=》优先级最高。

如果找不到就会走默认的处理请求/*


四、servlet重要对象和API


4.1 init-parm vs context-param


loginServlet
com.qcc.study.servlet02.LoginServlet


initParam

qcc


0


loginServlet
/login


contextParam

admin

配置在标签中,用来初始化当前的Servlet的,属于当前Servlet的配置,因此存放在 servletConfig对象中;

通过getServletConfig().getInitParameter("initParam")的方式获取;

直接配置在web.xml的标签中,属于上下文参数,在整个web应用中都可以使用,它是全局的,因此存放在servletContext对象中(即application对象);

通过getServletContext().getInitParameter("contextParam")的方式获取;

4.2 ServletContext


web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。(在容器启动时候就有)


作用:


4.2.1 共享数据


我在这servlet中保存的数据,可以在另外一个servlet获取。

注意:实际工作中,一般不用servletContext存取数据,一般用session和COOKIE和request存取数据


一个servlet用于通过ServletContext来set数据

package com.happy.servlet;
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;
import java.io.IOException;
import java.io.PrintWriter;
public class SetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext servletCOntext= this.getServletContext();
//
//
//

happyContextParam
//

admin
//
String happy = servletContext.getInitParameter("happyContextParam");
System.out.println(happy);
int i=0;
Object object= servletContext.getAttribute("happy");
if (object==null){
i=0;
} else {
i=(int)object+1;
}
servletContext.setAttribute("happy",i);
ServletConfig servletCOnfig= this.getServletConfig();
String happyServletParam = servletConfig.getInitParameter("happyServletParam");
System.out.println(happyServletParam);
PrintWriter writer = resp.getWriter();
writer.println("访问次数+1");
writer.println("http://localhost:8080/s2/get");
System.out.println(i);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPut(req, resp);
}
}

一个servlet用于通过ServletContext来get数据

package com.happy.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletCOntext= this.getServletContext();
Object happy = servletContext.getAttribute("happy");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("访问次数共计:"+happy);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}

web.xml如下

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"
version="4.0"
metadata-complete="true">


happyContextParam

admin


SetServlet
com.happy.servlet.SetServlet

happyServletParam

happyvalue



SetServlet
/set/*


GetServlet
com.happy.servlet.GetServlet


GetServlet
/get



4.2.2 获取初始化参数


可以用来配置一些web应用初始化参数

注意:实际工作中一般不在web.xml中放参数,而用properties文件等存全局参数




happyContextParam

admin


setByConf

setByConfValue

package com.happy.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;
public class GetInitParamsServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletCOntext= this.getServletContext();
String setByCOnf= (String)servletContext.getInitParameter("setByConf");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("setByConf:"+setByConf);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}

4.2.3 请求转发


实际工作中一般不用ContextServlet对象的dispatcher,而用response对象的dispatcher方法


package com.happy.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;
public class ContextDispatcherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletCOntext= this.getServletContext();
servletContext.getRequestDispatcher("/get").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}


ContextDispatcherServlet
com.happy.servlet.ContextDispatcherServlet


ContextDispatcherServlet
/cds


4.2.4 读取项目资源文件


实际工作中一般不用这个api,而是用反射和类加载等加载资源文件



前景补充知识

关于classpath


  • java目录,作为source目录

  • resources目录,作为resources目录

对回被打包到同一个路径下:classes,我们俗称这个路径为classpath:


maven构建时候,部分source目录下面资源文件不能打包问题

解决方案:在build中配置resources.来防止我们资源导出失败的问题




src/main/resources

**/*.properties
**/*.xml

true


src/main/java

**/*.properties
**/*.xml

true




获取资源文件

写一个servlet调用context对象的获取资源文件的api方法getResourceAsStream

InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");


PropertiesServlet
com.happy.servlet.PropertiesServlet


PropertiesServlet
/ps

package com.happy.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.InputStream;
import java.util.Properties;
public class PropertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletCOntext= this.getServletContext();
InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println(url+" "+username+" "+password);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}

效果如下:


4.3 HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个httpServeletResponse。



  • 如果要获取客户端请求过来的参数:找HttpServeletRequest

  • 如果要给客户端响应一些信息:找HttpServeletResponse


4.3.1 HttpServletResponse简单分类


负责向浏览器发送数据的方法

ServletOutputStream getOutputStream() throws IOException; //其他,如果老用中文会造成字符窜丢失
PrintWriter getWriter() throws IOException; //中文

负责向浏览器设置响应头方法

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setBufferSize(int var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);

响应的状态码:

int SC_COnTINUE= 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_COnTENT= 204;
int SC_RESET_COnTENT= 205;
int SC_PARTIAL_COnTENT= 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_COnFLICT= 409;
int SC_GOnE= 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LOnG= 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

4.3.2 HttpServletResponse常见应用


1. 向浏览器输出消息

2.下载文件resp.setHeader("Content-disposition","attachment;filename"+filename);

核心:

resp.setHeader("Content-disposition","attachment;filename="+filename);

URLEncoder.encode(filename,"utf-8")) //解决文件名乱码


  1. 要获取下载文件的路径

  2. 下载文件名是啥

  3. 设置想办法让浏览器能够支持下载我们需要的东西

  4. 获取下载文件的输入流

  5. 创建缓存区

  6. 获取OutputStream对象

  7. 将FIleOutputStream流写入到buffer缓冲区

  8. 使用outputstream将缓冲区中的数据输出到客户端

package com.happy.servlet;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class DownServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/* 1. 要获取下载文件的路径
2. 下载文件名是啥
3. 设置想办法让浏览器能够支持下载我们需要的东西
4. 获取下载文件的输入流
5. 创建缓存区
6. 获取OutputStream对象
7. 将FIleOutputStream流写入到buffer缓冲区
8. 使用outputstream将缓冲区中的数据输出到客户端*/
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/书.jpg");
System.out.println(realPath);
String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
System.out.println(filename);
// resp.setHeader("Content-disposition","attachment;filename"+filename);
String userAgent = req.getHeader("USER-AGENT");
if (StringUtils.contains(userAgent, "MSIE") || StringUtils.contains(userAgent, "Edge")) {
// IE浏览器
filename = URLEncoder.encode(filename, "UTF-8");
} else if (StringUtils.contains(userAgent, "Firefox") || StringUtils.contains(userAgent, "Chrome") || StringUtils.contains(userAgent, "Safari")) {
// google,火狐浏览器
// filename = new String(filename.getBytes(), "ISO-8859-1");
filename = URLEncoder.encode(filename, "UTF-8");
} else {
filename = URLEncoder.encode(filename, "UTF-8");
// 其他浏览器
}
System.out.println(filename);
resp.setHeader("Content-disposition", "attachment;filename=" + filename);
// 创建输入流,把文件变成流
FileInputStream is = new FileInputStream(realPath);
// 创建输出流
ServletOutputStream os = resp.getOutputStream();
// 创建缓存区,new 一个byte【】作为byte
byte[] buff = new byte[1024];
int len = 0;
try {
System.out.println("开始读取数据");
while ((len = is.read(buff)) > 0) {
os.write(buff, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
is.close();
os.close();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

3.生成验证码

原生生成验证码方法:

package com.happy.servlet;
import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 前端刷新为windows.location.refresh
// 通过后端响应给前端设置头信息,响应可以设置前端所有东西
response.setHeader("refresh","8");
BufferedImage bufferedImage=drawNum();
// 告诉浏览器,这个请求的响应用图片方式打开
response.setContentType("image/png");
// 取消缓存
response.setDateHeader("expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
boolean jpg = ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Test
public BufferedImage drawNum(){
// 在内存中创建一个空白的图片
BufferedImage bufferedImage = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
// 设置图片的背景颜色
graphics.setColor(Color.white);
// 画边框
graphics.fillRect(0,0,80,20);
// 给图片写数据
graphics.setColor(Color.blue);
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.drawString(makeNum(),0,20);
return bufferedImage;
}
public String makeNum(){
Random random = new Random();
String num = String.valueOf(random.nextInt(999999+1));
StringBuffer sb = new StringBuffer(num);
for(int i=0;i<=5-num.length();i++){
sb.append(0);
}
return sb.toString();
}
}


4.实现重定向

本质上是302和location设置重定向地址


response.sendRedirect();

常见场景:



  • 用户登陆

package com.happy.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 方式一
// 可以直接重定向到外部网站
// response.sendRedirect("http://www.baidu.com");
// 也可以内部地址,要带项目名
response.sendRedirect("/response/image");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}

所以本质上是302和location设置重定向地址

// 方式二,拆分两步
response.setHeader("Location","/response/image");
// response.setStatus(302);
response.setStatus(HttpServletResponse.SC_FOUND);

重定向和转发的区别





















重定向转发
相同点页面实现跳转页面实现跳转
不同点url地址栏会发生变化url不会产生变化

${pageContext.request.contextPath}


登陆跳转(重定向实战)

index.jsp作为登陆页面如下:

<%@ page cOntentType="text/html;charset=UTF-8" language="java" %>





<%--这里提交的路径,需要寻找项目的路径--%>
<%----%>

用户:
密码:




web.xml配置映射


FormServlet
com.happy.servlet.FormServlet


FormServlet
/login

处理servlet

package com.happy.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FormServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("进入这个请求了");
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+":"+password);
response.sendRedirect("/response/success.jsp");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
}

4.4 HttpServletRequest


4.4.1 响应重定向和请求转发


重定向和转发的区别


























重定向转发
相同点页面实现跳转页面实现跳转
不同点url地址栏会发生变化url不会产生变化
状态码302307

重定向response.sendRedirect

注意:重定地址(外部地址)要带项目名

获取方式:



  1. 写死response.sendRedirect("projectContextName/success.jsp");



  2. this.getServletContext().getContextPath()
    response.sendRedirect(this.getServletContext().getContextPath()+"/success.jsp");


  3. request.getContextPath()
    response.sendRedirect(request.getContextPath()+"/success.jsp");




转发request.getRequestDispatcher

注意:转发地址(内部地址)不用带项目名



转发this.getServletContext().getRequestDispatcher

4.4.2 获取前端参数

package com.happy.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+":"+password);
String[] hobbies = request.getParameterValues("hobbies");
System.out.println(Arrays.toString(hobbies));
System.out.println(this.getServletContext().getContextPath());
System.out.println(request.getContextPath());
// 方式一:response redirect转发
// response.sendRedirect(this.getServletContext().getContextPath()+"/success.jsp");
// 方式二:servletContext 重定向
// this.getServletContext().getRequestDispatcher("/success.jsp").forward(request,response);
//方式三:request 重定向
request.getRequestDispatcher("/success.jsp").forward(request,response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}


推荐阅读
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有