一、servlet
servlet是服务器三大组件(servlet,filter,listener)之一。servlet用来处理请求和响应(request,response)。servlet即实现了Servlet接口的实现类
注册功能:
注册页面-->提交按钮-->servlet-->将数据保存到数据库(JDBC)-->响应浏览器
需要一个Java程序(servlet的特点):
1、在服务器中有一个可以被访问的路径
2、所有功能的实现由tomcat服务器管理,即对象的创建或方法的调用都是由服务器在某个时间自动执行的
二、使用servlet
1、创建一个类,实现Servlet接口
public class FirstServlet implements Servlet {
//初始化方法
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
//返回servlet的配置信息
@Override
public ServletConfig getServletConfig() {
return null;
}
//提供服务,即处理请求和响应
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("helloworld");
servletRequest.getRequestDispatcher("/success.html").forward(servletRequest, servletResponse);
}
//获取servlet的信息
@Override
public String getServletInfo() {
return null;
}
//销毁
@Override
public void destroy() {
}
}
2、在web.xml中注册servlet,即为此servlet设置一个可以访问的路径
<!--注册FirstServlet-->
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.atguigu.servlet.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
注意:
A:<servlet-name>设置servlet的友好名称,一般设置为servlet的类名
B:<servlet-class>设置servlet的全类名
C:<url-pattern>设置servlet的虚拟路径,可以设置多个,一般设置为"/类名",/不能省略,代表在上下文路径下访问
例如:以上servlet的配置的访问方式,localhost:8080/上下文路径/FirstServlet
三、servlet的生命周期
经过观察,servlet的访问是由servlet容器(服务器)管理的,即servlet的实例化,以及其中方法的调用,都是由servlet容器(服务器)完成的,问:服务器是如何管理servlet的?
1、初始化-->init,实例化之后紧接着初始化,在服务器工作的整个过程中,只执行一次,默认第一次访问时执行
注意:可以再web.xml中,注册servlet的标签中加入标签<load-on-startup>,将此过程的执行时间提前到服务器启动时
<servlet>
<!--servlet的友好名称-->
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.atguigu.servlet.FirstServlet</servlet-class>
<!--
<load-on-startup>设置servlet的初始化时机
默认第一次访问时初始化,若设置此标签,并且其中设置了正整数,就可以将servlet的初始化事件提前到服务器启动时
标签中设置的值越小,优先级越高
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
<url-pattern>/code.jpg</url-pattern>
</servlet-mapping>
2、服务-->service,处理请求和响应,每次浏览器访问此servlet,service()都会执行一次
3、销毁-->destroy,服务器关闭时销毁,在服务器工作的整个过程中,只执行一次
四、ServletConfig和ServletContext
ServletConfig:表示servlet的配置信息
//ServletConfig功能1:获取servlet的友好名称
String servletName = servletConfig.getServletName();
System.out.println("SecondServlet的友好名称-->"+servletName);
//ServletConfig功能2:获取servlet的初始化参数
String testInitParam = servletConfig.getInitParameter("testInitParam");
System.out.println("SecondServlet的初始化参数-->"+testInitParam);
//ServletConfig功能3:获取ServletContext对象
ServletContext servletContext = servletConfig.getServletContext();
ServletContext:表示当前工程的上下文对象。其本质就是当前的工程,因此可通过ServletContext获取当前工程的信息,并且此对象在服务器启动时创建,在服务器关闭时销毁,服务器工作的整个过程中只创建一次。同时也是一个域对象,可以在其范围内(整个工程的范围内)共享数据,在整个工程的任意一个位置都可以获取共享的数据
/**
* ServletContext功能1:获取当前工程的部署路径(编译路径)
* servletContext.getRealPath(""):获取当前工程的部署路径
* D:\IDEA\workspace\javaee0922\out\artifacts\day06_servlet_war_exploded
* servletContext.getRealPath("abc"):获取当前工程的部署路径下abc的路径
* D:\IDEA\workspace\javaee0922\out\artifacts\day06_servlet_war_exploded\abc
*/
String realPath = servletContext.getRealPath("abc");
System.out.println("当前工程的部署路径-->"+realPath);
//ServletContext功能2:获取当前工程的初始化参数
String testContextParam = servletContext.getInitParameter("testContextParam");
System.out.println("当前工程的初始化参数-->"+testContextParam);
//ServletContext功能3:获取上下文路径
String contextPath = servletContext.getContextPath();
System.out.println("获取上下文路径-->"+contextPath);
//ServletContext功能4:作为一个域对象,在其范围之内(整个工程的范围内)共享数据
servletContext.setAttribute("testServletContext", "helloworld");
注意:
A:servlet的初始化参数的配置
<servlet>
<servlet-name>SecondServlet</servlet-name>
<servlet-class>com.atguigu.servlet.SecondServlet</servlet-class>
<init-param>
<param-name>testInitParam</param-name>
<param-value>你好servlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SecondServlet</servlet-name>
<url-pattern>/SecondServlet</url-pattern>
</servlet-mapping>
B:当前工程的初始化参数
<context-param>
<param-name>testContextParam</param-name>
<param-value>hello,servlet</param-value>
</context-param>
五、Servlet的扩展实现类
HttpServlet-->(继承)-->GenericServlet-->(实现)-->Servlet
GenericServlet:实现了Servlet接口,将其中不常用的方法进行了重写,例如init()和destroy(),其重写的方法中没有任何内容。但是真正处理请求的方法service()仍然是一个抽象方法
HttpServlet:继承了GenericServlet,重写了service(ServletRequest,ServletResponse),在其重写的方法中,将ServletRequest-->HttpServletRequest,ServletResponse-->HttpServletResponse,并调用service(HttpServletRequest,HttpServletResponse),在此方法中,根据不同的请求方式,调用了不同的方法,例如:GET-->doGet(),POST-->doPost(),因此以后创建servlet,使用继承HttpServlet的方式,而写只需要重写doGet()和doPost()
六、HttpServletRequest和HttpServletResponse
HttpServletRequest封装了请求报文,因此可以获取请求相关信息,即处理请求
HttpServletRequest的功能:
1、获取请求参数
注意:请求参数指get请求时拼接在请求地址后的数据,或者post请求时请求报文的请求体中的数据,格式为name=value&name=value
request.getParameter("username");//获取唯一的请求参数
request.getParameterValues("hobby");//获取多个同名的请求参数
注意:request获取请求参数的乱码问题
A:get请求下的乱码,是tomcat的编码丢失造成的,需要在tomcat的配置文件server.xml中,71行左右的标签中添加属性URIEncoding="UTF-8"
B:post请求下的乱码,需要在获取请求参数之前加入代码request.setCharacterEncoding("UTF-8");
2、请求转发
request.getRequestDispatcher("/success.html").forward(request, response);
分析:
testForm.html-->TestServlet-->success.html
发现地址栏中的地址不变,因此转发是服务器内部的跳转行为,指将当前请求传递到下一个资源继续处理
HttpServletResponse封装了响应报文,因此可以响应客户端,即处理响应
HttpServletResponse功能:
1、响应浏览器数据
PrintWriter writer = response.getWriter();
writer.write("helloworld<br>");
writer.print("你好");
注意:响应数据时出现乱码的解决方案
A:设置响应到浏览器数据的编码格式
response.setCharacterEncoding("UTF-8");
B:设置浏览器的解码方式
response.setContentType("text/html;charset=UTF-8");
2、重定向
response.sendRedirect(request.getContextPath()+"/success.html");
发现地址栏中的地址发生变化,为最终显示的页面的路径,说明浏览器实现了两次跳转,第一次跳转TestServlet,通过重定向的代码的执行,浏览器再次跳转重定向指向的路径
总结:
当业务逻辑实现结果为成功,则使用重定向;若失败,则使用转发
例如:登录成功使用重定向,失败使用转发