servlet
servlet:
定义:动态的web开发技术,本质是一个类,是运行在服务器端的一个java小程序
作用:处理业务逻辑,生成动态web内容
编写一个servlet步骤:
1.编写一个类
a.继承HttpServlet
b.重写doGet或者doPost方法
2.编写配置文件(web-inf/web.xml)
a.注册servlet
b.绑定路径
3.访问
http://主机:端口号/项目名/路径
接受参数: 格式:key=value
String value=request.getParameter("key")
例如: http://localhost/day09/hello?username=tom
request.getParameter("username")就可以获取tom值
回写内容:
response.getWriter().print("success");
处理响应数据中文乱码:
response.setContentType("text/html;charset=utf-8"); //建议大家放在方法中的第一行
小案例:
ServletTest01.java源码:
package com.servlet.hjh.day0529;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletTest01 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String value =req.getParameter("username");
System.out.println(value);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<servlet>
<servlet-name>ServletTest01</servlet-name>
<servlet-class>com.servlet.hjh.day0529.ServletTest01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest01</servlet-name>
<url-pattern>/test01</url-pattern>
</servlet-mapping>
</web-app>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="http://localhost:8080/Servlet/test01?username=hjh">request请求参数示例</a>
</body>
</html>
启动tomcat服务器,浏览器中输入,回车,显示“request请求参数示例”。当点击这个超链接时,页面刷新,发送一个带参数的请求“http://localhost:8080/Servlet/test01?username=hjh”。servlet类的“req.getParameter("username");”方法获取了url中的username的值hjh,进行输出。
往浏览器回写数据,会出现中文乱码:;使用resp.setContentType("text/html;charset=utf-8")设置浏览器输出的编码格式
package com.servlet.hjh.day0529;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletTest01 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取url参数
String value =req.getParameter("username");
System.out.println(value);
//往浏览器回写数据
//resp.getWriter().print("用户名username="+value);//???username=hjh 出现乱码
//设置浏览器输出的编码格式
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().print("用户名username="+value);//用户名username=hjh
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
LoginServlet案例:
数据库:
create database hejh;
use hejh;
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
email varchar(20),
name varchar(20),
sex varchar(10),
birthday date,
hobby varchar(50)
);
insert into user values (null,'hjh','123','hjh@126.com','hjh','1','1988-01-01',null);
案例的项目结构:
导包要注意,不能少!!!!
UserDao.java源码
package com.hjh.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.hjh.domain.User;
import com.hjh.util.DataSourseUtils;
public class UserDao {
public User findUserByUsernameAndPassword(String username, String password) throws SQLException {
//创建QueryRunner对象,操作sql语句
QueryRunner qr = new QueryRunner(new DataSourseUtils().getDataSourse());
//编写sql语句
String sql = "select * from user where username=? and password=?";
//执行sql BeanHandler, 将查询结果的第一条记录封装成指定的bean对象,返回
User user = qr.query(sql, new BeanHandler<User>(User.class),username,password);
//返回user对象
return user;
}
}
User.java源码:
package com.hjh.domain;
public class User {
private int id;
private String username;
private String password;
public User() {}
public User(int id,String username,String password) {
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
UserService.java源码:
package com.hjh.service;
import java.sql.SQLException;
import com.hjh.dao.UserDao;
import com.hjh.domain.User;
public class UserService {
public User login(String username, String password) {
User user = null;
try {
user = new UserDao().findUserByUsernameAndPassword(username,password);
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}
LoginServlet.java源码
package com.hjh.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hjh.domain.User;
import com.hjh.service.UserService;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
response.setContentType("text/html;charset=utf-8");
//2.接收用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//3.调用UserService的login(username,password),返回一个user对象
User user = new UserService().login(username,password);
//4.判断user是否为空
if(user==null) {
//user为空
response.getWriter().print("用户名和密码不匹配");
}else {
//user为不为空
response.getWriter().print(user.getUsername()+":欢迎回来");
}
}
}
DataSourseUtils.java源码:
package com.hjh.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSourseUtils {
//建立连接池ds
private static ComboPooledDataSource ds = new ComboPooledDataSource();
//获取数据源
public static DataSource getDataSourse() {
return ds;
}
//获取连接
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//释放资源
public static void closeResourse(Connection conn,Statement st) {
try {
if(st!=null) {
st.close();
}else {
st = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null) {
conn.close();
}else {
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**释放资源closeResourse(conn,ps)*/
public static void closeResourse(Connection conn,PreparedStatement ps) {
try {
if(ps!=null) {
ps.close();
}else {
ps = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null) {
conn.close();
}else {
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**释放资源closeResourse(rs)*/
public static void closeResourse(ResultSet rs) {
try {
if(rs!=null) {
rs.close();
}else {
rs = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
c3p0-config.xml配置
<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<!-- 基本配置 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/hejh</property>
<property name="user">root</property>
<property name="password">root</property>
<!--扩展配置-->
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!-- 命名的配置 -->
<named-config name="XXX">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/xxxx</property>
<property name="user">root</property>
<property name="password">1234</property>
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">20</property>
<property name="minPoolSize">10</property>
<property name="maxPoolSize">40</property>
<property name="maxStatements">20</property>
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.hjh.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
index.html页面代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="http://localhost:8080/Servlet/login" method="get">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="login">
</form>
</body>
启动项目,浏览器中输入url:“http://localhost:8080/Servlet/login.html”回车,页面显示如下。用户名密码输入“hjh;123”,点击login按钮,表单提交到"http://localhost:8080/Servlet/login",给服务器发送一个请求,url为“http://localhost:8080/Servlet/login?username=hjh&password=123”,loginServlet类接收到用户请求 并处理,将用户提交的用户名密码和数据库中的用户名密码相比较。
常见的响应头-refresh
响应头格式:
refresh:秒数;url=跳转的路径
设置响应头:
response.setHeader(String key,String value);设置字符串形式的响应头
response.addHeader(String key,String value);追加响应头, 若之前设置设置过这个头,则追加;若没有设置过,则设置
设置定时刷新:
response.setHeader("refresh","3;url=/Servlet/login.html");
LoginServlet优化1:定时跳转
实现:在LoginServlet源码中加上红色部分代码即可
package com.hjh.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hjh.domain.User;
import com.hjh.service.UserService;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
response.setContentType("text/html;charset=utf-8");
//2.接收用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//3.调用UserService的login(username,password),返回一个user对象
User user = new UserService().login(username,password);
//4.判断user是否为空
if(user==null) {
//user为空
response.getWriter().print("用户名和密码不匹配,3秒后跳转");
//优化,定时跳转
response.setHeader("refresh","3;url=/Servlet/login.html");
}else {
//user为不为空
response.getWriter().print(user.getUsername()+":欢迎回来");
}
}
}
启动项目,输入错误的用户名或密码,点击login按钮,页面提示“用户名和密码不匹配,3秒后跳转”,3秒后跳转到index.html页面。
LoginServlet优化2:统计用户登录次数
在原loginServlet案例中,加入下面红色部分代码,实现打印当前用户登录次数的功能:
package com.hjh.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hjh.domain.User;
import com.hjh.service.UserService;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//初始化登录次数
@Override
public void init() throws ServletException{
//获取上下文对象
ServletContext context = getServletContext();
//初始化登录次数为0
context.setAttribute("count",0);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
response.setContentType("text/html;charset=utf-8");
//2.接收用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//3.调用UserService的login(username,password),返回一个user对象
User user = new UserService().login(username,password);
//4.判断user是否为空
if(user==null) {
//user为空
response.getWriter().print("用户名和密码不匹配,3秒后跳转");
//优化,定时跳转
response.setHeader("refresh","3;url=/Servlet/login.html");
}else {
//user为不为空
response.getWriter().println(user.getUsername()+":欢迎回来");
//获取上下文对象
ServletContext context = getServletContext();
//获取当前登录的次数sum
Integer sum = (Integer) context.getAttribute("count");
//登录成功了,次数自增1
sum++;
//再将次数放入上下文对象中
context.setAttribute("count", sum);
//获取最新的登录次数,打印输出
Integer count = (Integer) context.getAttribute("count");
response.getWriter().print("登录成功的总次数为:"+count);
}
}
}
serlvet总结:
servlet的体系结构:(了解)
Servlet:接口
|
GenericServlet:抽象类
|
HttpServlet:抽象类
|
自定义servlet
servlet常用方法:
void init(ServletConfig config):初始化
void service(ServletRequest request,ServletResponse response):服务 处理业务逻辑
void destroy():销毁
ServletConfig getServletConfig() :获取当前servlet的配置对象
GenericServlet常用方法:
除了service方法没有显示,其他都实现了
空参的Init() 若我们自己想对servlet进行初始化操作,重写这个init()方法即可
HttpServlet常用方法:
service做了实现,把参数强转,调用了重载的service方法
重载的service方法获取请求的方式,根据请求方式的不同调用相应doXxx()方法
doGet和doPost方法
servlet生命周期:
void init(ServletConfig config):初始化
* 初始化方法
* 执行者:服务器
* 执行次数:一次
* 执行时机:默认第一次访问的时候
void service(ServletRequest request,ServletResponse response):服务 处理业务逻辑
* 服务
* 执行者:服务器
* 执行次数:请求一次执行一次
* 执行时机:请求来的时候
void destroy():销毁
* 销毁
* 执行者:服务器
* 执行次数:只执行一次
* 执行时机:当servlet被移除的时候或者服务器正常关闭的时候
serlvet是单实例多线程
默认第一次访问的时候,服务器创建servlet,并调用init实现初始化操作.并调用一次service方法
每当请求来的时候,服务器创建一个线程,调用service方法执行自己的业务逻辑
当serlvet被移除或服务器正常关闭的时候,服务器调用servlet的destroy方法实现销毁操作.
url-pattern的配置:★
方式1:完全匹配 必须以"/"开始 例如: /hello /a/b/c
方式2:目录匹配 必须"/"开始 以"*"结束 例如: /a/* /*
方式3:后缀名匹配 以"*"开始 以字符结尾 例如: *.jsp *.do *.action
优先级:
完全匹配>目录匹配>后缀名匹配
练习:
有如下的一些映射关系:
Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 *.do
问题:
当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应
Servlet引擎将调用Servlet1。
当请求URL为“/abc”时,“/*”和“/abc”都匹配,哪个servlet响应
Servlet引擎将调用Servlet3。
当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet1。
当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet2.
当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet2。
在servlet标签有一个子标签 load-on-startup
作用:用来修改servlet的初始化时机
取值:正整数 值越大优先级越低
注意:
当我们的配置文件里面没有指定配置的话,会查找tomcat的web.xml,
若请求我们自己的项目处理不了,tomcat的默认的servlet会帮我们处理信息
路径的写法:
相对路径:
当前路径 ./ 或者 什么都不写
上一级路径 ../
绝对路径:(我们使用)
带主机和协议的绝对路径(访问站外资源)
http://www.itheima.com/xxxx
http://localhost:80/day09/hello
不带主机和协议的绝对路径
ServletContext:
上下文
常用的方法:
setAttribute(String key,Object value);//设置值
Object getAttribute(String key);//获取值
removeAttribute(String key)://移除值
获取全局管理者:
getServletContext();
ServletConfig:(了解)
servlet配置对象
作用:
1.获取当前servlet的名称
2.获取当前servlet的初始化参数
3.获取全局管理者
方法:
String getServletName():获取当前servlet的名称(web.xml配置的servlet-name)
String getInitParameter(String key):通过名称获取指定的参数值
Enumeration getInitParameterNames() :获取所有的参数名称
初始化参数是放在 web.xml文件
servlet标签下子标签 init-param
★getServletContext():获取全局管理者
servletconfig是由服务器创建的,在创建servlet的同时也创建了它,通过servlet的init(ServletConfig config)将config对象
传递给servlet,由servlet的getServletConfig方法获取
ServletConfig小练习:
web.xml配置:
<servlet>
<servlet-name>SConfigServlet</servlet-name>
<servlet-class>com.hjh.servlet.SConfigServlet</servlet-class>
<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
<init-param>
<param-name>hjh</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SConfigServlet</servlet-name>
<url-pattern>/config</url-pattern>
</servlet-mapping>
package com.hjh.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SConfigServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletConfig对象
ServletConfig config = getServletConfig();
//获取servlet的名称
String servletName = config.getServletName();
System.out.println("servletName的名称是:"+servletName);
//获取初始化参数,获取单一的值
String age = config.getInitParameter("age");
System.out.println("age的值是:"+age);
System.out.println("------------------------------------------------------------");
//获取所有的初始化参数
Enumeration<String> initParameterNames = config.getInitParameterNames();
while(initParameterNames.hasMoreElements()) {
String name = initParameterNames.nextElement();
System.out.println("name:"+config.getInitParameter(name));
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
eclipse中console输出为:
servletName的名称是:SConfigServlet
age的值是:18
------------------------------------------------------------
name:123
name:18
ServletContext上下文
一个项目的引用.代表了当前项目.
当项目启动的时候,服务器为每一个web项目创建一个servletcontext对象.
当项目被移除的时候或者服务器关闭的时候servletcontext销毁
作用:
1.获取全局的初始化参数
2.共享资源(xxxAttribute)
3.获取文件资源
4.其他操作
获取servletcontext:
方式1:了解
getServletConfig().getServletContext()
方式2:
getServletContext()
常用方法:
1.了解
String getInitParameter(String key):通过名称获取指定的参数值
Enumeration getInitParameterNames() :获取所有的参数名称
在根标签下有一个 context-param子标签 用来存放初始化参数
<context-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</context-param>
2.xxxAttribute
3.
String getRealPath(String path):获取文件部署到tomcat上的真实路径(带tomcat路径)
getRealPath("/"):D:\javaTools\apache-tomcat-7.0.52\webapps\day09\
InputStream getResourceAsStream(String path):以流的形式返回一个文件
4.获取文件的mime类型 大类型/小类型
String getMimeType(String 文件名称)
web.xml配置:
SContextServlet.java源码:
package com.hjh.servlet;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SContextServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取上下文对象
ServletContext context = getServletContext();
//2.获取全局初始化参数
String encoding = context.getInitParameter("encoding");
System.out.println("encoding:"+encoding);//encoding:utf-8
//3.获取文件真实目录
String contextPath = context.getContextPath();
System.out.println("contextPath:"+contextPath);//contextPath:/Servlet
String realPath = context.getRealPath("/c3p0-config.xml");
System.out.println("realPath:"+realPath);//realPath:D:\tomcat-9.0\webapps\Servlet\c3p0-config.xml
//4.以流的形式返回一个文件
InputStream is = context.getResourceAsStream("/c3p0-config.xml");
System.out.println(is);//null
//5.获取文件的mime类型
String mimeType = context.getMimeType("1.jpg");
System.out.println(mimeType); //image/jpeg
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
获取文件的路径:
通过类加载器获取文件:2.txt 放在classes目录下无论是java项目还是web项目都可以
类.class.getClassLoader().getResource("2.txt").getPath()
web.xml配置
<servlet>
<servlet-name>PathServlet</servlet-name>
<servlet-class>com.hjh.servlet.PathServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PathServlet</servlet-name>
<url-pattern>/path</url-pattern>
</servlet-mapping>
PathServlet.java源码
package com.hjh.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PathServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = PathServlet.class.getClassLoader().getResource("c3p0-config.xml").getPath();
System.out.println(path);///D:/tomcat-9.0/webapps/Servlet/WEB-INF/classes/c3p0-config.xml
String path2 = PathServlet.class.getClassLoader().getResource("/c3p0-config.xml").getPath();
System.out.println(path2);///D:/tomcat-9.0/webapps/Servlet/WEB-INF/classes/c3p0-config.xml
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}