这里主要是自己大二的学校课程下的上机任务[中]!
笔者能力有限,有很多不足的地方望指正!
2022年4月20日08:33:54
<pre>
自行完成相应的动作和思考
0.读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
本项目模拟一个购物车的业务
1 javabean的规范
2 javabean作为数据封装用
3 javabean作为业务逻辑组件用
4 servlet作为业务控制器用
5 servlet直接向客户端输出HTML页面和数据结果
6 html和jsp都没有,没有页面,但我们也看到了输出的网页界面,思考jsp的本质,用servlet也可以输出页面
7 errors:易踩到的坑:绝对路径与相对路径
在页面内部的HTML中的连接地址,只能认为是客户端的
在servlet内部的转发地址,肯定是在服务端的
客户端的根在站点
服务端的根在应用程序
而:一个站点可以有多个web应用程序
8 please首先请求showProduct控制器,验证和思考业务本身
pre>
正常的运用到了javabean,对商品对象进行了封装, 全war包没有前端静态资源, 但是也实现了前端的页面效果:
通过:PrintWriter out=response.getWriter();
写html等到浏览器:
out.println("");
out.println("ShowCartServlet ");
out.println("");
out.println("你目前没有购买任何商品
");
out.println("");
out.println("");
商家对象只有唯一, 卖家可以有很多, 分别对应服务器和客户端的关系:
所以将商家提供的资源products存进context上下文中, 保证为全局变量, 所有人共享, 买一份少一份!
本app还用到了一个对products对象操作的封装, 将商品数量增、减、显示
封装到了一个业务组件中shopcart
如果加入数据库, 则
public void init() throws ServletException{
// 用HashMap来做商店,初始化各种商品,供所有用户来购买
// 初始时,商品库存数量均为100个
products=new HashMap();
products.put("001",new Product("001","海信电视机","58英寸,LED液晶显示,安卓操作系统,2014年上市",6999.00,100));
products.put("002",new Product("002","海尔洗衣机","洗涤容量6Kg,滚筒式,LED显示屏,内筒材料为不锈钢",3999.00,100));
products.put("003",new Product("003","格力空调","三级变频,壁式挂机,超静音,超长质保,强力除湿",3269.00,100));
products.put("004",new Product("004","海尔热水器","横式,专利金刚三层胆,专利金刚三层胆,60L",2780.00,100));
products.put("005",new Product("005","西门子冰箱","三门冰箱,电脑控温,总容积为231-280L,能效等级为一级",5780.00,100));
ServletContext context=getServletContext();
// 商店置于APP全局中,所有人共享可用,买走1份少1份
context.setAttribute("products",products);
}
这段表示数据库中商品的初始化部分!,如果要对数据库中的products进行操作的话则需要用到类似jdbc, mybatis,jpa,等技术
<pre>
自行完成相应的动作和思考
0.读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
进行一个最简单的用户登录的模拟
1 界面如何组织参数输入
2 参数如何传到服务器上进行相应的处理
3 一个servlet从接请求到给响应要做些什么事情?
4自己要慢慢熟悉在前端用html里的form的方式向后台提交数据,提交请求
pre>
实验大致流程:
访问:
http://localhost:8080/09/login.html
打开f12可以知道, 有发出请求:
请求 URL: http://localhost:8080/09/login?username=%E5%85%B4%E8%B6%A3%E4%BD%BF%E7%84%B6%E7%9A%84%E5%B0%8F%E5%B0%8F&password=nihao
//中文会出现百分号形式的编码
<pre>
自行完成相应的动作和思考
0.读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
01 最简单的示例,用eclipse生成servlet
02 再生成一个servlet
03 第三个servlet
04 第四个servlet
05 第五个servlet
06 MyServletDefault默认的servlet
07 自定义出错信息【出错页统一规划】
不看注解 ,看web.xml文件的配置
</pre>
</body>
这个war主要分析一下web.xml就行:
<servlet-mapping>
<servlet-name>Servlet01servlet-name>
<url-pattern>/abc/*url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>Servlet02servlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>Servlet03servlet-name>
<url-pattern>/abcurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>Servlet04servlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>Servlet05servlet-name>
<url-pattern>*.actionurl-pattern>
servlet-mapping>
<welcome-file-list>
<welcome-file>index.htmlwelcome-file>
<welcome-file>index.htmwelcome-file>
<welcome-file>index.jspwelcome-file>
<welcome-file>default.htmlwelcome-file>
<welcome-file>default.htmwelcome-file>
<welcome-file>default.jspwelcome-file>
welcome-file-list>
根据web.xml文件中的
标签中的路径要求,来指向不同的servlet,
值得注意的是,这里面,
需要吧/*
这个映射注释掉,才能访问*.do``*.action
<pre>
自行完成相应的动作和思考
00 读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
01 注意包名的设计和使用
02 注意非同包的类的引入
03 能不能自己设计一个界面,让用户登录更美观一些?
04 用户名和密码能不能用get方式发起请求来传参?
05 传一个数组,该怎么组织数据呢?
06 字符串匹配检查是用的什么方法?
07 碰到问题,开会脑筋,解决问题,记录问题,小结收获----良好的学习和积累习惯
08 相对路径和绝对路径:网站根目录和应用程序项目的根目录的差别
09 客户端的请求地址和服务器端的转发地址在根路径上的差别
10 最后一个逗号的处理,还有别的方式吗 ParamsServletPlus
11 思考,页面的跳转和servlet组件之间的跳转,有何差别?(略)
12 请求行中有那些行数【键值对】有什么用?
pre>
包名的设计和使用
用户和密码一般不用get方式来发起请求,戳这里
简单来说就是get方式会将密码和账号暴露在浏览器请求地址上
post则会隐藏起来:
这里是从登录url跳转到表单提交的servlet映射上去了,但是都没有暴露我提交的用户名和密码
从源码上面可以看出来:
后端接收数组
// 获取参数名为“hobby”的值
String[] hobbys = request.getParameterValues("hobby");
当有转发的时候:
例如请求Request URL:
http://localhost:8080/11/RequestParamsServlet?username=ladidol&password=&hobby=sing&hobby=dance
后端其实过程就是先请求/RequestParamsServlet
的接收servlet再请求/ParamsServlet
的响应servlet.
去掉最后一个,
的代码:
for (int i = 0; i < hobbis.length; i++) {
sb.append(hobbis[i]+",");
}
// 处理最后一个逗号
str = sb.substring(0, sb.length()-1);
其他常用方法:
for (int i = 0; i < hobbys.length-1; i++) {
out.print(hobbys[i] + ", ");
}
out.print(hobbys[hobbys.length-1]);
请求行:
①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。
②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL。
③是协议名称及版本号。
请求头:
④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。
与缓存相关的规则信息,均包含在header中
请求体:
⑤是报文体,它将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1¶m2=value2”的方式传递请求参数。
略!详情请看第10个war包
那我就在这里补充一下转发和重定向的区别:
转发:
重定向:
<pre>
自行完成相应的动作和思考
0 读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
1 过滤器的配置和Servlet一样,但执行的不是业务功能,而是过滤功能
2 一般情况下,用Filter来过滤Servlet,而Servlet用于控制,那么Filter则用于控制前后的预设和善后处理
3 因此,Filter做有意义的工作,一定是从Servlet对应的url-pattern入手,换句话来描述,就是你要经过这个Servlet处理,得先经过Filter的预处理
pre>
(2条消息) Servlet过滤器_pan_junbiao的博客-CSDN博客_servlet过滤器
在拦截器中:
实现Filter接口
需要实现响应的doFilter
方法(并且持有 FilterChain
参数)
拦截器中:
// 相当于是模拟预设工作
System.out.println("2019001001 这是准备工作.....");
// 放行【如果没有下面的doFilter过程,即为拦截了】,放行后可以到达servlet
chain.doFilter(request, response);
// 相当于是模拟善后工作【servlet工作完后,再回到这里】
System.out.println("2019001001 这是善后工作.....");
servlet:
// 模拟核心业务
System.out.println("2019001001,我的Servlet在工作...");
在web.xml文件中:
<filter>
<filter-name>MyFilter01filter-name>
<filter-class>filter.MyFilter01filter-class>
filter>
<filter-mapping>
<filter-name>MyFilter01filter-name>
<url-pattern>/MyServleturl-pattern>
filter-mapping>
<servlet>
<servlet-name>MyServletservlet-name>
<servlet-class>servlet.MyServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>MyServletservlet-name>
<url-pattern>/MyServleturl-pattern>
servlet-mapping>
可以看出,这个简易的filter, 在配置文件中, 需要配置filter
和filter-mapping
且过滤url和servlet相对应!
<pre>
自行完成相应的动作和思考
0.读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
1 多次过滤的配置
2 不管多少次过滤,最后的核心业务仍然交给Servlet来控制处理
3 多级过滤器,进入顺序和退出顺序 要好好体会,要深入理解
4 就算是做预处理业务,也可以把工作做细,做专一
5 软件工程追求的是单一,模块化,最后才可以复用
---将核心业务与周边业务剥离,才能更好地去关注本身
6 那么,多个过滤器存在时,怎么设置谁先过滤,谁后过滤呢?
7 当过滤器是两边包围时,遵循的是先进后出的原则
8 思考,周边业务【即过滤过程】本身有没有先后顺序
如果:核心业务是约会,之前是先洗漱,再化妆,还是可以先化妆,再洗漱?
如果:核心业务是吃饭,之前是先拿碗,还是先拿筷子?
9 建议改造过滤器和业务处理器,即filter和servlet,
在console输出相应的插旗,来观察两级过滤动作和业务动作的执行过程。
10 注意,在web.xml中filter和servlet的配置很相似
只是约定
在写法上,servlet写法,与filter写法不一样
在使用上,servlet处理业务,filter过滤业务,各司其职
pre>
测试之间要先知道filterChain(过滤链)是干嘛的。
一个过滤器处理完后,会把request和response对象通过filterchain传递给下一个过滤器,如果没有下一个过滤器,则会直接开始执行业务代码,
经过测试,多个filter过滤器是根据filter在web.xml中的配置先后顺序,执行先后顺序
前后顺序对称, filter先开始的后结束,后开始的先结束
然后对filter的详细解释, 老师的实验要求, 就写的十分nice, 资瓷郑老师!
<pre>
自行完成相应的动作和思考
0.读完程序中的文档,即注释,如果有相关问题,则直接回答问题。
1 复习pojo如何封装?
2 复习过滤器如何配置?如何设置通配?
3 复习Servlet控制器如何配置?
4 登录业务一般要做什么?
5 退出业务一般要做什么?
6 cookie是什么,一般用于干什么?它在客户端,但服务器端如何控制它?
自行搜索并学习cookie的原理
7 自动登录的简单原理是什么?
8 过滤器如何完成自动登录的预先处理动作,再转给Servlet控制?
9 第一次就能自动登录吗?
相关技术:
EL表达式
JSTL标签
basePath获取方式
使用绝对路径的建议
保持时间是以秒为单位的
pre>
4 登录业务一般要做什么?
就是判断密码账号是否正确, 有验证码的还要判断验证码登录!
if ("fhzheng".equals(username) && "123546".equals(password)) {
5 退出业务一般要做什么?
这里就是把用户信息从session中移除掉
// 移除session
request.getSession().removeAttribute("user");
// 创建cookie
Cookie cookie = new Cookie("autologin", "msg");
cookie.setPath(request.getContextPath());
// 将cookie置为过期
cookie.setMaxAge(0);
response.addCookie(cookie);
6 cookie是什么,一般用于干什么?它在客户端,但服务器端如何控制它?
自行搜索并学习cookie的原理
详情见我的另一篇博客戳这里
cookies按老师说的, 就是一个键值对集合的数据结构
自动登录逻辑:
先登录一下:
通过浏览器抓包,得到登录后会返回set-Cookie的数据,这里面包含有autologin的键值对
再次访问这个页面的时候
主要是根据AutoLoginFilter
这个将请求中的cookie中的用户信息给拿到,放到session对象中,从而就有了user对象
这样只要有这段cookie在,你就一直能访问这个页面!
- 创建cookie Cookie c =new Cookie(“uname”,“Kitty”);
- response.addCookie©;添加cookie到服务器端。可以使用抓包工具查看到;
- response.addCookie©一旦执行,服务器端会自动发回消息头set-cookie给浏览器,set-cookie是会携带cookie键值对的,uname=kitty。创建的cookie就会保存在浏览器。所以创建的cookie是会保存在浏览器上的
因为笔者能力有限,这些主要是用于自己的笔记!可能有点粗糙!
感谢阅读!
欢迎点赞关注哦!
也欢迎到访我的博客!
同样欢迎友链互加!
小小的博客传送门!