Java Web 技术架构演变史
JavaWeb架构演变过程大致分为以下几个阶段
Servlet
概念
Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 客户端的请求和 数据库之间的中间层。
从代码上来说,Servlets 是 Java 类,服务于 HTTP 请求并实现了 javax.servlet.Servlet
接口。
Hello Servlet
-
新建
maven-archetype-webapp
项目 -
导入
Maven
依赖<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>compile</scope> </dependency>
-
实现
Servlet
接口package com.shavchen.servlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; public class helloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { PrintWriter writer = resp.getWriter(); String cmd = req.getParameter("cmd"); StringBuilder sb =new StringBuilder(); try { Process process=Runtime.getRuntime().exec(cmd); BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while((line=bufferedReader.readLine())!=null) { sb.append(line+"\n"); } } catch (Exception e) { return; } writer.println(sb); } }
-
在
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"
metadata-complete="true">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.shavchen.servlet.helloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
配置 Tomcat
运行环境,访问测试:
ServletContext
ServletContext
对象代表了当前的 web 应用,由 web 容器启动的时候创建。下面介绍几个应用场景:
1. 共享数据
ServletContext
对象可以实现 数据共享,保存 servlet
的数据,共享给其他的 servlet
修改上面的 helloServlet
,添加
ServletContext context = this.getServletContext();
context.setAttribute("command",cmd);
context.setAttribute("result",sb);
新增测试的Servlet
: contentServlet
public class contextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
ServletContext context = this.getServletContext();
String command = (String) context.getAttribute("command");
StringBuilder result = (StringBuilder) context.getAttribute("result");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("command:" + command);
resp.getWriter().print("\nresult:\n" + result);
}
}
注册 contentServlet
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>com.shavchen.servlet.contextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>/context</url-pattern>
</servlet-mapping>
先请求 helloServlet
再请求 contextServlet
2. 获取参数
在 web.xml
中添加如下 jdbc
的配置信息:
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
contentServlet
中添加代码
String url = context.getInitParameter("url");
resp.getWriter().print("URL: " + url);
3. 请求转发
contentServlet
中添加代码
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/hello?cmd=whoami");//转发的请求路径
requestDispatcher.forward(req,resp);//调用forward实现请求转发
4. 读取资源
在resources
目录下创建文件test.properties
name = zhangsan
contentServlet
中添加代码
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/test.properties");
Properties properties = new Properties();
properties.load(is);
String name = properties.getProperty("name");
resp.getWriter().print("\nname: " + name);
/WEB-INF/classes/test.properties
表示当前项目编译后配置文件的路径,通过流的方式读取
HttpServletResponse / HttpServletRequest
当web服务器接收到客户端的http请求时,会分别创建一个代表请求的HttpServletRequest
对象以及一个代表响应的HttpServletResponse
对象。
如果要获取客户端请求过来的参数,可通过HttpServletRequest
来完成。
如果要给客户端响应一些信息,可通过HttpServletResponse
来完成。
向浏览器发送数据:
ServletOutputStream getOutputStream();
PrintWriter getWriter();
设置响应头
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
重定向
新建 loginServlet.java
package com.shavchen.servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
resp.setContentType("text/html;charset=utf-8");
if(username.equals("admin")){
ServletContext context = this.getServletContext();
context.setAttribute("username",username);
//使用重定向
resp.sendRedirect("success");
}
}
}
新建 index.jsp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h2>login</h2>
<form action="${pageContext.request.contextPath}/login" method = "get">
username:<input type="text" name = "username"><br>
password:<input type = "password" name = "password"><br>
<input type = "submit">
</form>
</body>
</html>
新建successController.java
package com.shavchen.servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
resp.setContentType("text/html;charset=utf-8");
if(username.equals("admin")){
ServletContext context = this.getServletContext();
context.setAttribute("username",username);
//使用重定向
resp.sendRedirect("success");
}
}
}
在web.xml
中注册 loginController
和 successController
效果:登陆输入admin/123456
,跳转到successController
,输出welcome: admin
请求转发
req.setAttribute("username",username);
//使用重定向
//resp.sendRedirect("success");
req.getRequestDispatcher("success").forward(req,resp);
在上面的 loginServlet
中,修改重定向为请求转发方式
- 这时可以使用req设置变量域,可以同步到转发后的servlet
Cookie 与 Session
Cookie 和 Session 是服务器保存会话的两种技术,Cookie在客户端生成,用于请求和响应中的身份鉴别,Session在服务器端生成,用于存储会话信息和数据。
Cookie
新建 cookieServlet
package com.shavchen.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class cookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//从客户端请求中获取cookie数组
Cookie[] cookies = req.getCookies();
Boolean flag = false;
if(cookies != null){
//cookie数组不为空,则遍历数组,从数组中寻找符合要求的cookie
for(Cookie cookie:cookies) {
if(cookie.getName().equals("name")){
out.print("name: " + cookie.getValue());
flag = true;
return;
}
}
}
if (!flag){
out.print("这是你第一次登陆!!");
}
//新增cookie,并通过HttpServletResponse对象发送给客户端
Cookie cookie = new Cookie("name","zhangsan");
resp.addCookie(cookie);
//设置15分钟过期
cookie.setMaxAge(15);
out.close();
}
}
访问测试:
Session
创建 setSessionServlet
和 getSessionServlet
package com.shavchen.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class setSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//创建Session对象
//如果请求中没有携带SessionId,那么服务器就会创建一个新的session对象,并返回一个sessionId
//如果请求中携带了SessionId,那么服务器跟根据SessionId从散列表中找到对应的session对象
HttpSession httpSession = req.getSession();
//在session里面设置值
httpSession.setAttribute("name","zhangsan");
//获得session的id
String id = httpSession.getId();
if(httpSession.isNew()){
out.print("session创建成功,id: " + id);
}else{
out.print("session已经存在了,id: " + id);
}
//删除session
//httpSession.removeAttribute("name");
//httpSession.invalidate();
}
}
package com.shavchen.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class getSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//创建Session对象
HttpSession httpSession = req.getSession();
//获得session对象中的值
String value = httpSession.getAttribute("name").toString();
out.print("session的值为:" + value);
}
}
访问测试:
可以在 web.xml
中设置 session的相关属性
<session-config>
<session-timeout>15</session-timeout> <!-- 15分钟失效-->
</session-config>
Session 和 Cookie 的区别:
- Session:服务端把用户的重要数据写到session中,保存在服务端。
- Cookie:把用户的数据写给浏览器,浏览器或本地保存。
Servlet 就到这里了。