Servlet day01
1 Servlet引言
Servlet是JavaWeb应用中最核心的组件,本质上就是运行在服务器(Tomcat)中一小段Java代码。用于接收用户的请求,并负责响应动态的结果页面。Servlet技术是JavaEE规范的重要组成。
1.1 为什么要学Servlet
在之前,我们已经学习了如何在tomcat中部署静态的web应用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aIlVQScr-1631153002355)(Servlet day01.assets/image-20210517130342805.png)]
静态Web应用存在的问题:静态网站只能显示固定效果,无论何人何时何地访问,显示效果不会有变化。通常大多数的Web应用是需要显示动态的效果(不同的人、不同的时刻访问看到不同的效果),比如:天气预报网站、新闻门户网站…。
解决方案:使用Servlet生成动态页面。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-voh9ZBbl-1631153002357)(Servlet day01.assets/image-20210517131752330.png)]
Servlet的生成动态网页的原理:
Servlet本质上仍是Java代码,在Servlet可以通过字符串拼接的方式动态的构造html源码。当请求到达Servlet后,执行动态拼接,最终响应回的就是内容变化的HTML。
1.2 JavaWeb应用的项目结构
JavaWeb应用既包含静态资源(HTML、CSS、JavaScript、图片…),又包含动态资源(Servlet、JSP)。JavaWeb应用在组织这些组成时,有一套固定的项目结构,特别是动态资源的结构是固定不变的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GMv16Bet-1631153002359)(Servlet day01.assets/image-20210517132119834.png)]
+项目名 //静态资源部分 -login.html -register.html +css -style.css +images -xxx.jpg -yyy.jpg ... //动态资源 +WEB-INF -web.xml //配置web项目 +lib //项目依赖的jar包,比如mysql-connector-java.jar +classes //存放带包结构的class文件
我们部署到Tomcat的JavaWeb应用,一定要满足这个项目结构要求。
2 第1个Servlet程序
动态效果的需求:显示系统时间
2.1 Servlet的开发步骤
Servlet的开发步骤大体分为2步:编码Servlet类+配置Servlet的访问路径
-
编码(Servlet类)
编码Servlet类按照要求必修要实现Servlet接口,下面我们先简单的介绍Servlet体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90ZTL3Sc-1631153002364)(Servlet day01.assets/20181022191005145.jpg)]
编码Servlet类,有3种方式:
- 直接实现Servlet接口
- 继承GenericServlet
- 继承HttpServlet(常规做法)
class FirstServlet extends HttpServlet{ //重写service方法 //对外服务的方法 public void service(HttpServletRequest req,HttpServletResponse resp) throws IOException,ServletException{ //生成动态网页的代码 } }
-
配置(web.xml )
编码Servlet类后要配置其对外访问路径,这要在web.xml中通过标签配置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4uYLkBw0-1631153002366)(Servlet day01.assets/image-20210517180518380.png)]
web.xml <servlet> <servlet-name>Servlet起个名,保证唯一即可</servlet-name> <servlet-class>Servlet类全类名</servlet-class> </servlet> <servlet-mapping> <servlet-name>和上面的servlet-name值对应</servlet-name> <url-pattern>以/开头</url-pattern> </servlet-mapping>
2.2 实战
环境准备:新建web项目
先创建一个普通java项目,然后右键–>Add Framework Support–>Web Application
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJTBi3Xi-1631153002368)(Servlet day01.assets/image-20210519211751579.png)]
实战编码:
-
编码
注意:WEB-INF中新建lib目录,并从tomcat/lib目录里复制servlet-api.jar到WEB-INF/lib里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u4gQaSjq-1631153002369)(Servlet day01.assets/image-20210519214132789.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5o3MjXo-1631153002370)(Servlet day01.assets/image-20210519214145373.png)]
public class FirstServlet extends HttpServlet { /* * req: 表示请求 从该对象中获取到用户传输的数据 * resp:表示响应 通过该对象可以向浏览器发送数据 */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //生成系统时间 Date date = new Date(); String content ="<html><head><meta charset=\"utf-8\"/></head><body>"+date+"</body></html>"; //设置响应类型,帮助浏览器正确解析响应结果 resp.setContentType("text/html"); //设置内容编码方式 resp.setCharacterEncoding("utf-8"); PrintWriter pw = resp.getWriter(); pw.println(content); pw.flush();//tomcat会自动关闭流 ,无须手动关闭,但注意一定要刷新输出流 } }
-
配置(web.xml)
web.xml <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>com.baizhi.servlet.FirstServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/first</url-pattern> </servlet-mapping>
-
部署项目
- Idea中关联tomcat
- 部署项目到tomcat
操作图示:
Idea中关联tomcat
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y8PbkiP9-1631153002371)(Servlet day01.assets/image-20210519215446757.png)]
部署项目到tomcat:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exxlbmAt-1631153002372)(Servlet day01.assets/image-20210519220051058.png)]
-
访问测试:http://localhost:8989/项目名/url-pattern
3 Servlet的注解开发
在web.xml中配置Servlet的url-pattern的方式,开发繁琐且容易出错。在JavaEE6后,推出了简化的配置方式:注解配置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zlguygm4-1631153002374)(Servlet day01.assets/image-20210519222012674.png)]
只需要在Servlet类上方添加@WebServlet注解,即可配置Servlet的url-pattern。
//@WebServlet(name="FirstServlet",urlPatterns="/first")
//简写形式
@WebServlet("/first")
public class FirstServlet extends HttpServlet{
...
}
使用注意事项:
- Tomcat版本必须>=7.0
- 注解方式和xml方式可以同时存在,但注意url-pattern值不能重复
4 Servlet收参
Servlet收参:在Servlet中收集随着请求发送来的数据。
用户在使用Web应用的一些功能时,需要在请求中发送数据。比如:登录时需要发送用户名密码
4.1 Servlet收参的语法
Servlet收参需要解决2方面的问题:
- client如何在请求中发送数据?
- Servlet中如何获取请求中的参数?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gk4BrqdT-1631153002375)(Servlet day01.assets/image-20210520130905172.png)]
4.1.1 Client发送请求的3种方式
-
通过form表单
<!-- 1. 通过表单 发送数据 --> <form action="/servlet-day01/parameter"> 用户名: <input type="text" name="username" > <br> 密码: <input type="password" name="password" id=""> <br> <input type="submit" value="提交"> </form>
请求参数格式为k=v格式(name属性名=参数值),比如:username=xushy&password=123456,也就是说input标签必须有name属性。
form的type属性决定了数据的提交方法,type有2个值:GET和POST。
- get方式:k=v格式拼接在地址后面
- post方式:k=v格式在请求体中传输
-
通过超链接
<!--2. 超链接拼接发送数据 本质就是模仿表单提交数据--> <a href="/servlet-day01/parameter?username=xushy&password=123456">通过超链接发送数据</a>
超链接就是模拟表单的GET方式提交数据。
-
地址栏直接输入地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4LC46JHO-1631153002376)(Servlet day01.assets/image-20210520142350975.png)]
地址栏直接输入地址也是在模拟表单的GET方式提交数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-joQ3dU7F-1631153002377)(Servlet day01.assets/1622188676331.png)]
4.1.2 Servlet中如何收参
Servlet中通过request.getParameter(“参数名”)获取数据。
@WebServlet("/parameter")
public class ParameterServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//请求参数k=v格式:username=xushy&password=123456
//req.getParameter("参数名")获取参数值
String username = req.getParameter("username");
System.out.println("username = " + username);
String password = req.getParameter("password");
System.out.println("password = " + password);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ts71P6cG-1631153002378)(Servlet day01.assets/image-20210520212742855.png)]
注意:
http://localhost:8989/servlet-day01/parameter?username=&password=
这种情况,Servlet中收到的是空串,而不是null
http://localhost:8989/servlet-day01/parameter?username=
这种情况,Servlet中username是空串,password是null
4.2 Servlet收参典型的案例
Servlet收参典型的案例是登录和注册。
4.2.1 登录案例
最典型的案例就是登录,下面我们来分析并演示下登录案例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A6HWTEeY-1631153002379)(Servlet day01.assets/image-20210520213453511.png)]
-
login.html
<html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form action="/servlet-day01/login"> 用户名:<input type="text" name="username"/><br/> 密码:<input type="password" name="pwd"/><br/> <input type="submit"/> </form> </body> </html>
-
LoginServlet
@WebServlet("/login") public class LoginServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1 收参 String name = req.getParameter("username"); String pwd = req.getParameter("pwd"); //2 比对 //3响应结果 //设置内容响应类型 resp.setContentType("text/html"); //设置内容编码方式 resp.setCharacterEncoding("utf-8"); PrintWriter pw = resp.getWriter(); pw.print("<html><head><meta charset='utf-8'/></head><body>"); /* if("xushy".equals(name) && "123456".equals(pwd)) { pw.print("登录成功"); }else { pw.print("登录失败"); } */ UserService userService = new UserServiceImpl(); if(userService.login(name,pwd)) { pw.print("登录成功"); }else { pw.print("登录失败"); } pw.print("</body></html>"); pw.flush(); } }
4.2.2 注册案例
下面我们来分析下注册案例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SqudSafI-1631153002380)(Servlet day01.assets/image-20210520220341367.png)]
-
register.html
<form action="/servlet-day01/register"> 用户名: <input type="text" name="username" id=""> <br> 密码: <input type="password" name="pwd1" id=""><br> 确认密码: <input type="password" name="pwd2" id=""> <br> <input type="submit" value="注册"> </form>
-
RegisterServlet
@WebServlet("/register") public class RegisterServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String pwd1 = req.getParameter("pwd1"); String pwd2 = req.getParameter("pwd2"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html"); PrintWriter pw = resp.getWriter(); pw.print("<html><head><meta charset='utf-8'/></head><body>"); if (pwd1.equals(pwd2)) { UserService userService = new UserServiceImpl(); userService.register(username,pwd1); pw.print("注册成功,<a href='/servlet-day01/login.html'>请登录</a>"); }else { pw.print("注册失败,<a href='/servlet-day01/register.html'>请重新注册</a>"); } pw.print("</body></html>"); pw.flush(); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmKuci3H-1631153002381)(Servlet day01.assets/1622193146003.png)]
5 Servlet收参的乱码问题
Servlet收参时有一个典型的问题:收参乱码。简单说,通过浏览器发送中文字符,Servlet收取到的是乱码的字符。
5.1 收参乱码案例演示
-
encoding.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>收参乱码演示</title> </head> <body> <!-- 先演示method="get" 再演示method="post" --> <form action="/servlet-day01/encoding" method="post"> data: <input type="text" name="data" id=""> <br> <input type="submit" value="发送"> </form> </body> </html>
-
EncodingServlet.java
@WebServlet("/encoding") public class EncodingServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String data = req.getParameter("data"); System.out.println("data = " + data); } }
通过实验,可以发现method为get时不乱码,method为post时乱码。
5.2 乱码成因及解决方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rKWoKWOT-1631153002382)(Servlet day01.assets/image-20210523095710300.png)]
字符乱码的原因:编码和解码时使用的字符编解码集不一致!!!
收参乱码的解决方案:保证Servlet中解码方式和浏览器中发送数据的编码方式一致。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmGUBed7-1631153002383)(Servlet day01.assets/image-20200904221712974.png)]
-
浏览器中设置编码方式
html页面中<meta charset="utf-8"/>设置编码方式
-
服务端设置解码方式
-
get方式(当前环境下不再需要重点关注)
低版本tomcat需要修改conf/server.xml,添加URIEncoding=utf-8。
<Connector URIEncoding="utf-8" connectionTimeout="20000" maxThreads="2000" port="8989" protocol="HTTP/1.1" redirectPort="8443"/> 在上面标签中,添加URIEncoding="utf-8"
注意:从tomcat8.0开始,get默认是utf-8,不需要配置
-
post方式(必须通过编码的方式进行设置)
//注意:这行代码必须在getParameter调用前执行 req.setCharacterEncoding("utf-8");
-
6 Servlet整合JDBC
JavaEE应用通常要分为3层:视图层+业务层+数据访问层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R9ZjdYaP-1631153002383)(Servlet day01.assets/image-20210523105514780.png)]
由于视图技术的变化,需要使用Servlet衔接视图层和业务层。日后开发应用功能时,整个开发过程分成2个阶段
- 分析阶段:自顶向下,视图层–>业务层–>数据访问层
- 编码阶段:自底向上,数据访问层–>业务层–>视图层
案例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ZnzwCjw-1631153002385)(Servlet day01.assets/image-20210523111414630.png)]
7 Servlet调错
学习完Servlet后,JavaWeb原始技术体系就学习完毕了。引入新的技术,就有新的异常,下面是Servlet中常见的异常。
7.1 404 Not Found
原因:找不到资源
- 可能是路径写错了
- web.xml配错了
- tomcat加载项目时已经错了
调错步骤:
- 启动tomcat后,先看控制台有无异常
- 看路径是否正确
- web.xml是否配置有问题
7.2 500 服务器内部异常
原因:服务器tomcat在运行程序时出现异常
- Servlet代码逻辑有问题
- web.xml配置问题
- tomcat启动时加载项目出了问题
调错步骤:
- 启动tomcat后,先看控制台有无异常
- 查看web.xml配置是否有问题
- 看代码逻辑,添加打印语句
7.3 405
原因:service方法重写有问题
调错步骤:查看servlet中service方法,看方法名、形参类型有没有错
7.4 提示下载
原因:resp.setContentType(“响应类型”);响应类型写错了。
说明:404异常比较常见但是容易掌握解决方案,405不常见解决方案固定。最常见且成因最多的是500,各种原因都会造成500,当发生500的时候要按照我们讲解的挑错步骤一步步排除错误。
- 可能是路径写错了
- web.xml配错了
- tomcat加载项目时已经错了
调错步骤:
- 启动tomcat后,先看控制台有无异常
- 看路径是否正确
- web.xml是否配置有问题
7.2 500 服务器内部异常
原因:服务器tomcat在运行程序时出现异常
- Servlet代码逻辑有问题
- web.xml配置问题
- tomcat启动时加载项目出了问题
调错步骤:
- 启动tomcat后,先看控制台有无异常
- 查看web.xml配置是否有问题
- 看代码逻辑,添加打印语句
7.3 405
原因:service方法重写有问题
调错步骤:查看servlet中service方法,看方法名、形参类型有没有错
7.4 提示下载
原因:resp.setContentType(“响应类型”);响应类型写错了。
说明:404异常比较常见但是容易掌握解决方案,405不常见解决方案固定。最常见且成因最多的是500,各种原因都会造成500,当发生500的时候要按照我们讲解的挑错步骤一步步排除错误。