1、配置Tomcat服务器
一、Servlet 2.0
1、书写servlet程序
import javax.servlet.*;
import java.io.IOException;
public class MyServletDemo implements Servlet {
@Override
/**
* Servlet 初始化的时候执行,只会执行一次
*/
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("=======init=======");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
/**
* Servlet 请求的时候执行,会执行多次
*/
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("======hello service=====");
}
@Override
public String getServletInfo() {
return null;
}
@Override
/**
* Servlet 关闭的时候执行,会执行一次
*/
public void destroy() {
}
}
2、配置WEB-INF下面的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">
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>com.example.demoJJ.servlet.MyServletDemo</servlet-class>
<!--
指定Servlet的创建时机:
1. 第一次被访问时,创建。load-on-startup 配置的值为负数。
2. 在服务器启动时创建。load-on-startup 配置为0或者正数
3. 默认为负数
-->
<load-on-startup>-1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
</web-app>
3、解析
当你在浏览器中输入IP端口的时候,tomcat会对你的url进行解析,此时会有一个
/demo1
的路由,tomcat会在web.xml 中进行解析,刚好会有一个几个/demo1的路由与之对应。此时找到servlet-name
,通过servlet-name
会找到全类名的类,此时tomcat通过反射找到方法去执行(Class.forName() 加入字节码,newInstance产生实例)。
4、Servlet的生命周期
- 被创建:执行
init
方法,只会执行一次。 - 提供服务:执行
service
方法,执行多次。 - 被销毁:执行
destory
方法,执行一次。(正常关闭的时候会执行)
5、总结
-
Servlet
是单例的,会存在线程安全问题,所以尽量不要定义成员变量。
一、Servlet 3.0
的介绍
1、使用注解配置Servlet
介绍:
Servlet3.0
是向下兼容的,在Servlet 3.0
中支持注解的方式配置应用。当只有urlPatterns
的时候可以不写。
package com.example.demoJJ.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet(urlPatterns = "/demo2")
public class MySev3 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet 3.0");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
2、使用HttpServlet
进行进行书写程序
package com.example.demoJJ;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
private String message;
public void init() {
message = "Hello World!";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
// Hello
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>" + message + "</h1>");
out.println("</body></html>");
}
public void destroy() {
}
}
三、Request
对象的部分知识点
1、请求的转发与编码的设置
request.setCharacterEncoding("UTF-8"); // 设置编码
request.getRequestDispatcher("/demo1").forward(request, response); // 请求转发
2、设置属性,获取属性【共享数据】
request.setAttribute("name", "erik");
request.getAttribute("name");
四、一个小demo
1、工具类的编写
package com.example.demoLogin.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JdbcUtil {
private static DataSource ds;
private static String driver;
static {
// 读取配置文件
InputStream resourceAsStream = JdbcUtil.class.getClassLoader().getResourceAsStream("druid.properties");
Properties properties = new Properties();
try {
properties.load(resourceAsStream);
driver = properties.getProperty("driverClassName");
// 导入驱动
Class.forName(driver);
// 初始化数据库连接池
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据源
*
* @return
*/
public static DataSource getDatasource() {
return ds;
}
/**
* 获取连接池对象
*
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
2、实体类
package com.example.demoLogin.doman;
/**
*
*/
public class User {
private int id;
private String name;
private String password;
public User() {
}
public User(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
3、操作类
package com.example.demoLogin.dao;
import com.example.demoLogin.doman.User;
import com.example.demoLogin.util.JdbcUtil;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.SQLException;
public class UserDao {
/**
* 获取template
*/
private JdbcTemplate template = new JdbcTemplate(JdbcUtil.getDatasource());
/**
* 获取用户
*
* @param loginUser
* @return
* @throws SQLException
*/
public User getUserById(User loginUser) {
try {
String name = loginUser.getName();
String password = loginUser.getPassword();
String sql = "SELECT * FROM USER WHERE name = ? and password = ?";
return template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), name, password);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
}
4、Servlet类
package com.example.demoLogin.servlet;
import com.example.demoLogin.doman.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
// 获取属性
User user = (User) req.getAttribute("user");
PrintWriter writer = resp.getWriter();
writer.write("欢迎:" + user.getName() + "登录成功!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.example.demoLogin.servlet;
import com.example.demoLogin.dao.UserDao;
import com.example.demoLogin.doman.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
// 获取请求参数
String name = req.getParameter("name");
String password = req.getParameter("password");
User user = new User();
user.setName(name);
user.setPassword(password);
System.out.println(user);
User user1 = new UserDao().getUserById(user);
if (user1 == null) {
// 失败
req.getRequestDispatcher("/failServlet").forward(req, resp);
} else {
// 成功
req.setAttribute("user", user1);
req.getRequestDispatcher("/successServlet").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.example.demoLogin.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("登录失败了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5、html展示
<%--
Created by IntelliJ IDEA.
User: Erik.Zhou
Date: 2022/2/17
Time: 11:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/demoLogin_war_exploded/login" method="get">
用户名: <input type="text" name="name" placeholder="输入用户名!">
密码: <input type="password" name="password" placeholder="输入密码!">
<button type="submit">登录</button>
</form>
</body>
</html>
6、目录结构
7、状态码
分类:
- 1xx:服务器就接收客户消息,但没有接收完成,等待一段时间后,发送1xx状态码。
- 2xx:成功。代表:200
- 3xx:重定向。代表:302(重定向)【resp.sendRedirect("路径"); 】。304(访问缓存)
- 4xx:客户端错误。404(资源或者页面不存在)。405 请求方式和对应的方法不存在。403一般用于鉴权。
- 5xx:服务端错误。500(服务器内部异常)
8、响应数据
- 响应头:
- content-type // resp.setContentType("text/html;charset=utf-8"); 设置编码
9、重定向和转发的区别:
重定向:
- 地址栏发生变化。
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求。不能使用request对象来共享数据
转发的特点: - 转发地址栏路径不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求,能使用request对象来共享数据。
10、简单的验证码的使用:
package com.example.demoLogin.servlet;
import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet(name = "ImgServlet", value = "/ImgServlet")
public class ImgServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
// 1、创建一个对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2、美化图片
Graphics graphics = image.getGraphics();
graphics.setColor(Color.pink);
graphics.fillRect(0, 0, width, height);
graphics.setColor(Color.blue);
graphics.drawRect(0, 0, width - 1, height - 1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
for (int i1 = 0; i1 < 4; i1++) {
int i = random.nextInt(str.length());
graphics.drawString(str.charAt(i) + "", width / 5 * i1, height / 2);
}
// 画干扰线
for (int i = 0; i < 10; i++) {
int x1 = random.nextInt(width);
int x2 = random.nextInt(width);
int y1 = random.nextInt(height);
int y2 = random.nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
// 3、将图片保存到页面
ImageIO.write(image, "jpg", response.getOutputStream());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
11、资源的处理:[文件下载]
// 获取参数
String filename = req.getParameter("filename");
// 获取预发布
ServletContext context = req.getServletContext();
// 获取真实路径
String realPath = context.getRealPath(filename);
// 获取输入流对象
FileInputStream inputStream = new FileInputStream(realPath);
// 获取类型
String mimeType = context.getMimeType(filename);
// 设置response响应头
// 1、设置响应头类型:content-type
resp.setHeader("content-type", mimeType);
resp.setHeader("content-disposition", "attachment;filename=" + filename);
// 将字节流写到输出流中
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
// 关闭流对象
inputStream.close();
outputStream.close();
// 可能会初选中文的乱码问题,可以针对不同浏览器设置不同的头信息处理
12、Cookie
的快速入门
// 创建cookie
Cookie cookie1 = new Cookie("", "");
cookie1.setMaxAge(100); // 设置cookie的时间。正数:存活的秒数。0代表删除。默认值为负数,关闭即删除
// cookie.setPath("/"); // 共享cookie设置cookie 的范围,共享
// cookie.setDomain(".baidu.com");
resp.addCookie(cookie1);
// 获取cookie
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println(cookie.getName());
}
}
13、Session
的快速入门
session
存储在服务器端,他的实现是基于cookie
的,当第一次请求的时候,服务器端会set-cookie
,一个值为:JSESSIONID
的对象,后期客户端会通过这个请求头来向后端请求,从而保证了session
的一致性。
细节:
- 当客户端关闭后,服务器不关闭,再次获取session是否是同一个?
- 默认情况下不是。
- 如果需要是同一个则可以创建cookie,键为:JSESSION,设置最大存活时间,让cookie持久化存活。
// 让浏览器关闭后仍然是一个session。
HttpSession session = req.getSession();
Cookie jsessionid = new Cookie("JSESSIONID", session.getId());
jsessionid.setMaxAge(60 * 60);
- 客户端不关闭,服务器关闭后,再次获取的session是同一个嘛?【tomcat做了】
- 不是同一个,但是要群数据不丢失。
- session 的钝化
- 在服务器正常关闭之前,将session对象序列号到硬盘上
- session的活化
- 在服务器启动后,将session文件转化为内存中的session对象即可。
- session什么时候被销毁?
- 服务器关闭
- session对象调用invalidate()。
- session默认的失效时间为 30 分钟。【web.xml中进行配置】
14、JSP
的快速入门
- 指令:
- 作用:用户配置JSP页面,导入资源文件
- 格式:
<%@ 指令名称 属性名1=属性值 属性名2=属性值2 ....%> 如:<%@ page import="java.net.URLDecoder" %>
- 分类:
- page:配置JSP页面的。
<%@ page import="java.net.URLDecoder" %>
。 - include:完成包含。导入页面的资源文件。如:
公共头部
或者公共尾部
。 - taglib:导入资源。
- page:配置JSP页面的。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 注释:
<%-- 注释内容 --%>
- 在jsp页面中不需要创建,直接使用的对象一共有9个:
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据 |
request | HttpServketRequest | 一次请求访问的多个资源 |
session | HTTPSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户共享的数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面的对象 |
out | JSPWrite | 输出对象,可以把数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | :只有当isErrorPage 为true的时候才能使用。 |
- 表达式
<%! %> // 解析为:类变量
<%= "erik" %> // 输出到页面
<% %> // 局部数据。service中的数据。
15、MVC
开发模式
jsp
的发展演变历史
1、早期只有servlet,只能使用response输出标签数据,非常麻烦!
2、后来有了jsp
,简化了servlet的开发,如果过度应用jsp,在jsp中际写大量的java代码,又写大象的html代码,造成难于维护,难于分工协作。
3、再后来,java的web开发,借鉴mvc开发魔术,是得程序的设计更加的合理。-
MVC:
- M:Model,模型。完成具体的业务操作,如:查询数据库,封装对象。
- V:view,视图。展示数据。
- C:controller,控制器。:获取用户的输入,调用模型,传给视图。
-
优缺点:
- 耦合性低。
- 重用性高。
- 使得小项目麻烦。
EL
表达式
${3>4}
\${3>4} // 忽视el表达式
- 使用:
${域名称.域名}:从指定域中获取指定的值
1. pageScope ---------> pageContext
2. requestScope----------> request
3. sessionScope----------> session
4. applacationScope------>applation(servletContext)
16、过滤器
的使用
package com.example.demoLogin;
import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebFilter(filterName = "MyFilter", value = {"/*"})
public class MyFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
// 放行
chain.doFilter(request, response);
}
}