1. ServletConfig类是为Servlet程序的配置信息的类
2. Servlet程序和ServletConfig对象都是由Tomcat负责创建
3. Servlet程序默认是第1次访问的时候创建,ServletConfig在Servlet程序创建时,就创建一个对应的ServletConfig对象
1.获取Servlet程序的servlet-name的值
2.获取初始化参数init-param
3.获取ServletContext对象
DBServlet
public class DBServlet extends HttpServlet {
/**
* 梳理ServletConfig config 使用流程
* 1. 当DBServlet对象初始化时, tomcat会同时创建一个 ServletConfig对象
* 2. 这时如果DBServlet init() 方法中你调用 super.init(config);
* 3. 调用 父类 GenericServlet
* public void init(ServletConfig config) throws ServletException {
* this.config = config;
* this.init();
* }
* 这时就会把 Tomcat创建的 ServletConfig对象赋给 GenericServlet的属性 config
* 4. 因此如果你重写init()方法,记住如果你想在其它方法通过 getServletConfig() 方法获取ServletConfig
* , 则一定要记住 调用 super.init(config);
* @param config
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
//ConcurrentHashMap, 是一个线程安全的容器.
System.out.println("init" + config);
super.init(config);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在DBServlet 执行 doGet()/doPost() 时,可以获取到web.xml配置的用户名和密码
//你是一个OOP程序员->现有的方法或对象来搞定
//DBServlet的父类GenericServlet有getServletConfig()
/**
* 1. getServletConfig() 方法是 GenericServlet
* 2. 返回的 servletConfig对象是 GenericServlet private transient ServletConfig config;
* 3. 当一个属性被 transient 修饰,表示该属性不会被串行化(有些重要信息,不希望保存到文件)
*/
ServletConfig servletConfig = getServletConfig();
System.out.println("doPost=" + servletConfig);
String username = servletConfig.getInitParameter("username");
String pwd = servletConfig.getInitParameter("pwd");
System.out.println("初始化参数username= " + username);
System.out.println("初始化参数pwd= " + pwd);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
配置DBServletConfig
DBServlet
com.yinhai.servlet.DBServlet
username
yinhai
pwd
123456
DBServlet
/db
如果需要统计多个Servlet被调用的次数
可以使用DB数据库
或者ServletContext类
1. ServletContext是一个接口, 它表示Servlet上下文对象
2.一个web工程,只有一 一个ServletContext对象实例
3. ServletContext对象是在web工程启动的时候创建,在web工程停止的时销毁
4. ServletContext对象可以通过 ServletConfig.getServletContext() 方法获得对ServletContext对象的引用,也可以通过this.getServletContext()来获得其对象的引用。
5.由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对 象之间可以通过ServletContext对象来实现多个Servlet间通讯。ServletContext对 象通常也被称之为域对象。[ 示意图]
1.获取web.xml中配置的上下文参数context-param [信息和整个web应用相关,而不是属于某个Servlet]
2.获取当前的工程路径,格式: /工程路径
3.获取工程部署后在服务器硬盘上的绝对路径
4.像Map一样存取数据,多个Servlet共享数据
需求如下:
1.获取web.xml中配置的上下文参数context-param
2.获取当前的工程路径,格式: /工程路径
3.获取工程部署后在服务器硬盘上的绝对路径
配置站点信息
website
http://www.yinhai.net
company
yinhai
public class ServletContext_ extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取web.xml的context-parameter
//1.获取到ServletContext对象
ServletContext servletContext = getServletContext();
//2. 获取website
String website = servletContext.getInitParameter("website");
String company = servletContext.getInitParameter("company");
//3. 获取项目的工程路径
String contextPath = servletContext.getContextPath();
//4. 获取项目发布会,正在的工作路径
String realPath = servletContext.getRealPath("/");
System.out.println("项目路径= " + contextPath);// /servlet
System.out.println("website= " + website);
System.out.println("company= " + company);
System.out.println("项目发布后的绝对路径= " + realPath);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
工程路径 out目录
完成简单的网站访问计数器
2.使用Chrome访问Servlet01,每访问一次, 就增加1访问次数,在后台输出,并将结果返回给浏览器显示
3.使用火狐访问Servlet02,每访问一次, 就增加1访问次数,在后台输出,并将结果返回给浏览器显示
public class OrderServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = getServletContext();
System.out.println("OrderServletContext=" + servletContext
+ "运行类型" +servletContext.getClass());
//从servletContext获取visit_count属性k-v
Object visit_count = servletContext.getAttribute("visit_count");//设置一个名叫visit_count的k值
if(visit_count == null){
//说明是第一次访问网站
servletContext.setAttribute("visit_count" , 1);
visit_count = 1;
}else{
//说明是第二次以后
visit_count = Integer.parseInt(visit_count + "") + 1;
servletContext.setAttribute("visit_count" , visit_count);
}
//输出显示
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("该网站被访问的次数是 "+ visit_count + "
");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
public class PayServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = getServletContext();
System.out.println("OrderServletContext=" + servletContext
+ "运行类型" +servletContext.getClass());
//从servletContext获取visit_count属性k-v
Object visit_count = servletContext.getAttribute("visit_count");
if(visit_count == null){
//说明是第一次访问网站
servletContext.setAttribute("visit_count" , 1);
visit_count = 1;
}else{
//说明是第二次以后
visit_count = Integer.parseInt(visit_count + "") + 1;
servletContext.setAttribute("visit_count" , visit_count);
}
//输出显示
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("该网站被访问的次数是 "+ visit_count + "
");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
1. HttpServletRequest对象代表客户端的请求
2.当客户端/浏览器通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中
3.通过这个对象的方法,可以获得客户这些信息。
1.需求:说明:在一个表单提交数据给Servlet ,然后在Servlet通过HttpServletRequest对象获取相关数据
public class HttpServletRequestMethods extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//这里我们使用request对象,获取表单提交的各种数据
System.out.println("HttpServletRequestMethods doPost() 被调用..");
/***********************************
* 获取和http请求头相关信息
***********************************/
System.out.println("请求的资源路径URI= " + request.getRequestURI());
//http://主机/uri
System.out.println("请求的统一资源定位符(绝对路径)URL= " + request.getRequestURL());
System.out.println("请求的客户端ip 地址= " + request.getRemoteAddr());//本地就是127.0.01
//思考题:如发现某个ip 在10s中,访问的次数超过 100次,就封ip
//实现思路: 1用一个集合concurrentHashmap[ip:访问次数] 2[线程/定时扫描] 3 做成处理
// 获取http请求头的信息,可以指定其他,比如 User-Agent , Host等待 老师就举一个例子
System.out.println("http请求头HOST= " + request.getHeader("Host"));
// 说明,如果我们希望得到请求的头的相关信息,可以使用request.getHeader("请求头字段")
System.out.println("该请求的发起地址是= " + request.getHeader("Referer"));
// 请获取访问网站的浏览器是什么?
String userAgent = request.getHeader("User-Agent");
System.out.println("User-Agent= " + userAgent);
// 取出FireFox, 取出最后
String[] s = userAgent.split(" ");
System.out.println("浏览器=" + s[s.length - 1].split("\\/")[0]);
//获取 Cookie
// JSESSIONID=8CBBD23BDE01BAE6705E03C5C8916BD1
String cookie = request.getHeader("Cookie");
String JSESSIONID = cookie.split("=")[1];
System.out.println("取出JSESSIONID= " + JSESSIONID);
//课堂练习: 要求同学们取出 Windows NT 10.0 和 Win64
// 主要是Get / Post
System.out.println("http请求方式~= " + request.getMethod());
/***********************************
* 获取和请求参数相关信息, 注意要求在返回数据前,获取参数
***********************************/
//解决接收参数的中文乱码问题, 老师提示,写在 getParameter前.
request.setCharacterEncoding("utf-8");
//1. 获取表单的数据[单个数据]
//username=tom&pwd=&hobby=hsp&hobby=spls
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
//2. 获取表单一组数据
String[] hobbies = request.getParameterValues("hobby");
System.out.println("username= " + username);
System.out.println("pwd= " + pwd);
//增强for循环的快捷键 iter->回车即可 , 能使用快捷键,就使用快捷键
for (String hobby : hobbies) {
System.out.println("hobby=" + hobby);
}
//推而广之, 如果是 单选 , 下拉框 等等. => 作业布置
//返回接收到的信息, 给浏览器回显
//本质就是在http响应头,加上 Content-Type: text/html;charset=utf-8
//说 text/html 表示返回的数据类型,浏览器会根据这个类型来解析数据
// text/plain 表示返回的数据,请浏览器使用文本方式解析
// application/x-tar 表示返回的是文件,浏览器就会以下载文件的方式处理
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("提交的用户名= " + username + "
");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
1.获取doPost參数中文乱码解决方案,注意setCharacterEncoding("utf-8")要写在request.getParameter()前。
2.注意:如果通过PrintWriter writer,有返回数据给浏览器,建议将获取参数代码写在writer.print()之前,否则可能参数值(doPost)
3.处理http响应数据中文乱码问题
4.再次理解Http协议响应Content-Type的含义,比如text/plain application/x-tar
获取Cookie
//获取 Cookie
// JSESSIONID=8CBBD23BDE01BAE6705E03C5C8916BD1
String cookie = request.getHeader("Cookie");
String JSESSIONID = cookie.split("=")[1];
System.out.println("取出JSESSIONID= " + JSESSIONID);
一个业务需要多个servlet帮助
1.实现请求转发:请求转发指一-个web资源收到客户端请求后,通知服务器去调用另外- - 个web资源进行处理
2. HttpServletRequest对象(也叫Request对象)提供了一个getRequestDispatcher方法,该方法返回-一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发
3. request对象同时也是一个域对象, 开发人员通过request对象在实现转发时,把数据通request对象带给其它web资源处理
●setAttribute方法
●getAttribute方法
●removeAttribute方法
●getAttributeNames方法
红线代表 Servlet01完之后告诉Tomcat还有Servlet02
创建两个类,一个用于检查用户 一个用于提供用户的操作
创建一个CheckServlet类 然后该类结束告诉Tomcat需要进行另外的Servlet调用
@WebServlet(name = "CheckServlet",urlPatterns = "/checkServlet")
public class CheckServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("checkServlet be invoked...");
//根据用户名来确定该用户是什么身份
String username = request.getParameter("username");
//注意:如果是同一个request对象(请求转发),那么可以在不同的servlet中,使用getParameter
if ("tom".equals(username)) {
//分配
request.setAttribute("role", "管理员");
} else {
request.setAttribute("role", "普通用户");
}
//获取分发器
// 1. /manageServlet写的是 要转发的servlet的url
// 2. 会被解析成/servlet/manageServlet
// 3. forward(request, response) 表示把当前servlet的request对象和response对象,传递给下一个servlet使用
RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/manageServlet");
requestDispatcher.forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
ManageServlet类
@WebServlet(name = "Servlet" , urlPatterns = "/manageServlet")
public class ManageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("manageServlet be invoked...");
String username = request.getParameter("username");
String role = (String) request.getAttribute("role");
//输出信息
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("用户名: " + username + "
");
writer.print("角色 : " + role);
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
登录
1.浏览器地址不会变化(地址会保留在第1个servlet的urI)
2.在同一次HTTP请求中心进行多次转发,仍然是-次HTTP请求
3.在同一次HTTP请求中, 进行多次转发,多个Servlet可以共享request域/对象的数据,因为始终是同一个request对象
4.可以转发到WEB-INF目录下
5.不能访问当前WEB工程外的资源(错误的)
6.因为浏览器地址栏会停止在第一个servlet ,如果你刷新页面,会再次发出请求(并且会带数据),所以在支付页面情况下,不要使用请求转发,否则会造成重复支付
1)编写一个RegisterServlet ,能够接收到提交的各种数据
2)并把接收到的数据返回给浏览器,并显示
3)注意处理中文乱码问题
4)暂不处理文件提交
5)获取操作系统
POST /homeworkServlet HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Origin: http://localhost:8080
Connection: keep-alive
Referer: http://localhost:8080/servlet/homework01.html
Cookie: Idea-b98d27c7=9e6cf02b-2f2a-49f6-bd74-84801e7b197b
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Pragma: no-cache
Cache-Control: no-cacheusername=1&pwd1=&pwd2=&sport=zq&sport=sq&gender=male&city=cd&myfile=
@WebServlet(name = "Homework01",urlPatterns = "/homeworkServlet")
public class HomeworkServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("homeworkServlet be invoked...");
/***********************************
* 获取和请求参数相关信息, 注意要求在返回数据前,获取参数
***********************************/
//解决接收参数的中文乱码问题,写在 getParameter前.
request.setCharacterEncoding("utf-8");
//1. 获取表单的数据[单个数据]
//username=1&pwd1=&pwd2=&sport=zq&sport=sq&gender=male&city=cd&myfile=
String username = request.getParameter("username");
String pwd1 = request.getParameter("pwd1");
String pwd2 = request.getParameter("pwd2");
String gender = request.getParameter("gender");
String city = request.getParameter("city");
String myfile = request.getParameter("myfile");
//2. 获取表单一组数据
System.out.println("username= " + username);
System.out.println("pwd1= " + pwd1);
System.out.println("pwd2= " + pwd2);
System.out.println("gender= " + gender);
System.out.println("city= " + city);
//增强for循环的快捷键 iter->回车即可
String[] sport = request.getParameterValues("sport");
System.out.print("sport = ");
for (String s : sport) {
System.out.print(s);
}
System.out.println();
//获取电脑操作系统
String header = request.getHeader("User-Agent");
String regStr = "\\((.+)\\)";//分组
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(header);
matcher.find();
String group = matcher.group(1);
String[] split = group.split(";");
String system = split[0];
String bit = split[1];
//返回接收到的信息, 给浏览器回显
//本质就是在http响应头,加上 Content-Type: text/html;charset=utf-8
//说 text/html 表示返回的数据类型,浏览器会根据这个类型来解析数据
// text/plain 表示返回的数据,请浏览器使用文本方式解析
// application/x-tar 表示返回的是文件,浏览器就会以下载文件的方式处理
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("提交的用户名= " + username + "
");
writer.print("操作系统= " + system + "
");
writer.print("操作系统= " + bit + "
");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
1.每次HTTP请求,Tomcat会创建一个HttpServletResponse对象传递给Servlet程序去使用。
2. HttpServletRequest表示请求过来的信息,HttpServletResponse 表示所有响应的信息,如果需 要设置返回给客户端的信息,通过HttpServletResponse 对象来进行设置即可
1.字节流getOutputStream();常用于下载(处理二进制数据)
2.字符流getWriter();常用于回传字符串
3.两个流同时只能使用一个。使用了字节流,就不能再使用字符流,反之亦然,否则就会报错
DownServlet用于处理用户的下载请求
@WebServlet(name = "DownServlet",urlPatterns = "/downServlet")
public class DownServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// System.out.println("DownServlet 被调用");
// response.setContentType("application/x-tar;charset=utf-8");
// PrintWriter writer = response.getWriter();
// writer.print("hi");
// writer.flush();
// writer.close();
//完成了自己业务
//发出请求重定向-> DownServletNew
//1. sendRedirect 本质就会 返回 302 状态码 Location: /servlet/downServletNew
//2. 因此 302和 /servlet/downServletNew 是浏览器解析,而不是服务器
//3. 浏览器在解析 /servlet/downServletNew => http://localhost:8080/servlet/downServletNew
//4. 动态获取到application context
String contextPath = getServletContext().getContextPath();
System.out.println("contextPath= " + contextPath);
//response.sendRedirect("/servlet/downServletNew");
response.sendRedirect(contextPath + "/downServletNew");
//response.sendRedirect("http://www.baidu.com");
//第二种重定向的写法
// System.out.println("第二种方式重定向...");
// response.setStatus(302); //设置http响应的状态码
// //设置http响应的 Location: /servlet/downServletNew
// response.setHeader("Location", "/servlet/downServletNew");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
请求重定向到DownServletNew上
@WebServlet(name = "DownServletNew",urlPatterns = "/downServletNew")
public class DownServletNew extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("DownServletNew 被调用");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("ok");
writer.flush();
writer.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
1.最佳应用场景:网站迁移,比如原域名是www.hsp.com迁移到www.hsp.cn,但是百度抓取的还是员网址.
2.浏览器地址会发生变化,本质是两次http请求.
3.不能共享Request域中的数据,本质是两次http请求,会生成两个HttpServletRequest对象
4.不能重定向到/WEB-INF下的资源
5.可以重定向到Web工程以外的资源,比如到www.baidu.com [在前面的案例演示 ]
6.重定向有两种方式,推荐使用第1种.
//第二种重定向的写法
// System.out.println("第二种方式重定向...");
// response.setStatus(302); //设置http响应的状态码
// //设置http响应的 Location: rvlet/downServletNew
// response.setHeader("Location", "rvlet/downServletNew");
7.动态获取到application context
//动态获取到application context
String contextPath = getServletContext().getContextPath();
System.out.println("contextPath= " + contextPath);
response.sendRedirect(contextPath + "/downServletNew");
模拟支付
@WebServlet(name = "MyPayServlet",urlPatterns = "/myPayServlet")
public class MyPayServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("MyPayServlet 被调用...");
//得到金额
String money = request.getParameter("money");
System.out.println("money= " + money.getClass());
//转成int
//处理一下这个异常
int iMoney = WebUtils.parseString(money);
ServletContext servletContext = getServletContext();
if(iMoney > 100) {
//重定向到payok.html
//servletContext.getContextPath() 就是 /servlet
response.sendRedirect(servletContext.getContextPath() + "/payok.html");
} else {
response.sendRedirect(servletContext.getContextPath() + "/pay.html");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
一个判断是否输入为数字的类
public class WebUtils {
public static int parseString(String str) {
int num = 0;
try {
num = Integer.parseInt(str);//
} catch (NumberFormatException e) {
//这个异常不会throw 给 tomcat
System.out.println("输入的str格式不正确...");
}
return num;
}
}
支付页面
支付页面
支付页面