一、JSP
JSP是一种特殊的文件格式,它能够在html中嵌入Java代码,但它本质是一个Servlet子类
JSP的执行流程:
浏览器向服务器请求JSP——>服务器找到对应的JSP文件——>将它翻译成Java代码并编译执行——>将执行的结果返回给服务器
下面给出一段简单的JSP代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>MyJSP</title>
</head>
<body>
//声明式:用来在Jsp中声明成员变量
<%!
int count = 0;
%>
//用来在JSP中进行业务逻辑操作
<% count++;
%>
<h3>
//表达式:用来在jsp中输出内容
<%="访问次数"+count%>
</h3>
</body>
</html>
上述JSP翻译成java后
public final class MyJsp_jsp extends HttpJspBase implements JspSourceDependent, JspSourceImports {
int count = 0;
private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();
private static Map<String, Long> _jspx_dependants;
private static final Set<String> _jspx_imports_packages = new HashSet();
private static final Set<String> _jspx_imports_classes;
private volatile ExpressionFactory _el_expressionfactory;
private volatile InstanceManager _jsp_instancemanager;
static {
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
public MyJsp_jsp() {
}
public Map<String, Long> getDependants() {
return _jspx_dependants;
}
public Set<String> getPackageImports() {
return _jspx_imports_packages;
}
public Set<String> getClassImports() {
return _jspx_imports_classes;
}
public ExpressionFactory _jsp_getExpressionFactory() {
if (this._el_expressionfactory == null) {
synchronized(this) {
if (this._el_expressionfactory == null) {
this._el_expressionfactory = _jspxFactory.getJspApplicationContext(this.getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return this._el_expressionfactory;
}
public InstanceManager _jsp_getInstanceManager() {
if (this._jsp_instancemanager == null) {
synchronized(this) {
if (this._jsp_instancemanager == null) {
this._jsp_instancemanager = InstanceManagerFactory.getInstanceManager(this.getServletConfig());
}
}
}
return this._jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (!DispatcherType.ERROR.equals(request.getDispatcherType())) {
String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow", "GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow", "GET, HEAD, POST, OPTIONS");
response.sendError(405, "JSPs only permit GET, POST or HEAD. Jasper also permits OPTIONS");
return;
}
}
JspWriter out = null;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
PageContext pageContext = _jspxFactory.getPageContext(this, request, response, (String)null, true, 8192, true);
_jspx_page_context = pageContext;
pageContext.getServletContext();
pageContext.getServletConfig();
pageContext.getSession();
out = pageContext.getOut();
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>MyJSP</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(13);
out.write(10);
++this.count;
out.write("\r\n");
out.write("<h3>\r\n");
out.write(" ");
out.print("访问次数" + this.count);
out.write("\r\n");
out.write("</h3>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (Throwable var13) {
if (!(var13 instanceof SkipPageException)) {
out = (JspWriter)_jspx_out;
if (_jspx_out != null && ((JspWriter)_jspx_out).getBufferSize() != 0) {
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (IOException var12) {
}
}
if (_jspx_page_context == null) {
throw new ServletException(var13);
}
_jspx_page_context.handlePageException(var13);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
二、Servlet
Servlet就是一个Java的类,用来接受浏览器的request并返回给浏览器response的,它的书写流程如下
- 书写一个继承HttpServlet类
- 重写service方法
- 在WEB-INF文件夹的web.xml中配置访问路径
web.xml
<?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">
<context-param>
<param-name>enc</param-name>
<param-value>utf-8</param-value>
</context-param>
<servlet>
<servlet-name>test1</servlet-name>
<servlet-class>com.bigWhiteXie.servlet.MyServelet</servlet-class>
<init-param>
<param-name>enc</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>test1</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DoLogin</servlet-name>
<servlet-class>com.bigWhiteXie.servlet.DoLogin</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DoLogin</servlet-name>
<url-pattern>/DoLogin</url-pattern>
</servlet-mapping>
</web-app>
一个Servlet类
package com.bigWhiteXie.servlet;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class MyServelet extends HttpServlet {
private String message;
static int count = 0;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.print("<html>");
out.print("<head>");
out.print("</head>");
out.print("<body>");
out.print("<h1>欢迎访问</h1>");
out.print("访问次数:"+(++count));
out.print("</body>");
out.print("</html>");
}
}
三、Servlet的生命周期
- 类加载
- 类加载的时机:默认是第一次访问该servlet子类的时候
- <load-on-startup>0</load-on-startup>(当启动服务器时候加载,在<servlet>标签中设置) 数字越小加载的时机越往前
- 实例化,利用反射进行实例化
- 初始化
- 服务请求
- 销毁
一个servlet的生命周期函数执行顺序:
执行构造函数——>执行init()(一般用于加载或读取配置文件)——>执行service()——>执行destory()
四、Servlet核心源码
- 首先来了解一下Serlet的继承关系
- Servlet——>GenericServlet——>HttpServlet——>自定义Servlet子类
Servlet
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
可以看到,servlet作为一个接口提供给我们如上的五个主要函数
ServletConfig
public interface ServletConfig {
//获取该Servlet在web.xml中设置的name
String getServletName();
//获取web.xml中设置的全局变量
ServletContext getServletContext();
//获取该Servlet的初始变量
String getInitParameter(String var1);
//获取该Servlet初始变量的名字
Enumeration<String> getInitParameterNames();
}
GenericServlet
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
private transient ServletConfig config;
public GenericServlet() {
}
public void destroy() {
}
//实现获取初始化参数的方法
public String getInitParameter(String name) {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getInitParameter(name);
}
}
public Enumeration<String> getInitParameterNames() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getInitParameterNames();
}
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getServletContext();
}
}
public String getServletInfo() {
return "";
}
//传入一个ServletConfig实现类,并将它设置成成员变量
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public void log(String msg) {
this.getServletContext().log(this.getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
public String getServletName() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
} else {
return sc.getServletName();
}
}
}
从上面代码可以看出来,GenericServlet实现了除Service以外的所有方法。
HttpServlet
HttpServlet的源码就不贴,我们只用知道HttpServlet主要实现了service方法,目的是当子类不重写service方法时返回给浏览器一个错误。
五、Servlet读取初始参数和全局参数
要读取初始化参数和全局参数首先你需要在web.xml文件中进行设置
//全局参数
<context-param>
<param-name>enc</param-name>
<param-value>utf-8</param-value>
</context-param>
<servlet>
<servlet-name>test1</servlet-name>
<servlet-class>com.bigWhiteXie.servlet.MyServelet</servlet-class>
//初始化参数
<init-param>
<param-name>enc</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
读取
读取初始化参数只需要在对应的servlet类中执行
String enc = this.getInitParameter("enc");
读取全局参数
String enc1 = this.getServletContext().getInitParameter("enc");
六、Servlet处理request的中文乱码
当请求为post的时候
request.setCharacterEncoding(“utf-8”);
当请求为get的时候
在server.xml中指定对应的服务器编码
<Connector port=“8080” protocol=“HTTP/1.1”
connectionTimeout=“20000”
redirectPort=“8443” URIEncoding=“utf-8” />