目录
概述
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成 动态Web内容。这个过程为:
1,客户端发送请求至服务器端
2,服务器将请求信息发送至 Servlet
3,Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求
4,服务器将响应返回给客户端
Servlet 看起来像是通常的 Java 程序。Servlet 需要导入特定的属于 Java Servlet API 的包。
准备工作
在IDEA里创建一个web工程
File-New-Project-选Java Enterprise并勾选右侧的Web Application-next-输入工程名称-Finish
整理web工程目录结构
修改资源输出位置(.class文件等的存放位置)
修改jar包存放位置
配置Tomcat服务器
入门案例
思路
第1步:
自定义一个Servlet有三种方式:可以实现一个Servlet接口,或者继承抽象类GenericServlet,或者继承HttpServlet
三者有一些关系: Servlet接口 -> GenericServlet抽象类 -> HttpServlet类
第2步:
在web应用的web.xml文件中配置Servlet程序对外访问的路径
创建Servlet程序
选中src-右键-New-Create New Servlet-输入Servlet类的名字和包名-ok
package cn.tedu.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;
//Servlet核心功能: 接受请求 + 给出响应
@WebServlet("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//打印一句话 --- 在idea里看
System.out.println("欢迎来到Servlet的世界~");
//给浏览器做出响应 --- 在浏览器里看
response.getWriter().write("hello servlet!!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//你要写的代码和doPost()一样,直接调用上面方法就行啦
doPost(request,response);
}
}
访问Servlet
http://localhost:8080/cgb2109javaweb_war_exploded/ServletDemo1
注解方式开发Servlet程序
–1,创建新的web工程,创建Servlet
package cn.tedu.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;
//1,这是新版本的Servlet提供的注解开发方式,更好更简单(否则自己写配置文件)
//参数是,规定了浏览器的地址栏到底怎么写才能访问到我这个Servlet类
//2,ServletDemo1是子类,可以使用父类的所有资源(除了私有的,构造方法)
//3,自定义Servlet的规则:
//方式1:extends HttpServlet--推荐!!!
//方式2:extends GenericServlet--了解
//方式3:implements Servlet--了解
@WebServlet("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
//4,继承了父类,但是 想改父类原有的功能时 就重写!!
//5,不论调用doPost()或者doGet(),都是由Servlet来调用的
//6,当用户用post方式提交请求时(form表单提交),Servlet来调用doPost()
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("您访问了doPost()");
}
//7,当用户用get方式提交请求时,Servlet来调用doGet()
//(在地址栏?拼接数据 + form没改method的值)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("您访问了doGet()");
}
}
–2,测试Servlet
启动服务器,访问浏览器
http://localhost:8080/cgb2109javaweb03_war_exploded/ServletDemo1
本机 Tomcat默认的端口号 项目名称 项目中的资源名称
配置方式开发Servlet程序
–1,创建Servlet类
package cn.tedu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//使用配置方式开发Servlet程序
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost()成功的被Servlet调用!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet()成功的被Servlet调用!");
}
}
–2,配置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">
<!--配置Servlet类的访问信息-->
<servlet>
<!--给Servlet设置一个名字(一般是和类名相同)
细则:名字可以自定义,但是必须唯一,
不能和别的<servlet>的<servlet-name>相同
-->
<servlet-name>hello</servlet-name>
<!--指定Servlet类的全路径(包名.类名)-->
<servlet-class>cn.tedu.servlet.ServletDemo2</servlet-class>
</servlet>
<!--指定浏览器的访问规则-->
<servlet-mapping>
<!--即将根据指定的名字,去找到一个要被访问的Servlet类的全路径-->
<servlet-name>hello</servlet-name>
<!--指定了浏览器的访问方式,
细则:值可以自定义,但是浏览器必须是一样的写法才能访问Servlet
否则404:找不到你要访问的资源
-->
<!--url-pattern的值不能和其他的url-pattern的值相同-->
<url-pattern>/a/b/c</url-pattern>
</servlet-mapping>
</web-app>
–3,测试
http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo2
–4,总结
前后端整合
–1,创建前端HTML网页
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端 安排起来</title>
</head>
<body>
<!-- 点击超链接跳转到Servlet -->
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo3">点我,访问Servlet</a>
</body>
</html>
–2,创建后端Servlet程序
package cn.tedu.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;
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost()");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet()");
}
}
–3,配置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">
<!--配置方式开发Servlet程序-->
<!--配置Servlet类的访问信息-->
<servlet>
<!--给Servlet设置一个名字(一般是和类名相同)
细则:名字可以自定义,但是必须唯一,
不能和别的<servlet>的<servlet-name>相同
-->
<servlet-name>hello</servlet-name>
<!--指定Servlet类的全路径(包名.类名)-->
<servlet-class>cn.tedu.servlet.ServletDemo2</servlet-class>
</servlet>
<!--指定浏览器的访问规则-->
<servlet-mapping>
<!--即将根据指定的名字,去找到一个要被访问的Servlet类的全路径-->
<servlet-name>hello</servlet-name>
<!--指定了浏览器的访问方式,
细则:值可以自定义,但是浏览器必须是一样的写法才能访问Servlet
否则404:找不到你要访问的资源
-->
<url-pattern>/a/b/c</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>cn.tedu.servlet.ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<!--url-pattern的值不能和其他的url-pattern的值相同-->
<url-pattern>/ServletDemo3</url-pattern>
</servlet-mapping>
</web-app>
–4,测试
Servlet的继承结构
Servlet的生命周期
–1,概述
分为三大阶段
初始化 – 由Servlet主动调用init()
提供服务 – 由Servlet主动调用service()/doGet()/doPost()
销毁 – 由Servlet主动调用destroy()
–2,测试
package cn.tedu.lifecycle;
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;
//1,Servlet程序的注解开发方式,代替了web.xml文件中的8行配置代码
@WebServlet("/ServletDemo4")//注解的参数是指浏览器的访问方式
public class ServletDemo4 extends HttpServlet {
//2,Servlet的生命周期中会被调用的方法有:
//init() service()/doGet/doPost destroy()
//3,因为GenericServlet提供的以上方法中都是空实现,
// 重写这些方法并添加方法体来感受初始化的不同阶段
//4,重写的要求:有足够的权限 + 方法声明必须和父类一样
@Override
//当第一次访问Servlet程序时,Servlet自己调用init(),只会调用一次
public void init() throws ServletException {
System.out.println("init()被调用了,Servlet已被初始化!");
}
@Override
//每次访问Servlet程序时,Servlet自己调用service(),会调用多次
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("service()开始为您服务啦!");
}
@Override
//正常的关闭服务器时,Servlet自己调用destroy(),只会调用一次
public void destroy() {
System.out.println("destroy()被调用了,Servlet即将被销毁!");
}
}
创建前端网页
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端 安排起来</title>
</head>
<body>
<!-- 点击超链接跳转到Servlet -->
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo3">点我,访问ServletDemo3</a>
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo4">点我,访问ServletDemo4</a>
</body>
</html>
测试
Request
–1,概述
是指 从前端浏览器 到 后端的Servlet程序 的访问过程,叫请求的过程
可以使用Servlet提供的Request对象,来解析请求中的请求参数
–2,常用方法
getParamter()--按照参数名获取参数值,但是只得到一个值
getParamterValues()--按照参数名获取参数值,但是得到多个值,存入数组
setCharacterEncoding()--如果请求参数中有中文,设置字符集为utf-8
setAttribute()--设置属性
getAttribute()--获取属性
–3,测试
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前端提交数据,后端解析数据</title>
</head>
<body>
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo5?name=jerry&pwd=123">点我,提交get数据1</a>
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo5?hobby=篮球&hobby=足球">点我,提交get数据2</a>
</body>
</html>
创建Servlet程序,解析请求参数
//设置服务器端的编码
request.setCharacterEncoding("utf-8");//写入乱码解决
response.setContentType("text/html;charset=utf-8");//读出乱码解决
package cn.tedu.request;
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.util.Arrays;
@WebServlet("/ServletDemo5")
public class ServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//当用户以get方式提交数据时,Servlet会自动调用doGet()
//get方式提交的数据,可以一个一个的解析getParameter()
//也可以解析多个值getParameterValues()
//如果使用的是Tomcat7.0以上的版本,get方式提交中文数据不会乱码
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//1,request解析请求参数 name=jerry&pwd=123
//1.1,获取一个值
String s = request.getParameter("name");
System.out.println(s);//获取name参数的值
String pwd = request.getParameter("pwd");
System.out.println(pwd);//获取pwd参数的值
//1.2,获取到多个值
String[] hobbies = request.getParameterValues("hobby");
System.out.println( Arrays.toString(hobbies) );
}
}
表单提交数据
–1,创建HTML网页文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo6">
<h3>测试 get提交数据</h3>
姓名:<input type="text" placeholder="请输入姓名..." name="user"/> <br />
密码:<input type="password" placeholder="请输入密码..." name="pwd"/> <br />
<input type="submit" value="提交"/>
</form>
<form method="post"
action="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo6">
<h3>测试 post提交数据</h3>
姓名:<input type="text" placeholder="请输入姓名..." name="user"/> <br />
密码:<input type="password" placeholder="请输入密码..." name="pwd"/> <br />
<input type="submit" value="提交"/>
</form>
</body>
</html>
–2,创建Servlet程序
package cn.tedu.request;
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("/ServletDemo6")
public class ServletDemo6 extends HttpServlet {
//TODO 处理post方式提交的数据--可能出现中文乱码!!
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
//ServletDemo6?user=jack&pwd=123
//处理get方式提交的数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String user = request.getParameter("user");//获取user的值
String pwd = request.getParameter("pwd");//获取pwd的值
System.out.println(user+pwd);
}
}
综合案例
–1,需求
综合案例:
1,准备前端HTML网页,让用户输入部门数据(编号,名称,地址)
2,准备DeptServlet,接受请求,并且解析请求参数
3,把解析成功的请求参数,进行入库
3.1,准备jar包
3.2,准备dept表(deptno,dname,loc)
3.3,准备jdbc代码,进行insert的SQL语句操作
–2,创建HTML网页
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端大融合</title>
<style>
input[type='text']{
width: 200px;/* 宽度*/
height: 30px;/* 高度 */
background-color: pink;/* 背景色 */
border-color: pink;/* 边框色 */
border-radius: 10px;/* 圆角边框 */
}
input[type="submit"]{
width: 80px;/* 宽度*/
height: 40px;/* 高度 */
background-color: gray;/* 背景色 */
border-color: gray;/* 边框色 */
color: white;/* 文字的颜色 */
font-size: 20px;/* 字号大小 */
}
</style>
</head>
<body>
<form method="post" action="http://localhost:8090/cgb2109javaweb03_war_exploded/DeptServlet">
<h1>添加部门数据</h1>
<h3>编号:<input type="text" name="deptno"/></h3>
<h3>名称:<input type="text" name="dname"/></h3>
<h3>地址:<input type="text" name="loc"/></h3>
<input type="submit" value="保存" />
</form>
</body>
</html>
–3,创建DeptServlet类
package cn.tedu.dept;
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.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@WebServlet("/DeptServlet")
public class DeptServlet extends HttpServlet {
//用户以post方式提交的数据,doPost()解析请求参数
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try{
//防止中文乱码
request.setCharacterEncoding("utf-8");
//用来获取网页中传递来的参数,
//getParameter()的参数是网页中name属性的值
String a = request.getParameter("deptno");
String b = request.getParameter("dname");
String c = request.getParameter("loc");
//TODO jdbc--把解析到的参数入库,,insert
//获取驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection con=DriverManager.getConnection(url,"root","root");
//获取传输器Statement不安全低效,PreparedStatement安全防止了SQL攻击高效
String sql="insert into dept values(?,?,?)";//sql骨架,?是占位符
PreparedStatement p = con.prepareStatement(sql);
//设置SQL的参数,执行SQL
p.setObject(1,a);
p.setObject(2,b);
p.setObject(3,c);
p.executeUpdate();
//关闭资源
p.close();
con.close();
}catch (Exception e){
System.out.println("插入失败,请检查数据~");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post提交的,不能写在这里,
}
}
–4,总结
请求转发
–1,概述
作用是想让AServlet调用BServlet的功能.
过程: 浏览器访问AServlet ,但是AServlet偷偷调用了BServlet ,此时浏览器的地址栏没变
全程只是一次请求
实现:request.getRequsetDispather(访问BServlet的方式).forward(request,response)
–2,测试
AServlet
package cn.tedu.forwardtest;
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("/AServlet")
public class AServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("AServlet被执行!");
//实现请求转发:想让AServlet调用BServlet,本质上这是服务器的动作,浏览器没变化发现不了
//要求:两个资源可以互相调用,但是要求两个资源必须在同一项目中
//getRequestDispatcher()的参数是,对方的访问方式
//请求转发本质上就是一次请求:在AServlet添加请求的数据,试试BServlet也能获取到就可以了
request.setAttribute("name","rose");
request.getRequestDispatcher("/BServlet").forward(request,response);
}
}
BServlet
package cn.tedu.forwardtest;
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("/BServlet")
public class BServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("BServlet被执行!");
//获取在AServlet中存入的数据,其实就是根据key获取value
Object data = request.getAttribute("name");
System.out.println(data);
}
}
–3,总结
直接访问AServlet,背后的BServlet也会被执行,并且浏览器没变化.
五,响应Response
–1,概述
是指 从java程序组织好的数据 发送给 前端浏览器 的过程,叫响应
常用方法
getwriter()---给浏览器响应数据
setContentType()---用来解决防止响应时的中文乱码
senRedirect()--重定向
–2,测试
package cn.tedu.response;
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("/ResponseServlet")
public class ResponseServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//3,如果想要响应中文,防止中文乱码
response.setContentType("text/html;charset=utf-8");
//1,获取写出流
PrintWriter out = response.getWriter();
//2,正式写出数据--写到浏览器
out.write("hello servlet1~~~");
out.write("hello servlet2~~~");
out.write("hello servlet3~~~");
out.write("你好servlet~~~");//中文乱码啦~
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
优化MyRequest类
package cn.tedu;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
//模拟Servlet解析请求参数的对象Request
public class MyRequest {
public static void main(String[] args) {
//this是代表的本类对象,static里不能出现this,原因就是加载顺序
// this.getParamter();
MyRequest my = new MyRequest();
//查询指定参数名对应的值
String u = my.getParamter("pwd");
System.out.println(u);
}
//1,getParamter()获取每个请求参数
public String getParamter(String keyword){
String url="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo6" +
"?user=jack&pwd=123" ;
String[] data = url.split("\\?")[1].split("&");
//Map存数据有特性,数据必须以键值对的形式存在,可以根据key找value
Map<String,String> map = new HashMap<>();//{pwd=123, user=jack}
// 4,遍历数组,获取每个数据
for(String s : data){//遍历两次,第一次s是user=jack,第二次s是pwd=123
// 5,按照=切割,得到数组 [user,jack],只要第二个元素
String[] ss = s.split("=");
String value = ss[1];
String key = ss[0];
map.put(key,value);//存入map
}
return map.get(keyword);//去map里找key对应的value,{pwd=123, user=jack}
}
}
重定向
–1,概述
特点:
1, 整个过程有 两个请求 两个响应
2, 地址栏会发生改变
使用: response.sendRedirect(对方的访问方式)
此时,你想访问哪个程序都可以
–2,测试
ServletA
package cn.tedu.redirect;
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("/ServletA")
public class ServletA extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//面试题:重定向和请求转发的区别???
//1,请求转发是请求request的功能,全程1次请求1次响应,地址栏不变
//request.getRequestDispather("目标访问的方式").forward(请求,响应)
//2,重定向是response的功能,全程2次请求2次响应,地址栏改变
//response.sendRedirect("目标访问的方式")
response.sendRedirect("https://www.baidu.com/");
}
}
ServletB
package cn.tedu.redirect;
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("/ServletB")
public class ServletB extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}