Filter --- 过滤器
1、概述
一个运行在服务端的程序,先于与之相关的servlet和jsp页面执行。对从浏览器向服务器发起的请求进行过滤。
2、生命周期
与服务器共存亡。
3、执行流程
A、服务器启动时候调用过滤器中的无参数的构造函数创建好过滤器。
B、执行过滤器下的init方法,仅执行一次。
C、每次请求目标资源时,如果过滤器和当前的目标资源有关联关系,此时会执行过滤器下的doFilter方法,如果在doFilter方法中执行 chain.doFilter(request, response), 相当于放行,继续访问目标资源. 如果没有 chain.doFilter(request, response),就拦截了本次请求,无法访问目标资源。如果可以访问目标资源,目标资源在完成本次响应后,继续执行过滤器中doFilter代码。以后每次请求目标资源,都会执行doFilter方法。
D、服务器正常关闭,执行过滤器中的destroy方法。
4、过滤器链
如果在某个WEB中需要通过过滤器实现自动登录,全站乱码,非法文字屏蔽,如果将这3个功能都在同一个过滤器实现,不容易维护,代码繁琐。所以可以实现3个过滤器,在3个过滤器中实现不同的功能,此时这3个过滤器组成过滤器链。
过滤器链上过滤器执行的先后顺序取决于每个过滤器在WEB.XML中配置先后顺序。
5、Filter配置
1个Filter对应2对标签
filter(filter-name,filter-class) filter-mapping(filter-name,url-pattern)
保持2个filter-name一致
保证filter-class代表的filter全路径正确
url-pattern配置(同Servlet完全一致)
#_目录匹配
/aaa/bbb/*
localhost:8080/day14/aaa/bbb/ServletDemo01
localhost:8080/day14/aaa/bbb/demo.html
localhost:8080/day14/aaa/bbb/demo.jsp
localhost:8080/day14/aaa/bbb/demo.png
#_完全路径匹配
/aa/bbFilter
localhost:8080/day14/aaa/bbFilter
#_扩展名匹配.action
*.action
localhost:8080/day14/bb.action
如果只针对某个Servlet过滤,可以利用servlet-name进行配置
6、现实应用
可以解决全站乱码问题,自动登录问题,屏蔽非法文字,响应数据压缩等现实问题。
基础加强
1、注解概述
注解:是让虚拟机识别的,可以让程序具有一定的特殊功能。
JDK中内置的注解
@Override:描述子类重写父类的方法:
JDK1.5版本的时候 该注解只能应用在 类的继承上。
JDK1.6版本的时候 该注解可以应用在 类的实现上。
@SuppressWarnings:压制警告。
自定义注解
定义类 :class
定义接口:interface
定义枚举:enum
定义注解:@interface
注解的属性的类型:
基本数据类型:
String类型:
Class类型:
注解类型:
枚举类型:
以上类型的一维数组:
特殊的属性名称:value
如果使用注解的时候,只出现了value属性,value属性可以省略的。
2、文件上传
核心思想步骤:
把一个文件从客户端读取,写到服务器
前台页面表单中的必要属性:
<form method="post" enctype="multipart/form-data">
<input type="file" name="upload"/>
</form>
文件上传的核心思想:io 读/写的操作
InputStream is---这里的文件的输入流肯定是跟请求request对象有关的流
OutputStream os = new FileOutputStream("服务器端的一个路径")
IO流对接的模板代码:
int len = 0;
byte[] b = new byte[1024];
while((len = is.read(b))!= -1){
os.write(b, 0, len);
}
is.close();
os.close();
文件上传时,必须考虑不同用户上传文件的重名问题和上传文件不能过多的存放在同一个目录里。
解决方案:
(1)、重名问题:可以使用工具产生唯一ID串作为文件在服务器上的别名。再将 用户自己上传的真实文件名与之相对应存入服务器护着数据库中即可。
(2)、同一目录下的文件过多问题:
一个目录下文件过多,导致打开都很慢,更别说是读写操作。
目录分离:
A、按时间分:一个月一个目录,一个星期一个目录,一天一个目录
B、按数量分:一个目录下存5000个文件,创建一个新的目录,再去存放.
C、按用户分:为每个用户创建一个单独目录 存放文件.
D、按目录分离算法分:
使用唯一文件名.hashCode();得到一个代表当前这个文件的int类型值。
int类型占4个字节32位。可以让hashCode值&0xf; 得到一个int值,用这个int值作为一级目录。
再让hashCode右移4位 &0xf ;得到一个新int值,用这个新int值作为二级目录。依次类推。
3、动态代理
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。
比如一项业务要拓展新的服务原本实现服务能力的代码写在了A类中。我们不可以直接去改,应为改源代码有风险一不小心新功能没有实现还连累原本的功能也失灵了。原本写那段代码的人也不在了
没办法弥补老板会砍了你的。这样我们可以用代理解决这个问题。
A类有一个方法B类继承自A类不仅可以继承A类原有的方法还可以加入新的方法。这样我们通过多态的形式 A a=new B();用A来创建一个B类的对象这样我们调动a的方法时实际上调动的是B类的方法。
这样我们就可以不用修改A类的源代码也可以实现新功能。这样即便是新功能添加失败,还可以使用老功能。 比如玩英雄联盟嫌自己玩太累就下载了一个脚本。但是那个脚本只能放Q技能,所以我很不满意就想加强它的功能让他自动选取敌方英雄打出一套 Q W E R D F 大连招一套秒了他。但是又怕改它源代码自己技术不到家连Q技能都不能自动瞄准了,怎么办呢?我们可以用代理来实现。这样即使我们技术不到位写的代码放不出大连招原本的Q功能也不会失效。
代理技术分为静态代理和动态代理。动态代理是一个实现在创建类时在运行时指定的接口列表的类。
在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口。
委托类要求委托类必须实现某个接口。
我们调用Proxy类的newProxyInstance方法来获取一个代理类实例。这个代理类实现了我们指定的接口并且会把方法调用分发到指定的调用处理器(即是中介类)。
UserService proxyService = (UserService) Proxy.newProxyInstance(
TestApp.class.getClassLoader(),
new Class[]{UserService.class},
new MyInvocationHandler(userService));
newProxyInstance()方法的参数: ClassLoader loader:它是类加载器类型,Class[] interfaces:指定newProxyInstance()方法返回的对象要实现哪些接口(即是实现InvocationHandler接口的那个中介类的类名)InvocationHandler h:它是最重要的一个参数,是一个接口!叫做调用处理器,无论你调用代理对象的什么方法,
都是在调用InvocationHandler的invoke()方法!
InvocationHandler中有一个invoke方法invoke(object proxu,method method ,object[] params)
方法的三个参数含义分别如下:
proxu:产生的代理对象
method:正在调用的目标类的方法;
params:正在执行方法的参数。
当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用.invoke方法初步现实时时空的所以我们用代理方式调用委托类的方法时就是空。如果invoke中输出一段话“111”那我们不管调用委托类哪一种方法输出的都是‘111’因为所有方法都变成了对invoke的调用然后我们就可以在中介类中开始增强了。
首先我们要在中介类中加入一个构造方法参数为接口类的对象。这样的话通过多态的发不发誓只要实现了接口类的类的对象的方法都可以被增强了。
然后我们在invoke方法中通过proxu method params这三个参数通过反射来执行方法。我们可以在invoke通过不同的方法名来进行判断对不同的方法进行不同的增强或不增强。
动态代理的用途
动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。所有使用装饰者模式的案例都可以使用动态代理来替换。
在java类加载器中也应用了代理模式,例如我们自己写的Person类,一定是存放到CLASSPATH中,那么一定是由系统类加载器来加载。
当系统类加载器来加载类时,它首先把加载的任务交给扩展类加载去,如果扩展类加载器加载成功了,那么系统类加载器就不会再去加载。这就是代理模式了!
代理模式保证了JDK中的类一定是由引导类加载器加载的!这就不会出现多个版本的类,这也是代理模式的好处。
网上商城
通用 Servlet.
实现原理与步骤:
在前台提交数据时添加一隐藏提交参数。提交的参数为目标Servlet名称和要执行的方法的名称目标Servlet继承自 BaseServlet。所以也就有了BaseServlet的功能,所以会拿到你需要执行的方法的名称通过反射的方式执行这个方法。方法的返回值是一个路径通过返回的路径来跳转或转发到目标路径。
比如你提交一个 name = method value = login.提交到一个名为User 的Servlet 中该类继承自BaseServlet。在User 中拿到你的method的值login通过反射
Method method = clazz.getMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
方法名称methodName =login, HttpServletRequest.class 执行方法需要的参数, HttpServletResponse.class 执行方法需要的参数被执行。login方法的返回值为“/index.jsp”;(index.jsp代表着首页)就会被response.sendRedirect(path);转发或跳转到index页面.
public class BaseServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的uri参数,然后截取获得请求的方法名
String methodName=request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
try {
//通过反射获取方需要执行的方法
Class clazz = this.getClass();
Method method = clazz.getMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
//获取方法执行后所转发或者是重定向的路径//每一个Servlet中的方法执行后,基本上都会有一个返回值,即是跳转的路径
String path = (String)method.invoke(this, request,response);
if(path != null){
if(path.contains(request.getContextPath())){
//如果路径中包含工程名,则使用重定向方法
response.sendRedirect(path);
}else{
//不是重定向,则只能是转发
request.getRequestDispatcher(path).forward(request, response);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
搭建邮箱服务器
我们用的是MailServer这款邮箱服务器软件。配置完成我们的电脑就可以作为邮箱服务器使用了。然后通过Foxmail来登录收发邮件非常简单
不多介绍
购物模块的功能
1.封装实体
建立购物项 (Cartlterm),并且在购物项中有商品对象(product),
数量(count),小计(subtotal);
建立购物车(Cart),购物车的属性,有购物项的集合,还有总计,
用map集合存放购物项的集合列表,是因为要删除购物车项,所以使用Map而不适用List,使用商品的ID作为map的key,购物车项作为map的value;
创建购物项的方法:将购物车项添加到购物车,同时建立从购物车移除购物项的方法和清空购物车的方法。
2. 加入购物车的代码实现
实现流程:
建立一个购物车模块的Servlet,用来实现添加到购物车执行的方法,
并且调用封装的购物车对象Cart的方法,页面跳转跳到购物车的页面。
在商品详情页面点击【加入购物车】:
提交到Servlet:
3. 清空购物车
实现流程: 在购物项中的清空购物车的执行方法中,调用Cart中的clearCArt的方法, 并且最后跳转到购物车的页面中。
在购物车的页面中点击清除购物车的链接:
提交到Servlet:
4.移除购物项
实现流程:在从购物车中移除购物项的方法中,调用Cart中的removeCart的方法,并且最后跳转到购物车页面
在购物车的页面中点击 删除的链接:
添加到Servlet:
5.生成订单的功能:
实现过程:创建表和实体,建立订单项的实体和订单的实体,向订单表和顶单相表插入记录,页面跳转到订单页面。
在购物车的页面中点击提交订单:
提交到Servlet中:
我的订单查询
1.我的订单功能
登录后,用户一点击我的订单,应该可以查询该用户的所有订单,点击链接会提交到servlet中,根据用户的ID查询该用户的所有订单,查询每个订单的时候,每个订单下面的订单项也要显示,所以,查询订单的时候,将订单中的订单项也一起查询。
2.根据订单ID查询订单:
建立根据订单id查询订单的方法,接收oid,根据OID进行查询,页面跳转到order_info.jsp。在订单列表页面上点击【付款】连接,就会提交到Servlet
4.在线支付的方式
方式一:网站直接与银行网银接口对接
优点:免费的,不会影响到你的资金链
缺点:开发人员需要了解各个对接银行的网银接口,网银系统升级,导致代码需要修改
方式二:网站与第三方支付公司对接
有点:开发人员只需要与第三方支付公司对接,不需要了解各个银行的网银接口,网银升级,不需要修改代码
缺点:收费的,会影响到资金链
月营业额在百万一下网站使用
5.在线支付的流程
在线流程支付流程的分析,如何保证数据是安全和有效的;电子签名:申请一个账号的时候,支付公司给你一个密钥和一套加密算法、
从网站向第三方支付公司去提交数据:
*未加密的数据,使用加密算法和密钥堆未加密的数据进行加密,加密后会得到一个hmac码--代表这个人的身份。
提交数据的时候,提交的是未加密数据和hmac码,在第三方支付公司,使用相同的密钥和加密算法对未加密的数据进行加密,得到一个hmac码,比对这两个hmac码的值是否一致,如果一致可以提交,如果不一致不能提交。
Linux
1、 linux的目录结构
“/”代表根目录,根目录下存放了所有文件,没有盘符之分,都存在/目录下
bin目录存放可以执行的二进制文件。root管理员目录。usr 存放共享的系统资源,一般我们将软件安装在这个目录中,所有用户可用。
home 存放用户文件的目录,如创建一个新用户user,则在home目录下创建一个user目录,用户登录时,自动进入/home/user目录。
2、 linux常用命令:
目录切换命令:
cd / 切换到根目录;cd ~ 切换到用户目录,即当前用户刚登录的目录;cd ..切换到上层目录;cd - 切到上一个目录,相当于windows中的后退
列出文件列表:在linux中,以.开头的为隐藏文件或路径,以-开头的为文件,以d开头的是路径(相当于windows中的文件夹)
格式:ls [格式] ls -a 显示所有文件和路径,包括隐藏的文件和路径; ls -l 以更清晰易读的格式显示内容,缩写成ll
创建和删除路径:mkdir创建路径,rmdir移除路径;若要创建多级目录使用mkdir –p 多级路径。
查看文件内容:如果文件内容少,直接使用cat加文件名,将内容显示到窗口;如果内容多,使用more或less加文件名,more使用空格回车查看下文内容,q退出,less使用pageup和pagedown键查看,
tail -f动态显示内容,很实用,ctrl+c结束查看
删除文件:用法:rm [选项]... 文件... -f不询问删除,-r递归删除
cp复制,例:cp a.txt b.txt 将a.txt复制为b.txt文件; cp a.txt ../ 将a.txt文件复制到上一层目录中
mv移动,重命名,如果在同一目录下,更改名字移动,就相当于完成了重命名操作
tar命令常用参数:-c:创建一个新tar文件 -v:显示运行过程的信息 -f:指定文件名 -z:调用gzip压缩命令进行压缩 -t:查看压缩文件的内容 -x:解开tar文件 例:打包tar –cvf xxx.tar ./* 打包并压缩tar –zcvf xxx.tar.gz ./* 解压tar –zcvf xxx.tar.gz ./*
查找符合条件的字符串。用法: grep [选项]... PATTERN [FILE]...
在Linux下一般使用vi编辑器来编辑文件。vi既可以查看文件也可以编辑文件。三种模式:命令行、插入、底行模式。
切换到命令行模式:按Esc键;
切换到插入模式:按 i 、o、a键;
i 在当前位置生前插入
I 在当前行首插入
a 在当前位置后插入
A 在当前行尾插入
o 在当前行之后插入一行
O 在当前行之前插入一行
切换到底行模式:按 :(冒号);更多详细用法,查询文档《Vim命令合集.docx》和《vi使用方法详细介绍.docx》
打开文件:vim file
退出:esc à :q
修改文件:输入i进入插入模式
保存并退出:escà:wq
不保存退出:escà:q!
3中进入插入模式:
i:在当前的光标所在处插入
o:在当前光标所在的行的下一行插入
a:在光标所在的下一个字符插入
管道:linux中一个重要的概念,将上一个命令的结果作为下一个命令的输入,中间使用|连接
Nginx
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。
使用nginx实现负载的均衡,提高服务器性能,如搭建tomcat集群
请求负载过程中会话信息不能丢失.那么需要在多个tomcat中session需要共享.
* 配置Tomcat的session共享可以有三种解决方案:
第一种是以负载均衡服务器本身提供的session共享策略,每种服务期的配置是不一样的并且nginx本身是没有的。
第二种是利用web容器本身的session共享策略来配置共享。针对于weblogic这种方式还是靠普的。但是针对于tomcat这种方式存在很大的缺陷,主要因为是依靠广播方式来实现的session复制,会浪费很多带宽导致整个网络反映缓慢。官网也建议这种方式最好不要超过4台tomcat,具体的内容可参考/webapps/docs/cluster-howto.html里面有详细的说明。下面是具体的配置过程
第三种是Tomcat集群+redis的Session共享配置方法.