javaWeb

一、环境搭建

1、JSP介绍

什么是jsp?

JSP全称Java server page 直译就是"运行在服务端的页面"。

我们可以直接在JSP文件里写HTML代码,使用上把它当作HTML文件。而且JSP中的HTML/CSS/JS等的写法和HTML文件中的写法是一摸一样的。我们还可以把Java代码内嵌在JSP页面中,很方便地把动态数据渲染成静态页面

JSP = HTML + Java

2、开发工具介绍

开发Java的工具一般常见的为Eclipse、MyEclipse、Idea

Eclipse与MyEclipse的区别

Eclipse是一个IDE(Integrated Developing Environment),而这个IDE是允许安装第三方开发的插件来使自身的功能得到扩展和增强的,而MyEclipse就是其中的一种有名的插件集之一,主要是J2EE开发,MyEclipse将开发者常用到的一些有用的插件都集合起来,提供一种高级编程环境,但它是收费的。

MyEclipse是Eclipse的插件版,同时MyEclipse要钱,Eclipse免费使用

下载链接: 

https://www.eclipse.org/downloads/packages/

 web版

 MyEclipse会自带JDk,可以直接使用

Eclipse使用必须安装JDK

JDk 是Java语言的软件开发工具包,主要用于移动设备、嵌入式设备上的Java应用程序。JDK是整个Java开发的核心,它包含了JAVA的运行环境(JVM + Java系统类库)和java工具。

JDK下载链接(选择自己需要的版本下载即可):

https://www.oracle.com/cn/java/technologies/downloads/

JDK的配置

1、测试:按下win + R ,输入cmd,然后回车输入java -version

出现这个说明配置成功 ,如果没有则需要手动配置:

WIN + X Y

系统信息 高级信息设置 环境变量

1、新建系统变量 JAVA_HOME 值:JDK安装路径

2、选中"path"点击"编辑"选项 新建填入 %JAVA_HOME%\bin %与JAVA_HOME%\jre\bin

3、新建系统变量CLASSPATH 

值:.;%Java_Home%\bin;%Java_Home%\lib\dt.jar;%Java_Home%\lib\tools.jar

最后重复上面的测试步骤即可 

3、服务器安装与配置

tomcat下载链接:(常见的版本8、8.5、9,新版本不稳定,可能会闪退)

https://tomcat.apache.org/

启动tomcat只需要打开

tomcat目录结构

1、bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类 是以.bat结尾的(windows命令)。

2、conf目录主要是用来存放tomcat的一些配置文件。 server.xml可以设置端口号、设置域名或IP、默认加载的项目、请求编码。

3、lib目录主要用来存放tomcat运行需要加载的jar包。

4、logs目录用来存放tomcat在运行过程中产生的日志文件

5、temp目录用户存放tomcat在运行过程中产生的临时文件。

6、webapps目录用来存放应用程序,当tomcat启动时会去加载webapps目录下的应用程序。可以以文件 夹、war包、jar包的形式发布应用。

7、work目录用来存放tomcat在运行时的编译后文件,例如JSP编译后的文件。

 通过访问localhost:8080查看tomcat是否打开服务

手动部署项目:将项目复制到webapps目录下即可

二、servlet&表单提交&页面跳转

1、servlet

1.1、什么是servlet?

Servlet是在服务器端运行的Java程序,可以接收客户端的请求并作出响应

Servlet可以动态生成HTML内容对客户端进行响应

Servlet与jsp的关系

1.2、实现接口,初识代码

public class HelloServlet implements Servlet {
           
    public LoginServlet1() {创建}

	public void destroy() {销毁}

	public ServletConfig getServletConfig() {
		return null;
	}
	public String getServletInfo() {
		return null;
	}	
    
	public void init(ServletConfig arg0) {初始化}
    
	public void service(ServletRequest arg0, ServletResponse arg1) {处理请求}   
           
}

1.3、学会配置和映射

  <!-- 配置servlet(HelloServlet) -->
  <servlet>
  	<servlet-name>HelloServlet</servlet-name>
  	<servlet-class>com.zking.HelloServlet</servlet-class>
  </servlet>
  <!-- 映射servlet(HelloServlet) -->
  <servlet-mapping>
  	<servlet-name>HelloServlet</servlet-name>
  	<url-pattern>/请求路径</url-pattern>
  </servlet-mapping>

<!-- 注意:但凡是改了web.xml文件的内容 务必记得重启服务器再运行!!! -->

1.4、掌握servlet的生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

1.5、获取servlet初始化参数和上下文参数

1.5.1、初识代码(推荐使用
public class LoginServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp){
		处理get请求
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) {		
		处理post请求
	}
}
1.5.2、初始化参数
<!-- 配置servlet(HelloServlet) -->
  <servlet>
  	<servlet-name>HelloServlet</servlet-name>
  	<servlet-class>com.zking.HelloServlet</servlet-class>
    <!-- 初始化参数 -->
  	<init-param>
  		<param-name>参数名</param-name>
  		<param-value>参数对应值</param-value>
  	</init-param>
  </servlet>

<!--只能在对应的一个servlet中拿到值:-->
this.getInitParameter("参数名");
1.5.3、上下文参数
<context-param>
  	<param-name>参数名</param-name>
  	<param-value>参数对应值</param-value>
</context-param>

<!--可被整个应用共享:-->
this.getServletContext().getInitParameter("参数名");

1.6、servlet应用:处理用户登录请求

1.6.1、为简化配置,推荐采用注解方式
@WebServlet("/请求url")
public class LoginServlet extends HttpServlet {}

//其等同于
 <!-- 配置servlet(LoginServlet) -->
 <servlet>
  	<servlet-name>HelloServlet</servlet-name>
  	<servlet-class>com.zking.LoginServlet</servlet-class>
 </servlet>
 <!-- 映射servlet(LoginServlet) -->
 <servlet-mapping>
  	<servlet-name>HelloServlet</servlet-name>
  	<url-pattern>/请求url</url-pattern>
 </servlet-mapping>
1.6.2、HttpServletRequest方法(请求)
【String getParameter(String name)】:根据name值得到value值
【String[ ] getParameterValues(String name)】:根据name值得到多个value值 例如:爱好

【void setCharacterEncoding(String charset)】:设置请求的编码方式 防止中文乱码
【void setAttribute(String key, Object value)】:存值[键值对的方式]
【Object getAttribute(String key)】:根据键拿到值
1.6.3、HttpServletResponse方法(响应)
【void setContentType(String arg0)】:设置响应的编码方式
【PrintWriter getWriter()】:获得内置对象out

2、表单提交方式

<form action="请求路径url" method="get/post"></form>

表单提交有两种方式:
		1.get(默认)  地址栏会显示信息,安全性低;有数据长度的限制
		2.post 反之  以后推荐使用post

3、页面跳转方式

1、重定向

resp.sendRedirect("xx.jsp");
out.print("<script>alert('提示信息');location.href='页面地址';</script>");

2、转发

req.getRequestDispatcher("xx.jsp").forward(req, resp);

3、区别

重定向: 地址栏发生改变;不可携带数据跳转;可跳转到任意资源;在客户端发挥作用
转发:  地址栏不发生改变,停留在了之前请求的位置;可以携带数据跳转;只可转发到当前项目内资源;在服务端发挥作用

 三、域对象&EL表达式&JSTL

1、jsp内置对象之域对象

1.1、什么是jsp的内置对象?

JSP的内置对象是指在JSP页面系统中已经默认内置的Java对象,这些对象不需要开发人员显式声明即可使用。一共有9个:
分别为request、response、session、application、out、pageContext、config、page和exception。

1.2、什么是域对象?

可以用于存储数据的内置对象,它们作用范围不同。一共有4个:
分别为request、session、application、pageContext。

1.3、域对象怎么存值和拿值?

域对象.setAttribute(String key,Object value)
域对象.getAttribute(String key)

1.4、域对象作用范围的区别?

1. pageContext: 可以存储数据,作用范围是当前页面有效。
2. request: 可以存储数据,作用范围是同一个请求,转发有效。
3. session: 可以存储数据, 作用范围是同一个会话有效,常用于保存用户登录信息。
4. application: 可以存储数据,作用范围是同一个应用。

1.5、常用内置对象与servlet的对应关系

/* 
 * request        :HttpServletRequest 【req】
 * response       :HttpServletResponse【resp】
 * session        :HttpSession(通过req.getSession())
 * out            :PrintWriter(通过resp.getWriter()) 
 * application    :ServletContext(this.getServletContext())
 */

1.6、jsp标签中转发用法

<jsp:forward page="goods.do"></jsp:forward>

2、EL表达式

2.1、什么是EL表达式?

EL即 Expression Language(表达式语言)

2.2、为什么要用EL表达式?

1、为了替代jsp页面中的复杂代码
2、EL表达式不会在页面显示null

2.3、EL的语法

${EL expression}  
${obj.name}  
【注意:${obj.name}实质是调用obj的getName()方法】
【注意:sname必须是stu实体类中的属性名!!!】

eg:${stu.sname}实质就是调用了stu.getSname()方法 
eg:${aa}实质就是拿域对象中键为aa的值

2.4、EL中的隐含对象(作用域)

pageScope、requestScope、sessionScope、applicationScope 在键出现冲突(重复)的时候

2.5、EL运算符

//算术、关系、逻辑运算符同java一致
eg:${2>1&&5!=6}

//empty/not empty运算符 判断是否为空/不为空
eg:${empty ls}

3、JSTL

3.1、什么是JSTL?

JSTL(JavaServerPages Standard Tag Library)JSP标准标签库,惯称c标签。

3.2、为什么要用JSTL?

使用了EL表达式可以简化JSP页面代码,但是如果需要进行逻辑判断、循环遍历怎么办?

3.3、JSTL核心标签库组成

JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

根据JSTL标签所提供的功能,可以将其分为5个类别。

  • 核心标签
  • 格式化标签
  • SQL 标签
  • XML 标签
  • JSTL 函数

3.4、使用步骤

下载jstl-1.2.jar

网址:https://mvnrepository.com/artifact/javax.servlet/jstl/1.2

下载standard-1.1.2.jar

网址:https://mvnrepository.com/artifact/taglibs/standard/1.1.2

 

1、将两个JSTL的jar包放到WebContent->WEB-INF->lib下
2、在所需的JSP页面添加taglib指令
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

3.5、语法

3.5.1、通用标签:set remove out

set标签用于给变量设置值和作用范围:<c:set var="变量名" value="值" scope="作用域"></c:set>
out标签在页面上显示信息或变量值: <c:out value=""></c:out>
remove标签用于删除作用域内的变量:<c:remove var="变量" scope="作用域"/> 

3.5.2、条件标签;if
 <c:if test="条件"> 

</c:if>
3.5.3、迭代标签:forEach forTokens
<!--1、forEach用于循环遍历-->
<c:forEach items="要遍历的集合对象" var="变量" varStatus="状态" begin="开始" end="结束"  step="增量">
	 循环体代码…
</forEach>

<!--2、forTokens用于分割-->
<c:forTokens items="要分割的内容" delims="用什么分割" var="变量">
	 
</c:forTokens>

<!--常用代码:-->
<c:forEach items="${ls}" var="g">
		商品名称:${g.gname}
        商品价格:${g.gprice}
</c:forEach>

四、增删改查功能实现

登录逻辑流程图

1、增加

触发器+序列实现自增

--序列
create sequence seq_goods;

--触发器:前触发
create or replace trigger t_goods
before insert
on tb_goods
for each row
begin
  :new.gid := seq_goods.nextval;--插入之前给商品编号列赋值
end;

增加逻辑流程图

取表的最大序列+1

/**
* 拿到id(标识列)
* @param tabName 表名
* @param colName 列名
* @return id
*/
public int getID(String tabName,String colName) {
	int n=0;
    try {
    	con=DBHelper.getCon();
        String sql="select nvl(max("+colName+"),0) from "+tabName;
        ps=con.prepareStatement(sql);
        rs=ps.executeQuery();
        if(rs.next()) {
      	  n=rs.getInt(1)+1;
    	}
    } catch (Exception e) {
    	e.printStackTrace();
    } finally {
    	DBHelper.close(con, ps, rs);
    }
    return n;
}

//运用
int gid = getID("tb_goods", "gid");
g.setGid(gid);

2、删除

删除逻辑流程图

删除方法

	public int del(int id){
		Connection con = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			con = DBHelper.getCon();
			String sql = "delete from bs_book where id = ?";
			ps = con.prepareStatement(sql);
			ps.setInt(1, id);
			return  ps.executeUpdate();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return 0;
	}

 del.do代码

package com.zking.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zking.biz.IBookBiz;
import com.zking.biz.impl.BookBizImpl;
import com.zking.dao.impl.BookDaoImpl;
import com.zking.dao.impl.UserDaoImpl;
import com.zking.entity.Book;
import com.zking.entity.User;
@WebServlet("/del.do")
public class DeleteServlet extends HttpServlet{
	private IBookBiz bd = new BookBizImpl();
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPost(req, resp);
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");
		//前往首页,并且展示数据
		String id = req.getParameter("id");
		bd.del(Integer.valueOf(id));
		resp.sendRedirect("home.do");
	}
}

前端实现

	<table class="table table-hover">
		<tr class="danger">
			<td>编号</td>
			<td>名称</td>
			<td>价格</td>
			<td>作者</td>
			<td>操作</td>
		</tr>
		<c:forEach items="${ books }" var="s">
		<tr>
			<td>${ s.id }</td>
			<td>${ s.title }</td>
			<td>${ s.price }</td>
			<td>${ s.author }</td>
			<td><a href="del.do?id=${ s.id }">删除</a>|<a href="aa.do?id=${ s.id }">修改</a></td>
			</tr>
		</c:forEach>
	</table>

3、修改

修改思路

 1、修改前业务处理(selvlet:preupddate.do)

//实例化dao
GoodsDao gd=new GoodsDao();
//接收gid
String gid = req.getParameter("gid");
//根据gid拿到商品对象=单个查询
Goods goods = gd.getGoods(gid);
//存起来
req.setAttribute("goods", goods);
//转发
req.getRequestDispatcher("update.jsp").forward(req, resp);

 2、前端页面处理(update.jsp)

页面显示编号,但不可编辑

商品编号:<input type="text" value="${goods.gid}" name="gid" readonly>
商品名称:<input type="text" value="${goods.gname}" name="gname">

 页面不显示编号 隐藏域传值

隐藏域(会随着表单的提交而提交)传值 必须写在表单中
<input type="hidden" name="gid" value="${goods.gid}">

 3、修改后业务处理(servlet:update.do)

//实例化dao
GoodsDao gd=new GoodsDao();
//设置编码方式
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//接收表单提交的数据
String gid = req.getParameter("gid");
String gname = req.getParameter("gname");
String s = req.getParameter("gprice");
String ginfo = req.getParameter("ginfo");
double gprice=Double.parseDouble(s);
//实例化商品对象
Goods g=new Goods(gname, gprice, ginfo);
//调用dao方法 连接数据库进行判断
int n = gd.update(g, gid);
if(n>0){//修改成功
    //重定向跳转去加载并展示数据
    resp.sendRedirect("goods.do");
}

4、查询

查询逻辑

 模糊查询后端功能代码

/**
	 * 模糊查询的方法
	 * @key 模糊查询关键字
	 * @title 模糊查询的列名
	 * @return 返回List集合
	 */
	public List<Book> queryAll(String key,String title){
        //判断关键字是否为空,为空则改为空字符串
		if(key==null) {
			key = "";
		}
        //判断如果列名为空则对标题进行模糊查
		if(title==null){
			title ="title";
		}
		Connection con = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<Book> books = new ArrayList<>();
		try {
			con = DBHelper.getCon();
			String sql = "select * from bs_book where "+title+" like ? order by id";
			ps = con.prepareStatement(sql);
			ps.setString(1, "%"+key+"%");
			rs = ps.executeQuery();
			while(rs.next()) {
				Book book = new Book();
				book.setId(rs.getInt(1));
				book.setTitle(rs.getString(2));
				book.setPrice(rs.getDouble(3));
				book.setAuthor(rs.getString(4));
				books.add(book);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return books;
	}

 selvlet代码(home.do)

req.setCharacterEncoding("utf-8");
		//前往首页,并且展示数据
		String key = req.getParameter("key");
		String type = req.getParameter("type");
		List<Book> list = bd.queryAll(key,type);
		req.setAttribute("key", key);
		req.setAttribute("type", type);
		req.setAttribute("books", list);
		req.getRequestDispatcher("home.jsp").forward(req, resp);

前端展示代码

<table class="table table-hover">
		<tr class="danger">
			<td>编号</td>
			<td>名称</td>
			<td>价格</td>
			<td>作者</td>
			<td>操作</td>
		</tr>
		<c:forEach items="${ books }" var="s">
		<tr>
			<td>${ s.id }</td>
			<td>${ s.title }</td>
			<td>${ s.price }</td>
			<td>${ s.author }</td>
			<td><a href="del.do?id=${ s.id }">删除</a>|<a href="aa.do?id=${ s.id }">修改</a></td>
			</tr>
		</c:forEach>

五、三层架构

1、什么是三层架构

三层架构:就是将整个业务划分为三层:表示层、业务逻辑层、数据库访问层

表示层:主要是指与用户交互的界面,用于接收用户输入的数据和显示处理后用户所需要的数据

业务逻辑层:表示层和数据库访问层之间的桥梁,实现业务逻辑,具体包含:验证、计算、业务规划等等

数据库访问层:与数据库打交道,主要实现对数据的增、删、改、查

注意:entity(实体类) 它不属于三层之中的任何一层,但是它贯穿于三层,能在三层之间传递数据

2、层与层之间的关系

3、怎么理解三层架构

 服务员:只管接待客人

厨师:只管做客人点的菜

采购员:只管按要求采购食材

4、为什么需要三层架构

区分层次的目的是为了“高内聚,低耦合”的思想

高内聚:尽可能类的每个成员方法只完成一件事

低耦合:减少类内部,一个成员方法调用另一个成员方法

从类角度来看,高内聚低耦合:减少类内部,对其他类的调用

从功能块来看,高内聚低耦合:减少模块之间的交互复杂度

简单来说,就是解耦:只做自己功能内的事

他们各施其职,服务员不用不用了解厨师如何做菜,不用了解采购员如何采购食材;厨师不用知道服务员接待了哪位客人,不用知道采购员如何采购食材;同样,采购员不用知道服务员接待了哪位客人,不用知道厨师如何做菜。

任何一层发生变法都不会影响其它层:

服务员(表示层):请假——另找服务员;

厨师(业务逻辑层):辞职——招聘另一个厨师;

采购员(数据库访问层):辞职——招聘另一个采购员;

5、两层与三层的区别

两层:当一个地方发生变化时,都需要重新开发整个系统。“多层”放在一层,分工不明确耦合度高,难以适应需求变化,可维护性低】可扩展性低

三层:发生在哪一层的变化,只需要更改该层,不需要更改整个系统。层次清晰,分工明确,每层之间的耦合度低——提高了效率,适应需求变化,可维护性高,可扩展性高

6、现状分析

我们目前是直接在表示层(servlet)调用了数据访问层dao(相当于服务员直接找到了采购员),不合适!

因此,我们应该增加业务逻辑层biz,在servlet中调用biz,biz中调用dao

7、面向接口编程

旨在将设计与实现完全分离

        在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

8、使用三层架构实现登录功能

//接口:只做设计,不做实现
public interface IUserDao {//IUserBiz
	public User login(String uname,String upwd);
}
/**
 * 数据访问层
 */
public class UserDao implements IUserDao{
	
    //在这个类里 以前怎么写dao方法 现在仍然怎么写
	//实现类 专门做实现
    private Connection con=null;
    private ResultSet rs=null;
    private PreparedStatement ps=null;

    public User login(String uname,String upwd) {
        User u=null;
        try {
            con=DBHelper.getCon();
            String sql="select * from tb_user where uname=? and upwd=?";
            ps=con.prepareStatement(sql);
            ps.setString(1, uname);
            ps.setString(2, upwd);
            rs=ps.executeQuery();
            if(rs.next()) {
                u=new User(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBHelper.close(con, ps, rs);
        }
        return u;
    }
    
}
/**
 * 业务逻辑层
 */
public class UserBiz implements IUserBiz {
	//调用 数据访问层(里氏替换原则)
	IUserDao iud=new UserDao();
}

/**
 * 表示层 
 */
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
    //调用 业务逻辑层(里氏替换原则)
    IUserBiz iub=new UserBiz();
}

9、三层架构命名方式

 六、购物车实现

1、实现购物车的方式

1、Cookie

  • 优点:Cookie是存储在客户端的,占用很少的资源,可以减轻服务器压力
  • 缺点:基于Cookie开发的购物车要求用户浏览器必须支持并设置为启用Cookie,否则购物车则失效,如果换一台机器再去登录的话,就会丢失购物车信息

2、session

  • 优点:session可以于客户端保持同步,不依赖于客户端的设置,它是存储在服务器端的信息,因此比较安全
  • 缺点:session会占用服务器资源,加大服务器负荷,会话具有时效性,一旦超时,购物车中商品信息会丢失

3、数据库

  • 优点:持久化储存,可以分析用户购买行为
  • 缺点:购物车需要实时操作,数据库访问量一旦过大了,就容易导致发生并发或者直接奔溃,维护成本会增加

七、ajax

1、什么是ajax

**Ajax**即**A**synchronous **J**avascript **A**nd **X**ML(异步JavaScript和XML) , 使用Ajax技术网页应用能够快速地将更新呈现在用户界面上,而<font color="red">不需要重载(刷新)整个页面【**只刷新局部**】</font>,这使得程序能够更快地回应用户的操作。

2、为什么需要ajax

        在我们之前的开发,每当用户向服务器发送请求,哪怕只是需要更新一点点的局部内容,服务器都会将整个页面进行刷新,这么做的问题有两点:

  • 性能会有所降低(一点内容就需要刷新整个庞大的网页)
  • 用户的操作页面会中断(整个页面被刷新了)

而我们基于ajax可以使用JavaScript技术向服务器发送异步请求,这可以使我们在不刷新页面的前提下拿到后端数据,完成页面的局部刷新,给用户的感受是在不知不觉中完成请求和响应过程。

3、同步交互和异步交互的区别

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求;

4、基于jQuery实现ajax

1、$.ajax(url,[settings])

url:一个用来包含发送请求的URL字符串

type:请求方式(post或get(默认))

data:发送到服务器的数据,例如:key1=value1&key2=value2或{key1:"value1",key2:"value2"}

dataType:预期服务器返回的数据类型(json,text,xml,hmtl······)

success(daya):请求成功的回调函数  data:服务器返回的数据(响应)

error:请求失败的回调函数

2、$.get/post(url,[data],[callback],[type])

url:发送请求地址

data:待发送key/value参数,例如:key1=value1&key2=value2或{key1:"value1",key2:"value2"}

type:预期服务器返回的数据类型,xml,html,json,text·····

cllback:发送成功时回调函数

八、session&cookie

一、session

1、什么是session?

        一个会话就是浏览器与服务器之间的一次通话,包含浏览器与服务器之间的多次请求、响应过程,session对象用来存储有关用户会话的所有信息。

2、session的常用方法

返回类型方法名称说明
voidsetAttribute(String key,Object value)以key/value形式保存对象值
ObjectgetAttribute(String key)通过key获取对象值
voidsetMaxInactivelnterval()设置session的有效非活动时间,以秒为单位
voidinvalidate()设置session对象失效
StringgetId()获取session对象的编号

二、cookie

1、什么是Cookie?

Cookie的中文意思是“小甜饼”,在互联网中,Cookie是小段的文本信息,在网络服务器上生成,并发送给浏览器。通过使用Cookie可以标识用户身份,记录用户名和密码,跟踪重复用户等。浏览器将Cookie以key/value的形式保存到客户端的某个指定目录中。

 基本语法:

//导入包
import="javax.servlet.http.Cookie"
//创建Cookie
Cookie cookie = new Cookie("name","value");
name:用于代表cookie的名称
value:用于表示当前名称所对应的值
//写入Cookie
resp.addCookie(cookie);

 cookie常用方法

返回类型方法名称说明
voidsetMaxAge(int expiry)设置Cookie的有效期,以秒为单位
voidsetValue(String value)在Cookie创建后,对Cookie进行赋值
String getValue()获取Cookie的值
String getName()获取Cookie的名称
StringgetMaxAge()获取Cookie的有效时间,以秒为单位

九、过滤器&监听器

一、过滤器

1、什么是过滤器

顾名思义,过滤器就像一张滤网,是处于客户端与服务器目标资源之间的一道过滤技术。

正常来说,客户端发出请求后都会交给servlet;但是如果过滤器存在,客户端发出的请求都是先交给过滤器,然后再交给servlet

2、过滤器的作用

它的主要作用是阻止不合法的请求和非法的访问,可以解决多个servlet共性代码的冗余问题

3、过滤器的实现过程

  • 编写java类实现Filter接口,重写三个方法init()、doFilter()、destroy();
  • 在doFilter()方法中编写拦截逻辑;
  • 设置拦截路径

4、过滤器的拦截路径

通常有三种形式

  • 精确拦截匹配,如:/index.jsp        /login.jsp
  • 后缀拦截匹配,如:*.jsp    *.html    *.jpg
  • 通配符拦截匹配,/*(表示拦截所有)

5、过滤器的运用

web.xml配置

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.zking.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>

注意:

web.xml配置方式过滤链的执行顺序跟配置的顺序一致

注解方式过滤链的执行顺序和类名字符排序有关  

注解方式

@WebFilter("*.do")
public class EncodingFilter implements Filter{
    //转成我们常用的req和resp
    HttpServletRequest req=(HttpServletRequest)arg0;
    HttpServletResponse resp=(HttpServletResponse)arg1;
    //设置编码方式
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html; charset=UTF-8");
    //放行
    arg2.doFilter(arg0, arg1);
}

二、监听器

servlet监听器,用于监听某个状态变化

1、监听器分类

根据监听对象的类型和范围,将监听器分为3类:

ServletRequest监听器(请求监听器)        域对象request

HttpSession监听器(会话监听)                域对象session

ServletContext监听器(上下文监听器)        域对象application

1.1、servletContext监听【常用】

用于监听web应用启动和销毁的事件,监听器类需要实现servletContextLisetener接口

ServletContext【application】域对象的生命周期;

创建:服务器启动时;

销毁:服务器关闭

该接口的主要方法:

void contextLnitialized(ServletContextEvent se);通知正在接收的对象,应用程序已经被加载及初始化

void contextDestroyed(ServletContextEvent se);通知正在接收的对象,应用程序已经被销毁

servletContextEvent的主要方法:

ServletContext getServletContext();取得当前的ServletContext对象

1.2、httpSession会话监听【偶尔用】
1、HttpSessionListener 监听会话情况
该接口的主要方法:
    sessionCreated(HttpSessionEvent se); session创建
    sessionDestroyed(HttpSessionEvent se); session销毁
2、HttpSessionAttribyteListener 监听器的操作
该接口的主要方法:
    void attributeAdded(HttpSessionBindingEvent se); 监听Http会话中的属性添加
    void attributeRemoved(HttpSessionBindingEvent se); 监听Http会话中的属性移除
    void attributeReplaced(HttpSessionBindingEvent se); 监听Http会话中的属性更改操作
1.3、servletRequest监听【不用】

用于监听客户端的请求初始化和销毁事件,需要实现ServletRequestListener接口

该接口的主要方法:
    requestInitialized(ServletRequestEvent):通知当前对象请求已经被加载及初始化

​	requestDestroyed(ServletRequestEvent):通知当前对象,请求已经被消除

ServletRequestEvent实例中的方法:

​	getServletRequest():获取ServletRequest对象

​	getServletContext():获取ServletContext对象

 2、监听器的配置

<!-- web.xml -->
<listener>
   <listener-class>com.test.listener.TestHttpSessionListener</listener-class>
</listener>

<!-- 注解方式 -->
@WebListener

问:为什么说session监听器和request监听器一般都不用?

答:以request监听器为例,如果采用request监听,那就意味着每次请求都要触发一次监听,这大大降低了程序的效率,因此很少用。 

3、监听器的运用:统计在线用户人数&显示当前用户

 思路:

首先需要一个装在线用户的集合,当应用初始化的时候在线用户集合初始化,数量为0,存起来

每次登录成功(session属性添加)的时候,取出集合,把用户加入集合,再把集合存起来

注销的时候,取出集合,把用户移除集合,再把集合存起来

 1、Listener
@WebListener
public class CountListener implements ServletContextListener,HttpSessionListener,HttpSessionAttributeListener{

	private ServletContext  application;

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		//System.out.println("应用被销毁了");
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		//应用被初始化拿到application对象
		application = arg0.getServletContext();
		//实例化保存用户名的集合
		List<String> ls=new ArrayList<String>();
		//存起来
		application.setAttribute("ls",ls); 
		application.setAttribute("count", ls.size());
	}

	@Override
	public void sessionCreated(HttpSessionEvent arg0) {
		System.out.println("会话被创建了");
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent arg0) {
		System.out.println("会话被销毁了");
		//先拿集合
		List<String> ls=(List<String>)application.getAttribute("ls");
		//拿到当前的用户
		User u = (User)arg0.getSession().getAttribute("user");
		//将其从集合中移除
		ls.remove(u.getUname());
		//重新存起来 
		application.setAttribute("ls",ls); 
		application.setAttribute("count", ls.size());
	}

	@Override
	public void attributeAdded(HttpSessionBindingEvent arg0) {
		//先拿集合
		List<String> ls=(List<String>)application.getAttribute("ls");
		//拿当前用户
		User u = (User)arg0.getSession().getAttribute("user");
		//假设法
		boolean f=false;
		for (String s : ls) {
			//如果存在
			if(s.equals(u.getUname())) {
				f=true;
				break;
			}
		}
		if(f==false) {//不存在才加进去 
			ls.add(u.getUname());
		}
		//重新存起来
		application.setAttribute("ls",ls); 
		application.setAttribute("count", ls.size());
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent arg0) {
		// TODO Auto-generated method stub
		
	}

}
2、servlet
HttpSession session = req.getSession();//拿到session
session.invalidate();//让session失效
resp.sendRedirect("login.jsp");//跳转到login.jsp
 3、jsp
<h2>欢迎${user.uname},这是主界面</h2>
<div style="font-size: 20px;color:red;">当前在线用户:
	<c:forEach items="${ls}" var="i">
		${i}
	</c:forEach>
</div>
<h2>在线人数:${count}人</h2>

十、富文本编辑器

富文本编辑器(Rich Text Editor)是一种允许用户以更直观、更易于理解的方式编辑文本的工具。 与传统的纯文本编辑器不同,富文本编辑器为用户提供了多种格式化选项,如字体、颜色、大小、对齐方式、列表、链接、图片等。 这意味着,你可以轻松地创建出丰富、有吸引力的内容,而无需去记住复杂的HTML代码。

CKEditor

 Ckeditor也是一款非常经典的富文本编辑器,官方下载量过千万。它是在非常著名的FCkEditor基础上开发的新版本,FckEditor的用户现在基本都转移到Ckeditor了。

 Ckeditor有高性能的实时预览,它特有行内编辑功能,使得编辑内容更加直观,仿佛是在编辑网页一样,有很强的可扩展性,被各大网站广泛运用。

 更多介绍及下载:https://ckeditor.com/

十一、文件上传

就是将本地文件上传到服务器,并且可以在服务器进行访问

文章一:https://cloud.tencent.com/developer/article/1475522

文章二:https://blog.youkuaiyun.com/qq_21223653/article/details/107797667

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值