Javascript
Javascript是客户端的一个脚本语言
<script language="JavaScript">
var str = "hello world";
alert(typeof str);
str = 999;
alert(typeof str);
</script>
Javascript是一门弱类型的语言,变量的数据类型由后面附的值类型决定(和python类似)
<script language="JavaScript">
var str = "hello world";
alert(typeof str);
str = 999;
alert(typeof str);
</script>
js的类的属性不需要提前定义可以随时定义
js的函数使用时传参可不固定也可以不写return
function hello(num1,num2...) {
return
}
evevt.insertRow([index])
event.insertCell([index])
总结
1.CSS
-
CSS的角色:页面显示的美观风格
-
CSS的基础语法:标签样式;类样式;ID样式;组合样式;嵌入式样式表;内部样式表;外部样式表
-
盒子模型:border、margin、padding
-
定位和浮动:position、float、DIV+CSS布局
2.JS
-
JS是客户端(浏览器端)运行的脚本语言,语法风格和java比较类似
-
JS是弱类型的语言 var str = 99 ;
-
JS的函数 function hello(var num){}
-
DOM技术: 4-1) 鼠标悬浮:onmouseover,event.srcElement,事件传递,parentElement,style.backgroundColor 鼠标离开:onmouseout 4-2) 鼠标点击:hand/pointer,onclick , td.innerText , td.innerHTML="<input type='text'/>", td.firstChild.value=oldPrice 失去焦点:onblur , input.parentElement.innerText = newPrice ; 更新小计:input = event.srcElement , tr = input.parentElement.parentElement ; tr.cells , parseInt 更新总计:document.getElementById("fruit_tbl") , fruitTbl.rows 4-3) 删除一行:img , img.parentElement.parentElement.rowIndex , table.deleteRow(rowIndex)
BS介绍
创建项目
顺序
-
新建项目 - 新建模块
-
在模块中添加web
-
创建artifact - 部署包
-
lib - artifact 先有artifact,后来才添加的mysql.jar。此时,这个jar包并没有添加到部署包中 那么在projectSettings中有一个Problems中会有提示的,我们点击fix选择add to... 另外,我们也可以直接把lib文件夹直接新建在WEB-INF下。 这样不好的地方是这个lib只能是当前这个moudle独享。如果有第二个moudle我们需要再次重复的新建lib。
-
在部署的时候,修改application Context。然后再回到server选项卡,检查URL的值。 URL的值指的是tomcat启动完成后自动打开你指定的浏览器,然后默认访问的网址。 启动后,报错404.404意味着找不到指定的资源。 如果我们的网址是:http://localhost:8080/pro01/ , 那么表明我们访问的是index.html. 我们可以通过<welcome-file-list>标签进行设置欢迎页(在tomcat的web.xml中设置,或者在自己项目的web.xml中设置)
-
405问题。当前请求的方法不支持。比如,我们表单method=post , 那么Servlet必须对应doPost。否则报405错误。
-
空指针或者是NumberFormatException 。因为有价格和库存。如果价格取不到,结果你想对null进行Integer.parseInt()就会报错。错误的原因大部分是因为 name="price"此处写错了,结果在Servlet端还是使用request.getParameter("price")去获取。
-
<url-pattern>中以斜杠开头
编码注意
-
设置编码 tomcat8之前,设置编码: 1)get请求方式: //get方式目前不需要设置编码(基于tomcat8) //如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前) String fname = request.getParameter("fname"); //1.将字符串打散成字节数组 byte[] bytes = fname.getBytes("ISO-8859-1"); //2.将字节数组按照设定的编码重新组装成字符串 fname = new String(bytes,"UTF-8"); 2)post请求方式: request.setCharacterEncoding("UTF-8"); tomcat8开始,设置编码,只需要针对post方式 request.setCharacterEncoding("UTF-8"); 注意: 需要注意的是,设置编码(post)这一句代码必须在所有的获取参数动作之前
Servlet
Servlet是一个请求
HttpServle是基于HTTP协议的一个请求
Servlet的继承关系
-
Servlet的继承关系 - 重点查看的是服务方法(service())
-
继承关系 javax.servlet.Servlet接口 javax.servlet.GenericServlet抽象类 javax.servlet.http.HttpServlet抽象子类
-
相关方法 javax.servlet.Servlet接口: void init(config) - 初始化方法 void service(request,response) - 服务方法 void destory() - 销毁方法
javax.servlet.GenericServlet抽象类: void service(request,response) - 仍然是抽象的
javax.servlet.http.HttpServlet 抽象子类: void service(request,response) - 不是抽象的 1. String method = req.getMethod(); 获取请求的方式 2. 各种if判断,根据请求方式不同,决定去调用不同的do方法 if (method.equals("GET")) { this.doGet(req,resp); } else if (method.equals("HEAD")) { this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { 3. 在HttpServlet这个抽象类中,do方法都差不多: protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_get_not_supported"); if (protocol.endsWith("1.1")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } } 3.小结:
-
继承关系: HttpServlet -> GenericServlet -> Servlet
-
Servlet中的核心方法: init() , service() , destroy()
-
服务方法: 当有请求过来时,service方法会自动响应(其实是tomcat容器调用的) 在HttpServlet中我们会去分析请求的方式:到底是get、post、head还是delete等等 然后再决定调用的是哪个do开头的方法 那么在HttpServlet中这些do方法默认都是405的实现风格-要我们子类去实现对应的方法,否则默认会报405错误
-
因此,我们在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法
-
Servlet的生命周期
1) 生命周期:实例化(tomcat容器完成),初始化(init()),服务(service()),销毁(destroy()),从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init(),service(),destroy() 2) 默认情况下: 第一次接收请求时,这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service()) 从第二次请求开始,每一次都是服务 当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法 3) 通过案例我们发现:
- Servlet实例tomcat只会创建一个(通过反射,但私有方法无法调用,应为没有设置允许访问),所有的请求都是这个实例去响应。
- 默认情况下,第一次请求时,tomcat才会去实例化,初始化,然后再服务.这样的好处是什么? 提高系统的启动速度 。 这样的缺点是什么? 第一次请求时,耗时较长。
- 因此得出结论: 如果需要提高系统的启动速度,当前默认情况就是这样。如果需要提高响应速度,我们应该设置Servlet的初始化时机。
4) Servlet的初始化时机:
- 默认是第一次接收请求时,实例化,初始化
- 我们可以通过<load-on-startup>来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值0
5) Servlet在容器中是:单例的、线程不安全的
- 单例:所有的请求都是同一个实例去响应
- 线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化,
![01.Servlet是线程不安全的](F:\BaiduNetdiskDownload\Day4-servlet-http-session\素材\01.Servlet是线程不安全的.png)
- **注意**:我们已经知道了servlet是线程不安全的,给我们的启发是: 尽量的不要在servlet中定义成员变量。如果不得不定义成员变量,那么不要去:①不要去修改成员变量的值 ②不要去根据成员变量的值做一些逻辑判断
Http协议
是什么
1) Http 称之为 超文本传输协议 2) Http是无状态的 3) Http请求响应包含两个部分:请求和响应
-
请求: 请求包含三个部分: 1.请求行 ; 2.请求消息头 ; 3.请求主体 1)请求行包含是三个信息: 1. 请求的方式 ; 2.请求的URL ; 3.请求的协议(一般都是HTTP1.1) 2)请求消息头中包含了很多客户端需要告诉服务器的信息,比如:我的浏览器型号、版本、我能接收的内容的类型、我给你发的内容的类型、内容的长度等等 3)请求体,三种情况 get方式,没有请求体,但是有一个queryString post方式,有请求体,form data json格式,有请求体,request payload
-
响应: 响应也包含三本: 1. 响应行 ; 2.响应头 ; 3.响应体 1)响应行包含三个信息:1.协议 2.响应状态码(404) 3.响应状态(ok) 2)响应头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等) 3)响应体:响应的实际内容(比如请求add.html页面时,响应的内容就是<html><head><body><form....)
会话
1) Http是无状态的
- HTTP 无状态 :服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的
- 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱
- 通过会话跟踪技术来解决无状态的问题。
2) 会话跟踪技术
- 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端 - 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端 - 常用的API: request.getSession() -> 获取当前的会话,没有则创建一个新的会话 request.getSession(true) -> 效果和不带参数相同 request.getSession(false) -> 获取当前会话,没有则返回null,不会创建新的
session.getId() -> 获取sessionID
session.isNew() -> 判断当前session是否是新的
session.getMaxInactiveInterval() -> session的非激活间隔时长,默认1800秒
session.setMaxInactiveInterval()
session.invalidate() -> 强制性让会话立即失效
....
3) session保存作用域
-
session保存作用域是和具体的某一个session对应的
-
不同的浏览器,session id 不同
-
常用的API: void session.setAttribute(k,v) Object session.getAttribute(k) void removeAttribute(k)
服务器内部转发以及客户端重定向
1) 服务器内部转发 : request.getRequestDispatcher("...").forward(request,response);
-
一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
-
地址栏没有变化
2) 客户端重定向: response.sendRedirect("....");
-
两次请求响应的过程。客户端肯定知道请求URL有变化
-
地址栏有变化
错误详情
// 200 : 正常响应 // 404 : 找不到资源 // 405 : 请求方式不支持 // 500 : 服务器内部错误
Thymeleaf - 视图模板技术
1) 添加thymeleaf的jar包 2) 新建一个Servlet类ViewBaseServlet 3) 在web.xml文件中添加配置
-
配置前缀 view-prefix
-
配置后缀 view-suffix 4) 使得我们的Servlet继承ViewBaseServlet
5) 根据逻辑视图名称 得到 物理视图名称 //此处的视图名称是 index //那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去 //逻辑视图名称 : index //物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix //所以真实的视图名称是: / index .html super.processTemplate("index",request,response); 6) 使用thymeleaf的标签 th:if , th:unless , th:each , th:text
保存作用域
原始情况下,保存作用域我们可以认为有四个: page(页面级别,现在几乎不用) , request(一次请求响应范围) , session(一次会话范围) , application(整个应用程序范围) 1) request:一次请求响应范围,就是HttpServletRequest
2) session:一次会话范围有效session保存
3) application: 一次应用程序范围有效,就是ServletContext对象保存
-
路径问题
-
1) 相对路径
-
绝对路径
-
servlet-MVC
变为
再改通过反射调用
再进行中央控制
-
最初的做法是: 一个请求对应一个Servlet,这样存在的问题是servlet太多了
-
把一些列的请求都对应一个Servlet, IndexServlet/AddServlet/EditServlet/DelServlet/UpdateServlet -> 合并成FruitServlet 通过一个operate的值来决定调用FruitServlet中的哪一个方法 使用的是switch-case
-
在上一个版本中,Servlet中充斥着大量的switch-case,试想一下,随着我们的项目的业务规模扩大,那么会有很多的Servlet,也就意味着会有很多的switch-case,这是一种代码冗余 因此,我们在servlet中使用了反射技术,我们规定operate的值和方法名一致,那么接收到operate的值是什么就表明我们需要调用对应的方法进行响应,如果找不到对应的方法,则抛异常
-
在上一个版本中我们使用了反射技术,但是其实还是存在一定的问题:每一个servlet中都有类似的反射技术的代码。因此继续抽取,设计了中央控制器类:DispatcherServlet DispatcherServlet这个类的工作分为两大部分: 1.根据url定位到能够处理这个请求的controller组件: 1)从url中提取servletPath : /fruit.do -> fruit 2)根据fruit找到对应的组件:FruitController , 这个对应的依据我们存储在applicationContext.xml中 <bean id="fruit" class="com.atguigu.fruit.controllers.FruitController/> 通过DOM技术我们去解析XML文件,在中央控制器中形成一个beanMap容器,用来存放所有的Controller组件 3)根据获取到的operate的值定位到我们FruitController中需要调用的方法 2.调用Controller组件中的方法:
-
获取参数
获取即将要调用的方法的参数签名信息: Parameter[] parameters = method.getParameters();
通过parameter.getName()获取参数的名称;
准备了Object[] parameterValues 这个数组用来存放对应参数的参数值
另外,我们需要考虑参数的类型问题,需要做类型转化的工作。通过parameter.getType()获取参数的类型-
执行方法
Object returnObj = method.invoke(controllerBean , parameterValues);
-
视图处理
String returnStr = (String)returnObj;
if(returnStr.startWith("redirect:")){
....
}else if..... -
再次学习Servlet的初始化方法
-
Servlet生命周期:实例化、初始化、服务、销毁
-
Servlet中的初始化方法有两个:init() , init(config) 其中带参数的方法代码如下: public void init(ServletConfig config) throws ServletException { this.config = config ; init(); } 另外一个无参的init方法如下: public void init() throws ServletException{ } 如果我们想要在Servlet初始化时做一些准备工作,那么我们可以重写init方法 我们可以通过如下步骤去获取初始化设置的数据
-
获取config对象:ServletConfig config = ();
-
获取初始化参数值: config.getInitParameter(key);
-
在web.xml文件中配置Servlet <servlet> <servlet-name>Demo01Servlet</servlet-name> <servlet-class>com.atguigu.servlet.Demo01Servlet</servlet-class> <init-param> <param-name>hello</param-name> <param-value>world</param-value> </init-param> <init-param> <param-name>uname</param-name> <param-value>jim</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Demo01Servlet</servlet-name> <url-pattern>/demo01</url-pattern> </servlet-mapping>
-
也可以通过注解的方式进行配置: @WebServlet(urlPatterns = {"/demo01"} , initParams = { @WebInitParam(name="hello",value="world"), @WebInitParam(name="uname",value="jim") })
-
学习Servlet中的ServletContext和<context-param>
-
获取ServletContext,有很多方法 在初始化方法中: ServletContxt servletContext = getServletContext(); 在服务方法中也可以通过request对象获取,也可以通过session获取: request.getServletContext(); session.getServletContext()
-
获取初始化值: servletContext.getInitParameter();
-
什么是业务层
-
Model1和Model2 MVC : Model(模型)、View(视图)、Controller(控制器) 视图层:用于做数据展示以及和用户交互的一个界面 控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成 模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件
-
pojo/vo : 值对象
-
DAO : 数据访问对象
-
BO : 业务对象
-
-
区分业务对象和数据访问对象: 1) DAO中的方法都是单精度方法或者称之为细粒度方法。什么叫单精度?一个方法只考虑一个操作,比如添加,那就是insert操作、查询那就是select操作.... 2) BO中的方法属于业务方法,也实际的业务是比较复杂的,因此业务方法的粒度是比较粗的 注册这个功能属于业务功能,也就是说注册这个方法属于业务方法。 那么这个业务方法中包含了多个DAO方法。也就是说注册这个业务功能需要通过多个DAO方法的组合调用,从而完成注册功能的开发。 注册: 1. 检查用户名是否已经被注册 - DAO中的select操作 2. 向用户表新增一条新用户记录 - DAO中的insert操作 3. 向用户积分表新增一条记录(新用户默认初始化积分100分) - DAO中的insert操作 4. 向系统消息表新增一条记录(某某某新用户注册了,需要根据通讯录信息向他的联系人推送消息) - DAO中的insert操作 5. 向系统日志表新增一条记录(某用户在某IP在某年某月某日某时某分某秒某毫秒注册) - DAO中的insert操作 6. ....
-
在库存系统中添加业务层组件
IOC
Node 节点(注释和空白都算节点)
Element 元素节点
Text 文本节点
<sname>jim</sname>
-
耦合/依赖 依赖指的是某某某离不开某某某 在软件系统中,层与层之间是存在依赖的。我们也称之为耦合。 我们系统架构或者是设计的一个原则是: 高内聚低耦合。 层内部的组成应该是高度聚合的,而层与层之间的关系应该是低耦合的,最理想的情况0耦合(就是没有耦合)
-
IOC - 控制反转 / DI - 依赖注入
-
之前在Servlet中,我们创建service对象 , FruitService fruitService = new FruitServiceImpl(); 这句话如果出现在servlet中的某个方法内部,那么这个fruitService的作用域(生命周期)应该就是这个方法级别; 如果这句话出现在servlet的类中,也就是说fruitService是一个成员变量,那么这个fruitService的作用域(生命周期)应该就是这个servlet实例级别
-
之后我们在applicationContext.xml中定义了这个fruitService。然后通过解析XML,产生fruitService实例,存放在beanMap中,这个beanMap在一个BeanFactory中 因此,我们转移(改变)了之前的service实例、dao实例等等他们的生命周期。控制权从程序员转移到BeanFactory。这个现象我们称之为控制反转
依赖注入:
-
之前我们在控制层出现代码:FruitService fruitService = new FruitServiceImpl();
那么,控制层和service层存在耦合。
-
之后,我们将代码修改成FruitService fruitService = null ;
然后,在配置文件中配置:
<bean id="fruit" class="FruitController">
<property name="fruitService" ref="fruitService"/>
</bean> -
-
过滤器Filter
-
Filter也属于Servlet规范
-
Filter开发步骤:新建类实现Filter接口,然后实现其中的三个方法:init、doFilter、destroy 配置Filter,可以用注解@WebFilter,也可以使用xml文件 <filter> <filter-mapping>
-
Filter在配置时,和servlet一样,也可以配置通配符,例如 @WebFilter("*.do")表示拦截所有以.do结尾的请求
-
过滤器链 1)执行的顺序依次是: A B C demo03 C2 B2 A2,栈结构 2)如果采取的是注解的方式进行配置,那么过滤器链的拦截顺序是按照全类名的先后顺序排序的 3)如果采取的是xml的方式进行配置,那么按照配置的先后顺序进行排序
例子
事务管理
-
涉及到的组件:
-
OpenSessionInViewFilter
-
TransactionManager
-
ThreadLocal
-
ConnUtil
-
BaseDAO
ThreadLocal
-
get() , set(obj)
-
类似一个公共工作台,被一个项目公用;
-
ThreadLocal称之为本地线程不是当前线程,其是一个容器 。 我们可以通过set方法在当前线程上存储数据、通过get方法在当前线程上获取数据
-
set方法源码分析: public void set(T value) { Thread t = Thread.currentThread(); //获取当前的线程 ThreadLocalMap map = getMap(t); //每一个线程都维护各自的一个容器(ThreadLocalMap) if (map != null) map.set(this, value); //这里的key(this)对应的是要用的ThreadLocal(一个对象),不是当前线程,因为我们的组件中需要传输(共享)的对象可能会有多个(不止Connection) else createMap(t, value); //默认情况下map是没有初始化的,那么第一次往其中添加数据时,会去初始化 } -get方法源码分析: public T get() { Thread t = Thread.currentThread(); //获取当前的线程 ThreadLocalMap map = getMap(t); //获取和这个线程(企业)相关的ThreadLocalMap(也就是工作纽带的集合) if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //this指的是ThreadLocal对象,通过它才能知道是哪一个工作纽带 if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; //entry.value就可以获取到工具箱了 return result; } } return setInitialValue(); }
监听器
-
ServletContextListener - 监听ServletContext对象的创建和销毁的过程
-
HttpSessionListener - 监听HttpSession对象的创建和销毁的过程
-
ServletRequestListener - 监听ServletRequest对象的创建和销毁的过程
-
ServletContextAttributeListener - 监听ServletContext的保存作用域的改动(add,remove,replace)
-
HttpSessionAttributeListener - 监听HttpSession的保存作用域的改动(add,remove,replace)
-
ServletRequestAttributeListener - 监听ServletRequest的保存作用域的改动(add,remove,replace)
-
HttpSessionBindingListener - 监听某个对象在Session域中的创建与移除
-
HttpSessionActivationListener - 监听某个对象在Session域中的序列化(挂起)和反序列化
-
ServletContextListener的应用 - ContextLoaderListener
-
TransActionManager、ThreadLocal、OpenSessionInViewFilter
xml
1.概念 HTML :超文本标记语言 XML :可扩展的标记语言 HTML是XML的一个子集 2.XML包含三个部分: 1) XML声明 , 而且声明这一行代码必须在XML文件的第一行 2) DTD 文档类型定义 3) XML正文
常见错误
argument type mismatch类型不匹配
尽量在最后执行捕获(catch)
// 200 : 正常响应 // 404 : 找不到资源 // 405 : 请求方式不支持 // 500 : 服务器内部错误
标签:JavaWeb,Servlet,方法,request,session,随笔,servlet,请求 From: https://www.cnblogs.com/qylqf/p/17644734.html