是JAVA的基于WEB服务器的完成动态网页开发的一种技术
package com.it.servlet; import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; public class MyFirstServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取表单提交的参数,填写的参数是表单对应数据的name属性 String username = req.getParameter("username"); String password = req.getParameter("password"); if(username.equals("dqx") && password.equals("123")) { // 转发到/success.jsp req.getRequestDispatcher("/success.jsp").forward(req,resp); }else { // 在request作用域中存入一个 key value req.setAttribute("msg", "用户名或密码错误"); req.getRequestDispatcher("/login.jsp").forward(req, resp); } } }
<servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>com.it.servlet.MyFirstServlet</servlet-class> <!-- 配置在服务器启动时加载Servlet --> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <!-- 处理的请求 --> <url-pattern>/doLogin</url-pattern> </servlet-mapping>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <base href="<%=basePath%>"> </head> <body> <form action="doLogin" method="post"> <% String msg = (String) request.getAttribute("msg"); System.out.println("---------"); if(msg != null) { out.print(msg); } %> <hr> 用户名:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="登录"> </form> </body> </html>
<h1>登录成功</h1>
——————————————————————————————————
为什么需要读取配置?
答:因为有些配置是固定的(例如编码),许多地方都要使用到,而如果硬编码的话,一旦编码改变,则需要更改多处,影响维护。
<servlet> <servlet-name>myConfigServlet</servlet-name> <servlet-class>com.it.servlet.MyConfigServlet</servlet-class> <!-- 配置Servlet配置参数 --> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </servlet>
public class MyConfigServlet extends HttpServlet { private String charset; @Override public void init() throws ServletException { // 获得Servlet参数,这两种方式是一样的 charset = this.getInitParameter("charset"); charset = this.getServletConfig().getInitParameter("charset"); }
<context-param> <param-name>globalCharset</param-name> <param-value>GBK</param-value> </context-param>
public class MyConfigServlet extends HttpServlet { private String globalCharset; @Override public void init() throws ServletException { // 获得全局配置参数 globalCharset = this.getServletContext().getInitParameter("globalCharset"); System.out.println(globalCharset); }
// 注意,这里是因为演示,所以硬编码了,实际编码应该从配置中读取 // 这句话就是告知浏览器接收到响应数据时以何种类型处理,以何种编码解析 resp.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" />
byte[] bytes = username.getBytes("ISO-8859-1"); String newUsername = new String(bytes,"UTF-8");
可以在Servlet类上使用注解的方式代替在web.xml中的配置
import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @WebServlet(loadOnStartup = 0, initParams = {@WebInitParam(name = "charset",value = "UTF-8"),@WebInitParam(name = "key2",value = "value2")}, urlPatterns = "/AnnoServlet") public class AnnoServlet extends HttpServlet { }
// Servlet接口中的方法 void service(ServletRequest var1, ServletResponse var2);//核心方法,用于处理浏览器发送的请求 ServletConfig getServletConfig(); //用于获取Servlet的配置信息
答:因为继承了HTTPServlet方法没有重写service()方法或doGet()、doPost()方法
答:因为本身我们开发者编写一个Servlet类就是为了处理请求,而既没有service()方法处理请求,也没有doGet()、doPost(),那这个Servlet存在的意义就缺失了。所以HttpServlet处理时就直接报错,是为了告知调用者重写service()或者doGet()、doPost()等方法
// 格式: 协议://IP地址:端口号/资源路径 <a href="http://127.0.0.1:8080/myProject1/path1/update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/path1/subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="http://127.0.0.1:8080/myProject1/index.jsp">同一个服务器中不同项目中的文件servlet01/index.jsp</a> <br/> <a href="http://192.168.121.33:8080/demo/a.jsp">同一个局域网中不同服务器中的项目</a> <br/> <a href="http://www.baidu.com">外网服务器的项目</a> <br/>
提示:只能访问当前服务器的任何资源
<a href="/webdemo01/path1/update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="/webdemo01/path1/subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="/webdemo01/path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="/webdemo01/index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="/webdemo01/servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="/webdemo01/index.jsp">同一个服务器中不同项目中的文件servlet01/index.jsp</a> <br/> <%--不行--%> <a href="/demo/a.jsp">同一个局域网中不同服务器中的项目</a> <br/>
<a href="update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="../path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="../index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="../servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="../../myProject2/index.jsp">同一个服务器中不同项目中的文件
<head> <% // 这是绝对路径的base标签 String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; // 根路径的base标签 String genBasePath = request.getContextPath() + "/"; %> <base href="<%=genBasePath%>"> </head> <body> <%-- 注意,这里不要在写一个/了,不然就变成根路径与base标签无关了了 --%> <a href="index.jsp">访问index.jsp</a> </body>
转发,指的是在服务器跳转
服务器在内部接收到第一个请求时,转发到其他servlet或页面处理,然后返回数据给用户。
这个过程用户是不可见的,所以转发时,浏览器只会向服务器发出一个请求
重定向,客户端跳转
服务器在运行到重定向的语句时,将重定向请求发回给浏览器,其状态码为302(并携带者需要重定向的资源路径)
浏览器在接收到这个302的重定向响应后,用其中的资源路径地址再次向服务器发送一个请求。
所以这个过程中涉及到了2个请求。所以重定向是用户可见的。
// 转发(这里使用的是相对路径) req.getRequestDispatcher("index.jsp").forward(req, resp); // 重定向(这里使用的是相对路径) resp.sendRedirect("index.jsp");
转发能够获取request作用域中的数据,因为其转发的原理就是至始至终都只有一个请求,而request作用域的范围就是一个请求当中,所以能够获取
重定向不能获取request中的数据,因为重定向时,涉及到了2个请求,所以第二个请求已经不在第一个请求的作用范围内了,所以无法获取。
转发跳转后,由于是服务器内部跳转,浏览器无法察觉,所以还是显示的浏览器访问的资源路径。
重定向跳转后,由于是客户端跳转,跳转对浏览器是可见的,所以显示的路径是重定向的路径。
转发时候的字符串时候由于路径最前面会加上/项目名,所以写 / 代表着当前项目,这也意味着。转发只能转发到当前的项目资源。
绝对路径
转发:不支持
重定向:支持
相对路径(不推荐)
转发:支持
重定向:支持
根路径
转发:支持(当前项目)
重定向:支持(代表当前服务器,与在jsp中使用根路径是一样的)
其实每编写一个Servlet并使用web.xml配置好、或者使用注解的方式配置了一个Servlet时。
就相当于在Web根路径下放入了这个Servlet。