如果是tomcat启动成功却无法通过localhost:8080进入页面,先去查看是否是端口号被占用,
再用命令中断占用的进程,如果简单的命令窗口无法中断,切换到管理员身份运行即可
netstat -ano|findstr "8080" 查看那个进程占用了8080端口号 得到该进程pid后 taskkill /f /t /im “进程PID” 终结该占用的进程 如果失败,用管理员身份打开cmd去执行
在idea中创建动态的web工程后(该module有蓝点)
servlet
1、Servlet 是JavaEE 规范之一。规范就是接口
2、Servlet 就JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
3、Servlet 是运行在服务器上的一个java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。a
手动实现servlet程序
1、编写一个类去实现Servlet 接口
public class HelloServlet implements Servlet
2、实现service 方法,处理请求,并响应数据
3、到web.xml 中去配置servlet 程序的访问地址在web.xml中:添加这些内容(<servlet>标签开始
<?xml version="1.0" encoding="UTF-8"?> <web-app 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" version="4.0"> <!-- Servlet标签给tomcat配置servlet程序--> <servlet> <!-- servlet-name标签给servlet程序起一个别名(一般是类名)--> <servlet-name>HelloServlet</servlet-name> <!-- servlet-class是servlet程序的全类名--> <servlet-class>summer.tryingweb.HelloServlet</servlet-class> </servlet> <!--servlet-mapping标签给servlet程序配置访问地址--> <servlet-mapping> <!-- servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用--> <servlet-name>HelloServlet</servlet-name> <!-- url-pattern标签配置访问地址 / 斜杠在服务器解析的时候,表示地址为: http://ip:port/工程路径 /hello -> http://ip:port/hello --> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
a
servlet的生命周期
1、执行Servlet 构造器方法
2、执行init 初始化方法
第一、二步,是在第一次访问,的时候创建Servlet 程序会调用。
可以看到后面再重复执行,只打印了3
3、执行service 方法
第三步,每次访问都会调用。(每次执行都会调用
4、执行destroy 销毁方法
第四步,在web 工程停止的时候调用。
get和post请求的分发处理
/* service方法是专门用来处理请求和响应的 */ @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("3、servlet方法"); //类型转换(因为它有getMethod()方法 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; //获取请求方式 String method = httpServletRequest.getMethod(); //method(GET或POST) if("GET".equals(method)){ doGet(); }else if("POST".equals(method)){ doPost(); } } private void doPost() { System.out.println("post请求"); } public void doGet() { System.out.println("get请求"); }
HttpServletRequest是ServletRequest的一个子类,而其有getMethod方法。
通过继承HttpServlet实现Servlet程序
一般在实际项目开发中,都是使用继承HttpServlet 类的方式去实现Servlet 程序。
1、编写一个类去继承HttpServlet 类
2、根据业务需要重写doGet 或doPost 方法
3、到web.xml 中的配置Servlet 程序的访问地址使用idea创建Servlet 程序
如果没有上述创建选项(上面版本可能更老点),则按下面步骤实现
File-Project Struture - facet- Source Roots 将那个框勾上,后面就可以new 创建了
创建
之后可以发现在配置文件中会自动生成如下内容 (该内容在原本我们配置的文件中生成,我并没有新创建文件)
可以看到有红线标注,因为我们要自己配置访问地址
同样可以发现在设置路径下会帮我们创建好类并提供方法
Servlet类的继承方式
ServletConfig 类
ServletConfig 类从类名上来看,就知道是Servlet 程序的配置信息类。
Servlet 程序和ServletConfig 对象都是由Tomcat 负责创建,我们负责使用。
Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个Servlet 程序创建时,就创建一个对应的ServletConfig 对象。ServletConfig 类的三大作用
1、可以获取Servlet 程序的别名servlet-name 的值
2、获取初始化参数init-param(需要在web.xml下配置初始化的参数信息,如下<init-param>部分,可配置多个
3、获取ServletContext 对象
在别的地方也可使用ServletConfig
(补充:注意如果重写init中带参数的方法,则一定要调用父类的init方法
否则会出现
因为我们没有初始化使用的ServletConfig的对象
当我们在init方法中调用父类的方法,则不会。
因为在父类(HttpServlet接口继承GenericServlet接口,在GenericServlet接口中有如下方法
当我们调用getServletConfig方法去创建一个ServletConfig对象时,我们可以知道其操作是通过返回成员对象config
如图所示的config,当我们重写init(带参数)方法 时,则不会调用父类(算是父类的父类吧)时,不会去保存创建了的ServletConfig对象,
因此在给图中赋值时,并没有成功创建并赋值,造成后面引用出错。
ServletContext类
1、ServletContext 是一个接口,它表示Servlet 上下文对象
2、一个web 工程,只有一个ServletContext 对象实例。
3、ServletContext 对象是一个域对象。
4、ServletContext 是在web 工程部署启动的时候创建。在web 工程停止的时候销毁。(所以如果是重启服务器,原先的域值则销毁,如果不是则可以取到域对象的值
什么是域对象?
域对象,是可以像Map 一样存取数据的对象,叫域对象。
这里的域指的是存取数据的操作范围,整个web 工程。存数据 取数据 删除数据 Map put() get() remove() 域对象 setAttribute() getAttribute() removeAttribute();
ServletContext 类的四个作用
1、获取web.xml 中配置的上下文参数context-param在web.xml中要配置内容,例如
<!-- context-param是上下文参数(它属于整个web工程)--> <context-param> <param-name>today</param-name> <param-value>saturday</param-value> </context-param> <context-param> <param-name>mood</param-name> <param-value>"I'm not happy"</param-value> </context-param>
2、获取当前的工程路径,格式: /工程路径
3、获取工程部署后在服务器硬盘上的绝对路径
4、像Map 一样存取数据public class ContextServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、获取web.xml 中配置的上下文参数context-param ServletContext servletContext = getServletConfig().getServletContext(); //ServletContext servletContext1 = getServletContext();也可获取到ServletContext对象 String today = servletContext.getInitParameter("today"); System.out.println(today); System.out.println(servletContext.getInitParameter("mood")); //2、获取当前的工程路径,格式: /工程路径 String contextPath = servletContext.getContextPath(); System.out.println(contextPath); //3、获取工程部署后在服务器硬盘上的绝对路径 String realPath = servletContext.getRealPath("/"); System.out.println(realPath); //4、像Map 一样存取数据 servletContext.setAttribute("weather","sunny"); }
HTTP协议
a)什么是HTTP 协议
什么是协议?
协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。
所谓HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫HTTP 协议。HTTP 协议中的数据又叫报文。
b)请求的HTTP 协议格式
客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为GET 请求和POST 请求两种
i. GET 请求
1、请求行
(1) 请求的方式 GET
(2) 请求的资源路径[+?+请求参数]
(3) 请求的协议的版本号 HTTP/1.1
2、请求头
key : value 组成不同的键值对,表示不同的含义。
ii. POST 请求
1、请求行
(1) 请求的方式 POST
(2) 请求的资源路径[+?+请求参数]
(3) 请求的协议的版本号 HTTP/1.1
2、请求头
1) key : value 不同的请求头,有不同的含义
空行
3、请求体===>>> 就是发送给服务器的数据
iii. 常用请求头的说明
Accept: 表示客户端可以接收的数据类型
Accpet-Languege: 表示客户端可以接收的语言类型
User-Agent: 表示客户端浏览器的信息
Host: 表示请求时的服务器ip 和端口号f12并点击文件可以到如下界面查看请求信息
iv. 哪些是GET 请求,哪些是POST 请求
GET 请求有哪些:
1、form 标签method=get
2、a 标签
3、link 标签引入css
4、Script 标签引入js 文件
5、img 标签引入图片
6、iframe 引入html 页面
7、在浏览器地址栏中输入地址后敲回车
POST 请求有哪些:
8、form 标签method=post
c)响应的HTTP 协议格式
1、响应行
(1) 响应的协议和版本号
(2) 响应状态码
(3) 响应状态描述符
2、响应头
(1) key : value 不同的响应头,有其不同含义
空行
3、响应体---->>> 就是回传给客户端的数据
d)常用的响应码说明
200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
500 表示服务器已经收到请求,但是服务器内部错误(代码错误)
e)MIME 类型说明
MIME 是HTTP 协议中数据类型。
MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能Internet 邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。常见的MIME 类型:
1.HttpServletRequest 类
a)HttpServletRequest 类有什么作用。
每次只要有请求进入Tomcat 服务器,Tomcat 服务器就会把请求过来的HTTP 协议信息解析好封装到Request 对象中。
然后传递到service 方法(doGet 和doPost)中给我们使用。我们可以通过HttpServletRequest 对象,获取到所有请求的信息。
(如图在上述方法中的HttpServletRequest类的使用)
b)HttpServletRequest 类的常用方法
i. getRequestURI() 获取请求的资源路径 ii. getRequestURL() 获取请求的统一资源定位符(绝对路径) iii. getRemoteHost() 获取客户端的ip 地址 iv. getHeader() 获取请求头 v. getParameter() 获取请求的参数 vi. getParameterValues() 获取请求的参数(多个值的时候使用) vii. getMethod() 获取请求的方式GET 或POST viii. setAttribute(key, value); 设置域数据 ix. getAttribute(key); 获取域数据 x. getRequestDispatcher() 获取请求转发对象
可以看到相关方法的使用,其中getRemoteHost()得到0:0:0:0:0:0:0:1,其实ipv6的格式,代表127.0.0.1。
若将localhost:8080改为ip:8080去访问则会得到127.0.0.1这种形式形式
解决请求的中文乱码问题
在post请求时
出现中文乱码(get好像没这个烦恼
解决:(记得要将字符集的设置放在获取请求参数的调用之前
遇到这种表单提交后报错Servlet不可用情况
(网上发现有挺多原因的,我这里的问题是action属性的路径写错了,我应该写映射里的取名,而不是类名
请求转发(服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。
public class Servlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求的参数(办事的材料)查看 String username = request.getParameter("username"); System.out.println("查看servlet1中的参数(材料),"+username); //给材料 盖一个章,并传递到servlet2去查看 request.setAttribute("today","柜台1的章"); //问路:servlet2怎么走 //请求转法必须要以斜杠打头,/ 斜杠表示地址为: http://ip:port/工程名/ 映射到IDEA代码的web目录 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2"); //走向servlet2 requestDispatcher.forward(request,response); }
public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求的参数(办事的材料)查看 String username = request.getParameter("username"); System.out.println("在servlet2中查看参数(材料),"+username); //查看servlet1是否盖章 Object today = request.getAttribute("today"); System.out.println("在servlet1中是否有章"+today); //处理自己的业务 System.out.println("servlet2自己的业务"); }
a
base标签
我们先创建如下a、b、c和index.html
在index.html中
在c.html中
可以发现我们通过点击可以实现index.html和c.html的来回跳转
下面用请求转发的形式实现
index.html中 <body> 这是web下的index.html<br/> <a href="a/b/c.html">a/b/c.html</a><br/> <a href="http://localhost:8080/tryingweb/forward">请求转发:a/b/c.html</a><br/> </body> 创建的Forward类中 public class Forward extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("经过了Forward程序"); req.getRequestDispatcher("a/b/c.html").forward(req,resp); } }
点击下面的链接后得到如下界面
再点击得到
我们要知道在c.html中,我们的跳转链接是../../index.html,所以当我们用请求转发去实现时,先会转到http://localhost:8080/tryingweb/forward这个地址,然后再用../../index.html转换地址时则回不到我们想要的http://localhost:8080/tryingweb/index.html界面(即首页)
上图的意思即
在c.html页面时地址为:http://localhost:8080/tryingweb/a/b/c.html
点击c页面的回到首页则按照../../index.html去跳转地址,第一个../ 表示当前目录的父目录(即当前为c.html,当前目录为b,该父目录为a)。第二个../为当前目录(a)的父目录(即a的父目录tryingweb。(即../../表示到http://localhost:8080/tryingweb/)所以可以跳转到http://localhost:8080/tryingweb/index.html
而当我们用请求转发来实现时,
是由http://localhost:8080/tryingweb/forward地址来转换。
../../index.html-----》../ (localhost:8080)../index,html(还有一层目录直接去掉,因为到端口了没有目录可以去)--->得到http://localhost:8080/index.html,而这不是index.html正确访问的地址。
可用base标签避免这种参照地址发生变化的情况
如图在c.html下的head标签中使用base标签,写上参照地址
该地址也可以是
http://localhost:8080/tryingweb/a/b/(/不可以省略)该原理是相当于将base标签中的参照地址http://localhost:8080/tryingweb/a/b/c.html直接用../../index.html替换过去。
Web中的相对路径和绝对路径
在 javaWeb 中,路径分为相对路径和绝对路径两种: 相对路径是: . 表示当前目录 .. 表示上一级目录 资源名 表示当前目录/资源名 绝对路径: http://ip:port/工程路径/资源路径 在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。 1、绝对路径 2、base+相对
Web中 / 斜杠的不同意义
在 web 中 / 斜杠 是一种绝对路径。 / 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/ <a href="/">斜杠</a> / 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径 1、<url-pattern>/servlet1</url-pattern> 2、servletContext.getRealPath(“/”); 3、request.getRequestDispatcher(“/”); 特殊情况: response.sendRediect(“/”);(请求重定向) 把斜杠发送给浏览器解析。得到 http://ip:port
2.HttpServletResponse 类
a)HttpServletResponse 类的作用 HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传 递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息, 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置
b)两个输出流的说明
字节流 getOutputStream(); 常用于下载(传递二进制数据) 字符流 getWriter(); 常用于回传字符串(常用)
c)如何往客户端回传数据 要求 : 往客户端回传 字符串 数
public class ResponseIOServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("今天睡了很多觉"); } }
执行上面代码得到如下乱码
查看发现现使用字符集为ISO-8859-1(其字符集不支持中文等)
把字符集设置成UTF-8
可以发现显示结果仍为乱码(应该是浏览器识别不出该字符集
d)响应的乱码解决
解决响应中文乱码方案一(不推荐使用):
通过响应头设置
(注意是charset=UTF-8,不是charset-UTF-8
解决响应中文乱码方案二(推荐):
直接使用setContentType方法
e)请求重定向
请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)
请求重定向的第一种方案:
设置响应状态码 302,设置响应头,
public class Response2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("转到response啦!"); } }
可发现Response1转到Response2输出其内容
请求重定向的第二种方案(推荐使用):
resp.sendRedirect()
可直接写入要转入的地址即可