黑马程序员技术交流社区
标题:
web三大组件
[打印本页]
作者:
Itleizhihao
时间:
2019-9-26 15:32
标题:
web三大组件
web的三大组件:
Servlet
编写步骤:
1.写一个类实现Servlet接口
2.重写抽象方法
3.配置
注解配置 @WebServlet
web.xml中配置
<sevlet>
<servelet-name>别名
<servelet-class>群类名
</sevlet>
<servlet-mapping>
<servlet-name>
<url-pattern>
</servlet-mapping>
声明周期:
init() 初始化.只执行一次.
两种方式:
默认是第一次访问的时候执行.
在<servlet-mapping>中<load-on-startup> 如果是负数.就是第一次访问的时候执行
如果是0或者正数.就是服务器启动时执行.
service() 每一次访问都会执行
destroy() 只执行一次. 服务器关闭的时候执行.
Filter
Listener
```
## Filter
```java
生活中的过滤器: 相当于一个比较贪婪的土匪. 海关.
web中的过滤器: 就是去过滤请求和响应.
作用:
1.权键验证.
2.敏感词过滤.字符集的指定.
编写的步骤:
1.写一个类去实现Filter接口
2.重写方法
doFilter
FilterChain的对象去放行.
3.去配置(拦截的路径)
1.注解 @WebFilter
2.web.xml中去配置.
<filter>
<filter-name>别名
<filter-class>群类名
</filter>
<filter-mapping>
<filter-name>
<url-pattern>
</filter-mapping>
注意:
千万不要用注解和web.xml去重复配置一个Filter.否则就会执行两次这个Filter
执行流程:
前提:请求的url匹配上Filter配置的拦截路径.
如果匹配上了.会优先执行Filter中doFilter中的逻辑.
在doFilter方法中.如果FilterChain去放行.就可以访问对应的访问资源.
再去中放行后的逻辑.
生命周期方法:
init() 只执行一次. 并且只能在服务器启动的时候执行.
注意:跟Servlet中就不同了.
Servlet中可以去配置他的执行时机
Servlet就相当一一个开店的.有两个选择开门时间.
1.一大早.就开门.等着客户上门.
2.尽情的睡懒觉. 直到第一个顾客上门.
Filter 就是一个土匪. 必须一大早就拦在路上.等你的拦截对象(只能是服务器启动的时候就执行init方法.)
doFilter() 每次拦截都执行
destroy() 执行一次. 服务器关闭的时候执行.
拦截路径的配置: 跟Servlet的资源路径配置规则一样
1.完全路径匹配 /user/demoServlet
2.目录匹配 /user/*
3.后缀名匹配 *.jsp 注意这里没有斜杆
4.全部匹配 /*
/**/
拦截方式的配置
1.注解中配置 dispacherTypes
request 默认值.从浏览器中直接访问.
forward 转发
2.web.xml中配置
<filter-mapping>
<dispacher>
过滤器链
一次请求的URL匹配上多个Filter.这多个Filter都会执行.就叫做过滤器链.
执行流程: Filter1 Filter2
Filter1放行前的代码
Filter2放行前的代码
资源代码
Filter2放行后的代码
Filter1放行后的代码
有点类似于我们java中的栈.
过滤器链中的doFilter是如何执行的.
在第一个过滤器的doFilter中.如果我们用FilterChain放行了. filterChain.doFilter().
在执行filterChain的doFilter方法的时候.他回去判断.是否还有下一个匹配的过滤器.如果有就会去执行下一个Filter的doFilter方法.如果没有.就回去执行资源逻辑.
过滤器链中过滤器的顺序:
1.用注解的方式配置的过滤器. 过滤器的执行顺序跟过滤器的名字中字符的先后顺序有关.
2.如果web.xml中配置的过滤器. 只跟<filter-mapping>的先后顺序有关.
2.如果一个过滤器用注解配置的.一个是在web.xml中配置的.执行的顺序是怎么样的?
在web.xml中配置的过滤器先执行.
注意:
如果在过滤器链中任意的一个过滤器中不去放行. 那么后续的过滤器都不会执行.
或者反过来说. 要想正常访问某个资源.必须所有的过滤器都放行.
```
## 登录验证
```
1.要将request对象强转成 HttpServletRequest
2. 要将登录相关的资源排除掉. 包括web文件夹下所有的文件夹
3. 去判断是否登录.
如果已经登录.就放行
如果没有登录就跳转到登录界面.
```
## 动态代理
```java
真实对象: 就是被代理的对象.
代理对象: 就是我们去实现的跟被代理对象相同功能的一个对象.但是具体到每个方法可能不一致.这个不一致我们叫做"增强"
代理: 就是用代理对象去替代真实对象去执行对应的逻辑.就叫做代理.
1.JDK提供的动态代理的api
Proxy
前提: 真实对象跟代理对象必须实现相同的接口.
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
loader:就是类加载器. 真实对象.getClass().getClassLoader()
interfaces:就是真实对象实现的所有的方法. 真实对象.getClass().getInterfaces()
h:是一个回调接口.
InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
proxy:就是代理对象.一般不用.
method: 就是当前代理对象调用的方法封装成的对象.
args:就是调用当前方法,需要传入的参数.
2.cglib
使用步骤:
1.导包 spring-core就可以了
Lenovo le = new Lenovo();
//1.创建一个增强器对象
Enhancer en = new Enhancer();
//2. 设置父类
en.setSuperclass(le.getClass());
//3.设置回调函数
en.setCallback(new MethodInterceptor() {
/**
*
* @param o 代理对象
* @param method 代理对象调用的当前方法封装成的对象
* @param args 调用当前方法传入的参数
* @param methodProxy 方法代理对象
* @return
* @throws Throwable
methodProxy.invokeSuper(o,args); 传的第一个参数是代理对象
method.invoke(le, money); 第一个参数传的是真实对象.
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//判断是否是sale方法
if(method.getName().equals("sale")){
//1.增强参数
double money = (double) args[0];
money = money * 0.85;
System.out.println("专车接你....");
//使用真实对象调用该方法
String obj = (String) method.invoke(le, money);
System.out.println("免费送货...");
//2.增强返回值
return obj+"_鼠标垫";
}else{
Object obj = method.invoke(le, args);
return obj;
}
}
});
//4.创建代理对象
Lenovo o = (Lenovo) en.create();
// o.sale(8000);
o.show();
```
## FileReader源码分析
```java
FileReader{
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
}
InputStreamReader{
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
}
StreamDecoder{
public static StreamDecoder forInputStreamReader(InputStream var0, Object var1, String charset) throws UnsupportedEncodingException {
String var3 = charset;
if (charset == null) {
var3 = Charset.defaultCharset().name();
}
}
}
Charset{
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
String csn = AccessController.doPrivileged(
new GetPropertyAction("file.encoding"));
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}
}
默认编码格式跟file.encoding有关系.
http://bbs.itheima.com/forum.php ... d=462695&extra=
建议:
每次牵涉到编码集的时候.我们都手动指定.不要使用默认的编码集.因为不同的启动方式.是有可能不同的.
```
## Listener(了解)
```
监听:
就是关心的某个事件发生的时候.会触发对应的代码.
应用场景:
1.监听域对象的创建和销毁: reqeust, session ,application(ServletContext)
2.监听域对象中值的存入: session
4.监听session的钝化和活化
ServletContextListener
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2