欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

【Java12】tomcatservlet(nginx,web.xml,生命周期,适配器优化),requestresponse(请求转发,登陆案例(1),重定向,文件下载)

发布时间:2024/4/24 java 479 豆豆

文章目录

  • 1.nginx的conf文件:以前网络编程中B/S架构中服务器是用socket写,用文件输入流读一个文件,读到后socket通过outputstream写出去,这些过程有了nginx后再也不用写
  • 2.nginx反向代理与负载均衡:nginx是被广泛使用的网页服务器,在www.163.com的F12的Network中Headers中有server:nginx,使用nginx首当其冲,做反向代理,将请求分发到公司的多台服务器上
    • 2.1 location匹配方式:location / 默认匹配所有请求,相当于第四优先级(最弱)
    • 2.2 反向代理写法:http80,
    • 2.3 负载均衡写法:基于反向代理
  • 3.服务器:软件为tomcat或nginx,程序为servlet
  • 4.servlet:多态,web.xml
  • 5.servlet生命周期:LifecycleServlet
  • 6.servlet优化:GenericServelt/HttpServelt
  • 7.http协议和抓包:枚举Enumeration,request.getHeaderNames()
  • 8.request对象:.getParameterMap(),post请求中文参数乱码
  • 9.请求转发:jrss,request.setAttribute()
  • 10.登陆案例(1):成功和失败页面相当于两个模块
  • 11.response对象:text/html,重定向(.setStatus,.setHeader)
  • 12.文件下载:request/response


1.nginx的conf文件:以前网络编程中B/S架构中服务器是用socket写,用文件输入流读一个文件,读到后socket通过outputstream写出去,这些过程有了nginx后再也不用写

nginx软件链接:https://pan.baidu.com/s/1zvF2irI6OenDKVfvSIOZmg ,提取码:gsn9。

如果http协议是80端口的话,80端口会被隐藏,本机浏览器输入http://localhost:80启动服务端显示如下,hello nginx是E\my81\index.html里内容。本机ipconfig显示192.168.33.71。上面红框浏览器(客户端)是别人的电脑【局域网下同一网段】,上面两个大框是服务端,浏览器和服务器三要素对应。

nginx作用:1.反向代理:s被代理1个公网ip,但有n台s对外服务。
2.负载均衡:基于反向代理。
3.正向代理:我们电脑接入VPN 后,我们对外IP地址就会变成VPN服务器的公网IP。
4.动静分离:网页f12显示js,css,img属静态数据。

线程通讯:volatile关键字,wait(),notify()
线程安全:synchronized关键字
计算密集型:进行(多核)
io密集型:线/协程(只1个核在做,占资源轻,io等待时间拿来用)

2.nginx反向代理与负载均衡:nginx是被广泛使用的网页服务器,在www.163.com的F12的Network中Headers中有server:nginx,使用nginx首当其冲,做反向代理,将请求分发到公司的多台服务器上

原生nginx没有集成很多插件,使用不方便。推荐使用openresty(在nginx基础上集成了很多lua写的插件),官网下载openresty后解压后进一级目录输入nginx.exe回车运行服务端,浏览器输入localhost默认:80端口。修改conf目录下nginx.conf文件,删除注释。50x.html是错误页面,暂时不用。


如下还是在nginx.conf文件里,stream类型执行下载,echo是插件。


2.1 location匹配方式:location / 默认匹配所有请求,相当于第四优先级(最弱)

1.如下最强级别=。



2.如下优先级第二,^~以什么开头。如下/是路径,不是转义符。



3.如下优先级第三,正则表达式~。\w匹配数字、字母、下划线,转义字符\可以转义很多字符,比如\n表示换行,\t表示制表符,字符\本身也要转义,所以\\表示的字符就是\。如下/是路径。



如下同优先级的,按匹配程度较高的先匹配。


同优先级并且匹配程度相同的话,写在上面的优先执行。

2.2 反向代理写法:http80,

如下是其他服务器,记住192…:80是it works页面。



如下localhost先到本机127.0.0.0,再转到192上面的这个服务器。

如下是apach返回的Not Found返回的信息,192…:80/a路径没有,不是nginx返回的信息,因为已经把请求转到192…

1.默认拼接。


如下其实转到了192...:80/a。

2.如下转到192...:80/,两个/省去后一个字母。

2.3 负载均衡写法:基于反向代理


两个ip+端口根据权重切换。

3.服务器:软件为tomcat或nginx,程序为servlet

Web(World Wide Web)即全球广域网,也称为万维网。

nginx不支持java规范,tomcat支持。tomcat8:https://tomcat.apache.org/download-80.cgi。免安装,解压即可用:链接:https://pan.baidu.com/s/1UJM9kbIHGIXkNXlYLpcoGw ,提取码:g610。dos系统识别文件后缀名不能超过3位(先有dos后有windows),所以.htm。8080一般是用来连接代理的(8080不能省,只有80才能省)。 只有index.html是默认的,不用加在最后,localhost:8080/a.html。

如下javaee新建项目,apache-tomcat8…是前面tomcat软件解压路径。如下不需要自己开启tomcat,idea配置自动开启。


如下New和上面一样,关联tomcat软件解压路径。

如下将web文件夹当成前端static web项目,web文件夹里都可以访问,除了web-info无法访问(如【Mysql3】最后一节,-info文件夹放jar包),Toolbar工具栏。


如下是点乌龟运行后,浏览器自动打开的原理。改变路径 / 写法。

如上若还是不会默认打开谷歌,需要File - Settings - Tools - Web Browsers。

4.servlet:多态,web.xml


如下选中src右击new - java class,name为com.itheima01.servlet.MyServlet,还有一件事配置web.xml如上图所示。

package com.itheima01.servlet; import javax.servlet.*; import java.io.IOException;public class MyServlet implements Servlet { //javax.servlet.Servlet (x指extend,如果没有提示,则上面tomcat项目配置失败) //没有main函数,右击run不了,点乌龟@Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("控制台日志: 服务器被访问了"); servletResponse.getWriter().print("hello servlet"); //在网页上打印(英文,中文会乱码)} @Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {} }

如下点击idea中乌龟,自动打开网页,改变/my路径。


tomcat+servlet原理(4步):以前解析xml文件(web.xml)用dom4j,将xml先读到内存里在进行解析。第4步:mapping映射后,tomcat(中介即代理默认端口8080)底层会进行反射,当前类com.itheima01.servlet.MyServlet肯定是Servlet接口的implements实现类,可以向上转型,父类Servlet调用方法执行子类重新的方法。

为什么tomcat底层用反射?tomcat底层设计不能和MyServlet耦合,只有全限定名和MyServlet有关(自己设定的),通用性。tomcat像管家中介(用户,tomcat软件【中介】,jdk的Servlet)在第3步等客人,第4步客人来了找my,tomcat根据客人请求找到my的住址com....MyServlet,把my叫醒进行service办公。

如上在web.xml中,MyServlet01可以随便命名但要上下一致,my是资源位置,/my(因为在当前项目,http…8080可以省略,url)和com…MyServlet(class,全限定名就是全类名就是包名加类名)对应关系。

5.servlet生命周期:LifecycleServlet

package com.itheima02.life; import javax.servlet.*; import java.io.IOException;public class LifecycleServlet implements Servlet {public LifecycleServlet(){ //不写也可以,一个类默认有 空参构造System.out.println("LifecycleServlet");} //如下生命周期 5个重写 @Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init");} @Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service");} @Overridepublic void destroy() {System.out.println("destroy");}//11111111111111111111111111111111111111111111111111111111以下没用@Overridepublic ServletConfig getServletConfig() {System.out.println("getServletConfig");return null;} @Overridepublic String getServletInfo() {System.out.println("getServletInfo");return null;} }

//web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><servlet><servlet-name>MyServlet01</servlet-name><servlet-class>com.itheima01.servlet.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet01</servlet-name><!-- <url-pattern>http://localhost:8080/my</url-pattern>--><url-pattern>/my</url-pattern></servlet-mapping><servlet><servlet-name>LifecycleServlet</servlet-name><servlet-class>com.itheima02.life.LifecycleServlet</servlet-class></servlet><servlet-mapping><servlet-name>LifecycleServlet</servlet-name><url-pattern>/life</url-pattern></servlet-mapping><servlet><servlet-name>GoodServlet</servlet-name><servlet-class>com.itheima03.good.GoodServlet</servlet-class></servlet><servlet-mapping><servlet-name>GoodServlet</servlet-name><url-pattern>/good</url-pattern></servlet-mapping><servlet><servlet-name>BetterServlet</servlet-name><servlet-class>com.itheima03.good.BetterServlet</servlet-class></servlet><servlet-mapping><servlet-name>BetterServlet</servlet-name><url-pattern>/better</url-pattern></servlet-mapping> </web-app>


如下默认调用空参构造创建实例(第一行)。

6.servlet优化:GenericServelt/HttpServelt

只留一个接口叫适配器设计模式。将service方法根据不同请求方式分化出两个不同方法。

package com.itheima03.good; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;public class GoodServlet extends GenericServlet { //ServletRequest : 请求(前端发送服务器的数据), 兼容大部分协议(包括http), 子接口: HttpServletRequest@Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { //这个service方法将下面3个方法(service2,doPost,doGet)都调用了System.out.println("goodServlet"); //没有ServletRequest.getgetMethod() //因为不是所有的协议都有请求方式,所以要向下转型成httpHttpServletRequest request = (HttpServletRequest) servletRequest; //协议: 必须是httpHttpServletResponse response = (HttpServletResponse) servletResponse;//request.getMethod(); //http协议有请求方式service2(request,response); }private void service2(HttpServletRequest request, HttpServletResponse response) { String method = request.getMethod(); //请求方式if("GET".equals(method)){doGet(request,response);}else if("POST".equals(method)){doPost(request,response);}}//以后再写Servlet只要继承GoodServlet(GoodServlet可以改名为HttpServlet),重写doPost和doGet就行 //如下相当于 http协议中post请求方式的service方法,HttpServletRequest类比原ServletRequest类好用private void doPost(HttpServletRequest request, HttpServletResponse response) {}//如下相当于 http协议中get请求方式的service方法private void doGet(HttpServletRequest request, HttpServletResponse response) { } }

浏览器:localhost:8080/good,网页无显示,控制台打印goodServlet。

package com.itheima03.good; 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 BetterServlet extends HttpServlet { //sun公司已经封装HttpServlet@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {} }

如上解决了前二个问题。如下解决第三个问题,不用配置web.xml。

package com.itheima03.good; 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;@WebServlet(urlPatterns = "/best") public class BestServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp); }@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("被访问了");} }



如下把上面BestServlet类设置为模板,使用:选中包(包下)-new-servlet。

如上模板如下:

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse("File Header.java")@javax.servlet.annotation.WebServlet(urlPatterns = "/${Entity_Name}") public class ${Class_Name} extends javax.servlet.http.HttpServlet {@Overrideprotected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {doGet(request,response);}@Overrideprotected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {} }

7.http协议和抓包:枚举Enumeration,request.getHeaderNames()

http的request对象:由tomcat创建,并且里面数据由tomcat set进去,我们只需要get出来。

File-New-Project-Java Enterprise。

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head><!--111111111111111111111111111111111111111111111111111111111111111111111111111--> <body><!--http协议两种主要请求协议1. get (默认, 只要看到可以发起请求,但是没看到请求方式设置)2. post (需要收到设置)--><h1>get请求方式</h1><form action="http://localhost:8080/MyServlet" method="get"><input type="text" placeholder="请输入用户名" name="name"> <br><input type="text" placeholder="请输入密码" name="pwd"> <br><input type="submit"></form><h1>post请求方式</h1> <form action="/MyServlet" method="post"> <!-- 本服务器前面可以省略 --><input type="text" placeholder="请输入用户名" name="name"> <br><input type="text" placeholder="请输入密码" name="pwd"> <br><input type="submit"></form> </body> </html>

如上html文件建在web文件夹路径下,如下创建的是servlet的模板。

package com.itheima01.http; 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; import java.util.*; /*** http://192.168.139.236:8080/MyServlet 或 MyServlet换成..请求报文.html** #request对象核心功能: 获取前端的请求数据如下:* 1. 请求行* 请求方式 / 请求url / 协议* 方法:1. String getMethod() : 获取请求方式的类型2. StringBuffer getRequestURL() : 获取客户端发出请求完整URL3. String getProtocol(): 获取当前协议的名称和版本 4. String getRemoteAddr() : 获取IP地址** 2. 请求头* 1. 获取指定请求头的信息: value = request.getHeader("name");2. 获取所有的请求头的name值:request.getHeaderNames();** 3. 请求参数* tomcat: 会根据不同的请求方式(自动get请求从url获取参数,post请求从请求体里获取参数),从不同的地方获取参数并设置到request对象,这样不需要知道过程,只有结果。**/ @WebServlet(urlPatterns = "/MyServlet") public class MyServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //doGet方法相当于get请求方式下的service方法 // System.out.println("服务器被访问了"); //idea下面显示 // response.getWriter().print("hello http"); //在网页上输出// line(request); //请求行String agent = request.getHeader("user-agent"); //出bug执行的//用户访问我的网站突然崩溃,实际已获取了用户环境,在服务器所在地方可以模拟用户String referer = request.getHeader("referer"); //防盗链System.out.println(agent);System.out.println(referer);//11111111111111111111111111111111111111111111111111111111111111111111111111111111HashMap<String, String> map = new HashMap<>();Iterator<String> it = map.keySet().iterator();while(it.hasNext()){String key = it.next();String value = map.get(key);} //如下枚举Enumeration相当于上面迭代器 Enumeration<String> it2 = request.getHeaderNames(); //=号右边等价于map.keySet().iterator()while(it2.hasMoreElements()){String name = it2.nextElement();String value = request.getHeader(name);System.out.println(name + "->" + value);}}//11111111111111111111111111111111111111111111111111111111111111111111111111111111private void line(HttpServletRequest request) { //请求行,抓包String method = request.getMethod();StringBuffer url = request.getRequestURL();String protocol = request.getProtocol();String remoteAddr = request.getRemoteAddr(); System.out.println(method);System.out.println(url.toString());System.out.println(protocol); System.out.println("访问者的ip:" + remoteAddr);} }


如上浏览器网址中…报文.html是Referer中的上一次访问页面,因为已跳转到如下下个页面。

如下请求行中的请求url省略了如上的http://localhost:8080。cookie是浏览器缓存的一种。get请求中最后一行不是请求体,是谷歌浏览器工具抓包进行的参数强调渲染。

8.request对象:.getParameterMap(),post请求中文参数乱码

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head><!--111111111111111111111111111111111111111111111111111111111111111111111111111--> <body><h1>get请求</h1><form action="/ParamServlet" method="get">用户名: <input type="text" name="name"> <br>密码: <input type="password" name="pwd"> <br>性别: <input type="radio" name="gender" value="boy"><input type="radio" name="gender" value="girl"><br>爱好:<input type="checkbox" name="hobby" value="smoke"> 抽烟<input type="checkbox" name="hobby" value="drink"> 喝酒<input type="checkbox" name="hobby" value="firehead"> 烫头 <br><input type="submit"></form><h1>post请求</h1><form action="/ParamServlet" method="post">用户名: <input type="text" name="name"> <br>密码: <input type="password" name="pwd"> <br>性别: <input type="radio" name="gender" value="boy"><input type="radio" name="gender" value="girl"> <br>爱好:<input type="checkbox" name="hobby" value="smoke"> 抽烟<input type="checkbox" name="hobby" value="drink"> 喝酒<input type="checkbox" name="hobby" value="firehead"> 烫头 <br><input type="submit"></form> </body> </html> package com.itheima02.param; 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; import java.util.Arrays; import java.util.Map; import java.util.Set; /**请求参数: parameter ?n1=v1&n2=v2...方法:1. 根据name值获取value值: String value = request.getParameter(name);2. 根据name值获取多个value值:String[] value = request.getParameterValues(name);3. 获取所有的请求参数,封装到map中:Map<String, String[]> map = request.getParameterMap();name为String,value为String[]问题: post请求中文参数乱码原因: 编解码使用的字符集不一样编码: 浏览器 ( utf-8 )解码: 服务器 (tomcat + servlet)ISO-8859-1 utf-8解决: tomcat的编码表改成utf-81. 永久2. 临时 (选用) request.setCharacterEncoding("utf-8"); 注意: 必须放在获取参数之前【get请求 tomcat8以上被优化 不乱码(post请求参数在请求体中,走io流)】**/ @WebServlet(urlPatterns = "/ParamServlet") public class ParamServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // request.setCharacterEncoding("utf-8");String name = request.getParameter("name");String pwd = request.getParameter("pwd");String gender = request.getParameter("gender");String[] hobbies = request.getParameterValues("hobby"); //复选框可重复System.out.println(name+"," + pwd + "," + gender + "," + Arrays.toString(hobbies));//11111111111111111111111111111111111111111111111111111111111111111111111111111111111Map<String, String[]> map = request.getParameterMap(); // System.out.println(map); //这个map没有重写tostring方法Set<String> set = map.keySet();for (String key : set) {String[] value = map.get(key); //value数组没有重写tostring方法,不能 // System.out.println(key + "=" + Arrays.toString(value));}} }


如下选中的是map遍历出来的结果和下面第一行一样。

9.请求转发:jrss,request.setAttribute()

request表面上获取请求数据,还有快递员身份。

如下forward方法中request是邮件及内容,response是回应权限。A模块指MyServlet,B模块指ZhouServlet。一次请求链如下只有一去一回。

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head><!--111111111111111111111111111111111111111111111111111111111111111111111111111--> <body> 人事<!--<a href="http://localhost:8080/ShiServlet?msg=有人来面试">发送邮件</a>--><a href="/ShiServlet?msg=有人来面试">发送邮件</a> <!--点发送邮件后,地址栏修改为/Shi..,没写就是get请求--> </body> </html> package com.itheima03.transfer; import javax.servlet.RequestDispatcher; 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;@WebServlet(urlPatterns = "/ShiServlet") public class ShiServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收请求String msg = request.getParameter("msg");System.out.println("shi:" + msg);System.out.println("shi:我现在没空,叫周楠同学帮我面试"); request.setAttribute("extra","比我帅的不要~~"); //添加备注,这行注掉不写,ZhouServlet写request.getAttribute会得到null//2. 请求转发 // RequestDispatcher dispatcher = request.getRequestDispatcher("/ZhouServlet"); //比作邮件服务器或快递员 // dispatcher.forward(request,response); //快递员发货request.getRequestDispatcher("/ZhouServlet").forward(request,response); //这行等价上面两行} } package com.itheima03.transfer; 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;@WebServlet(urlPatterns = "/ZhouServlet") public class ZhouServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //request和response两个参数由A模块传递来//1. 接收请求String msg = request.getParameter("msg");System.out.println("zhou:" + msg); Object extra = request.getAttribute("extra");System.out.println("zhou:" + extra);//2. 业务处理System.out.println("周楠同学放下手机,难得做点事情: 面试");//3. 响应数据response.getWriter().print("this boy is ok,about 3k~~");} }


10.登陆案例(1):成功和失败页面相当于两个模块


File - New - Project - Java Enterprise。

如下想到Junit包失效。

//JdbcUtil.java package com.itheima.utils; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.jdbc.core.JdbcTemplate;public class JdbcUtil {private static ComboPooledDataSource ds = new ComboPooledDataSource(); //先new一个连接池public static JdbcTemplate getTemplate(){JdbcTemplate template = new JdbcTemplate(ds); //再new一个Template,把连接池交给给JdbcTemplate管理return template;} } //LoginServlet.java package com.itheima.login; import com.itheima.bean.User; import com.itheima.utils.JdbcUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; 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;@WebServlet(urlPatterns = "/LoginServlet") public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.接收请求String username = request.getParameter("userName"); //userName区分大小写String password = request.getParameter("password");//2.业务处理 //如下只有两种结果: 返回一行(一行是一个对象) 或 返回nullString sql = "select * from user where username = ? and password = ?";JdbcTemplate template = JdbcUtil.getTemplate(); //一定要封装成JdbcUtil,不然new ComboPooledDataSource,每访问一次就会创建一次连接池,内存崩。User user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username, password); //把如下注掉,用如上一行,即查不到数据,抛出异常,不抓异常,这样会密码错误直接跳转500(500服务器错误,404地址输错),而不是error.html /*User user = null;try {user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username, password);} catch (DataAccessException e) {e.printStackTrace();}*/if(user != null){request.getRequestDispatcher("/success.html").forward(request,response); //登录成功}else{request.getRequestDispatcher("/error.html").forward(request,response);}} } // User.java package com.itheima.bean;public class User {private Integer id; //和表字段一致private String username;private String password;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} } //login.html <!DOCTYPE html> <html lang="en"> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>登录页面</title><link href="css/bootstrap.min.css" rel="stylesheet"><link href="css/login.css" rel="stylesheet"><script src="js/jquery.js"></script><script src="js/bootstrap.js"></script> </head><!--1111111111111111111111111111111111111111111111111111111111111111111111111--> <body><div class="container text-center"><form class="form-signin" action="/LoginServlet"><h2 class="form-signin-heading">登录页面</h2><input type="text" name="userName" class="form-control" placeholder="用户名" required autofocus><input type="password" name="password" class="form-control" placeholder="密码" required><button class="btn btn-lg btn-primary btn-block" type="submit">登录</button></form></div> </body> </html>

11.response对象:text/html,重定向(.setStatus,.setHeader)



package com.itheima01.http; 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.IOException; import java.io.PrintWriter;@WebServlet(urlPatterns = "/MyServlet") public class MyServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("服务器被访问了"); // int i = 1/0; //服务器崩了出异常,没有try catch,状态码500 response.setStatus(302); //状态码设置,只有302需要我们手动设置 // response.setStatus(404); //这样设置状态码是404,servlet优先级高于tomcat,但是访问服务端依旧成功 // response.getWriter().print("hello response"); //前端网页打印出//响应体输出流设置,字节输出流(写) //待会下载文件案例中使用 // ServletOutputStream os = response.getOutputStream(); // os.write("abc".getBytes()); //01_响应报文.html中点击“访问MyServlet”超链接跳转到显示“abc”的新页面//方便输出字符数据,不用转换为字节了,print和write一样 // PrintWriter writer = response.getWriter(); // response.getWriter().print("xx"); } }

请求报文分get和post两种,在响应报文里看到了非servlet设置的内容,那就是tomcat设置的。将前端改为href=“/MyServlet123”,则会出现404。servlet关了,tomcat自动设置为500状态码。

如下体中hello response长度一共为Content-Lenth为14,头中GMT格林位置需+8小时为东八区北京时间。如下行和头都是tomcat默认自动设置,体是我们servlet手动设置。想修改状态码,需要在servlet(对我们暴露的小程序)中修改。


如下响应头分四种(蓝色字),如下简易API等同上行。


如下点击后,5秒后跳转到百度。

package com.itheima02.header; 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;@WebServlet(urlPatterns = "/RefreshAndTypeServlet") public class RefreshAndTypeServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("服务器被访问了"); // response.setHeader("refresh","5;http://www.baidu.com");//11111111111111111111111111111111111111111111111111111111111111111111111111111111111111/** 问题: 响应体中文乱码 。request.setCharacterEncoding("utf-8");* 原因: 编码: 服务器(utf-8 : servlet:因为在servlet里写的"哈哈",idea右下角显示utf-8)* 解码: 浏览器(iso-8859-1 : tomcat默认设置如下行) // response.setHeader("content-type","text/plain"); //在Response Headers(浏览器F12看出)中多出tomcat默认设置(不加这行不显示):Content-Type: text/plain;charset=ISO-8859-1* 解决: servlet中手动设置覆盖tomcat默认设置** windows系统: txt html jpg avi ...* 早期MIMEType : text/plain text/html image/jpeg (tomcat解压包中web.xml中有对应说明)*/ // response.setHeader("content-type","text/plain;charset=utf-8"); //新页面显示 <h1>哈哈</h1> // response.setHeader("content-type","text/html;charset=utf-8"); //点击网页上RefreshAnd..跳转新页面显示 哈哈response.setContentType("text/html;charset=utf-8"); //setContentType是简易API,同上一行response.getWriter().print("<h1>哈哈</h1>"); } }

因为重定向不是一次请求链,所以超过域对象,不能用request传递数据。ZhouServlet收不到人事的msg,能收到ShiServlet的response.setHeader(…/ZhouServlet?msg=…)。

package com.itheima03.redirect; 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;@WebServlet(urlPatterns = "/ShiServlet") public class ShiServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收请求String msg = request.getParameter("msg");System.out.println("shi:" + msg);//2. 重定向response.setStatus(302);response.setHeader("location","/ZhouServlet?msg=xx"); //不写?msg=xx,ZhouServlet就收不到msg,写了就能收到} } package com.itheima03.redirect; 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;@WebServlet(urlPatterns = "/ZhouServlet") public class ZhouServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} @Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收请求String msg = request.getParameter("msg");System.out.println("zhou:" + msg);//2. 业务处理System.out.println("这个哥们还不错");//3. 响应数据response.setContentType("text/html;charset=utf-8");response.getWriter().print("这个哥们还可以,大约3K");} }




如下浏览器F12,第二行没有带参数,拿不到msg。

前面登陆成功请求转发到成功.html页面,失败.html…。用请求转发不合适,因为没有传递数据,应该用重定向。请求转发一次请求,地址指向第一次访问位置如下(网址阅读性太差,实际页面应该为localhost:8080/success.html)。

如下红框用重定向,登陆失败逻辑错误,之后再改。

如下重定向,第一次请求收到302。

12.文件下载:request/response

首先服务器要有文件,在网络编程做过文件上传。在servlet里写代码覆盖tomcat默认设置。

//02文件下载.html <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head><!--1111111111111111111111111111111111111111111111111111111111111111111111111--> <body><!--方案A:浏览器打开此网页点击后自动下载的话,说明tomcat默认设置,因为servlet一个字没写--><!-- <a href="dir/1.zip">1.zip</a> <br> <a href="dir/2.exe">2.exe</a> <br><a href="dir/3.txt">3.txt</a> <br><a href="dir/4.jpg">4.jpg</a> <br>--><a href="/DownloadServlet?file=1.zip">1.zip</a> <br><a href="/DownloadServlet?file=2.exe">2.exe</a> <br><a href="/DownloadServlet?file=3.txt">3.txt</a> <br><a href="/DownloadServlet?file=4.jpg">4.jpg</a> <br> </body> </html> package com.itheima04.down; 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;@WebServlet(urlPatterns = "/DownloadServlet") public class DownloadServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String file = request.getParameter("file"); // 拿到1.zip之类//1. 告诉浏览器如何处理文件response.setHeader("content-disposition","attachment;filename=x" + file); //下载以x命名//2. 读取服务器本地文件,写出浏览器。绝对路径 等会要改成 相对路径//以前java工程: web/dir/文件(相对路径,里面是1.zip,2.exe等需下载的文件)//web工程: main方法在tomcat里,造成和java工程相对路径不一样 // FileInputStream fis = new FileInputStream("E:/mywork/IdeaProjects/class897/web-day03/web/dir/" + file);//ServletContext servletContext1 = this.getServletContext(); //this是当前的servlet对象:servlet.getServletContext() //同下一行ServletContext servletContext = request.getServletContext(); //request小域对象可获取ServletContext大域对象 String realPath = servletContext.getRealPath("dir/" + file); //绝对路径换成相对路径 FileInputStream fis = new FileInputStream(realPath);ServletOutputStream os = response.getOutputStream();int length;byte[] buffer = new byte[1024];while((length = fis.read(buffer)) != -1){os.write(buffer,0,length);}fis.close();os.close();System.out.println("文件下载完毕");} }

响应体交给浏览器,浏览器自动下载。

linux没有盘符,所以不能用绝对路径,不好部署。如下artifacts指整个项目,运行的是如下蓝字编译的内容(黄色文件夹),只要获得web_war_exploded文件夹就能得到其他文件相对路径。用serlvetContext = web_war_exploded文件夹路径(exploded部署意思,如下红线),如下右边servletContext是生命周期最长的域对象,所以可以将数据传到服务器任何地方。

request除了作为域对象还有本职工作即获取请求数据,servletContext很像连接池(连接池一个就够),服务器没关,连接池不消毁。servletContext生命周期和web应用一样长,所以也叫application应用,环境参数如相对路径。request和session两个域对象用的最多,pageContext太短,servletContext太长。重定向不能通过request传递数据,可以用servletContext传递数据,但是一般也不这么做,servletContext占用内存大。

上图灰色WEB-INF文件夹中添加lib文件夹里放druid-1.0.9.jar包并右击add as library【Mysql3】,点乌龟运行tomcat后,会生成黄色lib文件夹。黄色classes文件夹里代码不能直接访问,需用web.xml或用注解建立映射关系访问:WEB-INF下是浏览器无法直接访问,通过建立映射,url访问,由tomcat访问。

热更新不做编译,新增类必须停下来。


与50位技术专家面对面20年技术见证,附赠技术全景图

总结

以上是生活随笔为你收集整理的【Java12】tomcatservlet(nginx,web.xml,生命周期,适配器优化),requestresponse(请求转发,登陆案例(1),重定向,文件下载)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。