javaweb-web核心

day13_Tomcat&Servlet

1.web相关概念(了解)

1. 软件架构
	1. C/S:客户端/服务器端
	2. B/S:浏览器/服务器端

2. 资源分类
	1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析
		* 如: html,css,JavaScript
	2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器
		* 如:servlet/jsp,php,asp....
3. 网络通信三要素
	1. IP:电子设备(计算机)在网络中的唯一标识。
	2. 端口:应用程序在计算机中的唯一标识。 0~65536
	3. 传输协议:规定了数据传输的规则
		1. 基础协议:
			1. tcp:安全协议,三次握手。 速度稍慢
			2. udp:不安全协议。 速度快

2.Tomcat的启动问题

下载:http://tomcat.apache.org/
安装:解压即可使用,不需要安装
启动:双击bin/startup.bat就可以启动,启动的黑窗口不能关闭
	访问自己:http://localhost:8080
	访问别人:http://别人ip地址:8080
卸载:直接删除解压的文件即可

启动问题:启动黑窗口一闪而过
	问题1:JAVA_HOME环境变量没有配置
	解决:正确配置JAVA_HOME环境变量
	
	问题2:tomcat端口号冲突,一般是启动了多个tomcat服务器
	解决:在任务管理器中结束掉之前启动的tomcat进程
正常关闭tomcat:
	1.双击bin/shutdown.bat
	2.ctrl+c也是正常关闭

3.项目的3种发布方式

  • 3种发布方式
1. 直接将项目放到webapps目录下即可。(掌握这个就可以了)
	* /hello:项目的访问路径-->虚拟目录
	* 简化部署:将项目打成一个war包,再将war包放置到webapps目录下。
		* war包会自动解压缩
2. 配置conf/server.xml文件的<Host>标签体中配置
	<Context docBase="D:\hello" path="/hehe" />
	* docBase:项目存放的路径
	* path:虚拟目录
3. 在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写
	<Context docBase="D:\hello" />
	* 虚拟目录:xml文件的名称
  • 访问路径解析

访问路径解析.bmp

4.Servlet概述以及实现思路(重点1)

  • Servlet的作用

  • 实现一个Servlet的步骤
1.定义一个类实现Servlet接口;
public class ServletDemo1 implements Servlet{
	
}
2.配置这个Servlet
	2.1 在web.xml中配置Servlet(了解)
		<!--配置Servlet的类路径-->
        <servlet>
            <servlet-name>ServletDemo1</servlet-name>
            <servlet-class>com.itheima.servlet.ServletDemo1</servlet-class>
        </servlet>
        <!--配置Servlet的映射路径-->
        <servlet-mapping>
            <servlet-name>ServletDemo1</servlet-name>
            <url-pattern>/servletDemo1</url-pattern>
        </servlet-mapping>
    2.2 使用注解配置Servlet(吐血推荐)
    	@WebServlet("/demo1")
		public class ServletDemo1 implements Servlet{}

5.Servlet生命周期(了解)

  • 描述Servlet生命周期
思路:三个方法分别是什么时候被调用的?调用几次?作用分别是什么?
	当我们第一次访问Servlet时,服务器会创建Servlet对象,调用init()方法初始化,该方法只调用一次,可以用来加载配置文件;每当我们访问Servelt时,service()方法都会被调用,访问一次就调用一次,用来接收客户端请求以及对客户端作出响应;服务器正常关闭的时候销毁Servlet对象,destory()方法会被调用,调用一次,一般在该方法中释放资源;
  • 配置启动时加载
在web.xml中的<Servlet>标签中配置<load-on-startup>2</load-on-startup>,值越小优先级越高;

6.导入项目并手动发布项目(重要2)

  • 第一步:导入别人的项目 File—>new —>module from exiting Sources 然后一直下一步
  • 第二步:添加tomcat环境,解决Servlet/HttpServlet报错问题

第三步.让idea识别web目录,出现蓝色的小点点

第四步.将web目录中的内容进行发布,将项目源代码编译成符合tomcat要求的目录结果

第五步.将编译好的项目添加到tomcat中

7.总结

  • 将tomcat集成到idea中,并创建java Enterprise项目,启动服务器发布(自动 发布)
  • 创建Servlet并配置,成功访问Servlet,修改Servlet目标如下:

修改Servlet模板.bmp

  • 描述Servlet的生命周期
  • 手动发布多个项目

day14_request

1.<url-pattern>访问路径问题

1.完全路径匹配:以/开头,不包含通配符*  例如:/servletDemo1  /demo1 /abc /aaa/bbb  /abc.do  (常用)
2.目录匹配:以/开头,以*结尾;在浏览器访问时*表示任意字符  例如:/abc/*  /*
3.扩展名匹配:以*开头,以固定的后缀名结尾  例如  *.jsp  *.abc   但是/abc/*.do错误  

2.HTTP协议

  • 概念:http协议规定的是客户端和服务器之间通信的规则;
  • 特点:http协议是基于请求和响应;一定是先有请求后有响应,一次请求对应一次响应;
  • 请求部分:分4个部分
请求行:
	请求方式  url路径  协议/版本
	POST /day14/servletDemo5 HTTP/1.1
	
请求头:一般是一个key对应一个value,也有一个key对应多个value;
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
	告诉服务器浏览器的版本信息,一般用来解决浏览器兼容性问题;
    Referer: http://localhost:8080/day14/login.html
    告诉浏览器当前请求的来源,用于防盗链以及统计工作;
    
请求空行:用于分隔请求头和请求体

请求体:只有post请求才有请求体,get请求没有,post请求参数就在请求体中
	username=zhaoying

3.Requst对象获取请求行/头方法(了解)

3.1 Request原理

request和response是服务器创建的两个对象给我们使用,request封装了浏览器发送过来的所有数据,如果是获取浏览器发送过来的信息那么就找request对象,如果想告诉浏览器展示信息那么就找response对象;

3.2 Requst对象获取请求行方法

1. 获取请求方式 :GET
	String getMethod()  
2. (*)获取虚拟目录:/day14
	String getContextPath()
3. 获取Servlet路径: /demo1
	String getServletPath()
4. 获取get方式请求参数:name=zhangsan
	String getQueryString()
5. (*)获取请求URI:/day14/demo1
	String getRequestURI():		/day14/demo1	不全的路径
	StringBuffer getRequestURL()  :http://localhost/day14/demo1   全路径
	URL:统一资源定位符 : http://localhost/day14/demo1	中华人民共和国
	URI:统一资源标识符 : /day14/demo1					共和国

6. 获取协议及版本:HTTP/1.1
	String getProtocol()
7. 获取客户机的IP地址:
	String getRemoteAddr()

重点记一下:获取虚拟目录的getServletPath()方法,getRequestURI()方法作为一个次掌握的方法

3.3 Requst对象获取请求头方法

1. String getHeader(String name) ;根据指定的请求头获取请求头的值;
2. Enumeration<E> getHeaderNames() ;获取所有请求头

4.Request对象获取请求参数方法(重点)

4.1 获取请求参数的三个方法(重点1)

String getParameter(String name)  :根据一个name获取一个value值		很常用
String[] getParameterValues(String name)  :根据一个name获取多个value值
Map<String,String[]> getParameterMap()  :获取所有请求参数	很常用

4.2 请求参数中文乱码问题(重点2)

说明:从tomcat8.0之后,get请求参数不再乱码,但是post请求参数依然乱码

原因:request缓冲区默认字符集是iso-8859-1不支持中文
解决办法:在获取请求参数之前设置request缓冲区字符集为utf-8
request.setCharacterEncoding("utf-8")

5.Request对象请求转发和作为域对象(重点)

5.1 请求转发实现页面跳转(重点3)

1.请求转发api:
	request.getRequestDispatcher("/转发的路径,不带虚拟路径").forward(request,response);
2.转发的特点:
	2.1 请求转发是一次请求一次响应;
	2.2 请求转发浏览器地址栏不会发生变化
	2.3 请求转发api中路径不需要携带虚拟路径,默认是访问项目内部资源;

5.2 request作为域对象数据共享(存值、取值、移除值)(重点4)

作用范围:一次请求范围,浏览器发送请求到服务器做成响应结束,请求转发在一次请求范围内;
创建和销毁时间:浏览器发送请求之后服务器创建request对象,服务器做成相应之后销毁;
存值、取值、移除值api:
	存值:request.setAttribute(String name,Object value);
	取值:Object value=request.getAttribute(String name);
	移除值:request.removeAttribute(String name);

6.登录案例以及BeanUtils(重点)

6.1 案例分析

6.2 BeanUtils的使用(重点5)

//3.创建User对象
User loginUser = new User();
//3.2使用BeanUtils封装
try {
    BeanUtils.populate(loginUser,req.getParameterMap());
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

注意:form表单的name属性要和javabean的属性一一对应;

6.3 javabean规范

就是一个标准的java类。
javabean的成员变量和属性的区别:
	成员变量:成员变量都是private修饰的;
	属性:去掉setter和getter方法的set和get部分,将首字母变小写之后就是属性
		setUsername()----->Username----->username;
注意:往往javabean的属性和成员变量是一样,因为getter和setter方法都是idea工具根据成员变量自动生成的。

7.总结

获取虚拟路径: String path=request.getContextPath();
1.获取请求参数:
	String value=request.getParameter(String name); 获取一个name对应一个value值
	String[] values=request.getParameterValues(String name); 获取一个name对应多个value值
	Map<String String[]> map=request.getParameterMap(); 获取所有的请求参数
2. 请求参数中文乱码问题,tomcat8.0之后get请求参数不会乱码
	乱码原因:request缓冲区默认字符集是iso-8859-1,不支持中文
	解决办法:在获取请求参数之前设置缓冲区字符集
	request.setCharacterEncoding("utf-8")3.请求转发实现页面跳转
	api:request.getRequestDispatcher("/不带虚拟路径的路径").forward(request,response);
	特点:
		1.请求转发时一次请求一次响应
		2.请求转发地址栏不会发生变化
		3.请求转发的路径不带虚拟目录,默认只能转发到当前项目;
4.request作为域对象存值、取值、移除值
	作用范围:一次请求范围,从浏览器发送请求开始到服务器作出响应结束;
	创建和销毁时间:浏览器发送请求之后服务器就创建request对象,服务器作出响应之后销毁
	api:
		存值:request.setAttribute(String name,Object value);
		取值:Object value=request.getAttribute(String name);
		移除值:request.removeAttribute(String name);
5.BeanUtils的使用
	BeanUtils.populate(Object javabean对象,request.getParameterMap())
    
6.补充api ,在浏览器页面上相应中文信息
	  //设置编码
       response.setContentType("text/html;charset=utf-8");
       //输出
       response.getWriter().write("登录失败,用户名或密码错误");

day15_Response

1.http协议响应内容

1.响应行:协议版本	状态码	 状态描述
	常见的状态码:(记住)
		200	:响应成功
		302	:重定向,也是页面跳转的一种方式。
		304	:访问缓存
		404	:访问路径不正确
		405	:get请求没有对应的doGet()方法,post请求没有对应的doPost()方法
		500	:服务器端java代码出现异常了
2.响应头:一般是一个key对应一个value,也有一个key对应多个value
	content-type:告诉浏览器响应的内容类型以及采用的字符集
	content-disposition:告诉浏览器以文件下载的形式打开;
	location:告诉浏览器重定向的路径
3.响应空行:分隔响应头和响应体
4.响应体:服务器告诉浏览器展示的内容

2.response对象重定向实现页面跳转(重点1)

1.重定向api
	response.sendRedirect("/带虚拟路径的访问路径");
2.请求转发和重定向的区别?
    1.请求转发是一次请求一次响应,重定向是两个请求和两次响应;
    2.请求转发浏览器地址栏不会发生改变,重定向浏览器地址栏会发生改变
    3.请求转发路径不带虚拟目录,重定向路径要带虚拟目录;
    4.如果跳转前后使用request数据传递,那么只能使用请求转发,否则使用重定向;

注意:如果跳转前后使用request数据传递,那么只能使用请求转发,否则使用重定向;

3.web中页面访问路径问题(重点2)

相对路径:以./或者../开头  ./表示当前路径可以省略不写,../表示上一级目录
	规则:要找到当前页面和要跳转的页面之间的相对位置关系,比较当前页面访问路径和要跳转的页面的访问路径
		例如:
			http://localhost:8080/day15/responseServletDemo1
			http://localhost:8080/day15/responseServletDemo2
			从responseServletDemo1跳转到responseServletDemo2相对路径:./responseServletDemo2;
	暂时不推荐使用相对路径
绝对路径:吐血推荐  以/开头
	客户端路径:客户端浏览器访问服务器的路径就叫客户端路径,例如:form表单的action、a标签、img的src、重定向,需要使用虚拟目录
	服务端路径:服务器内部跳转的路径,请求转发 不需要使用虚拟目录

总结:除了请求转发不需要使用虚拟目录,其他路径都要使用虚拟目录。

4.response响应内容以及中文乱码问题(重点3)

1.响应数据:
	response.getWriter().write("数据");
	response.getWriter().print("数据");

	区别例如:
		    response.getWriter().write(97); //a
             response.getWriter().write("<br>");
             response.getWriter().print(97); //97
2.响应中文乱码问题
	原因:1.response缓冲区字符集是iso-8859-1不支持中文;缓冲区字符集和浏览器采用的字符集不一致;
	解决办法:在获取到流对象之前response.setContentType("text/html;charset=utf-8");
		1.设置了response缓冲区字符集为utf-82.告诉浏览器采用utf-8字符集
  • 验证码换一换功能
//声明refreshCode()
function refreshCode() {
    //向验证码的Servlet发送请求
    document.getElementById("vcode").src="/day15/checkCodeServlet?time="+new Date().getTime();
}

5.ServletContext作为域对象存值、取值、移除值

作用范围:整个web项目
创建和销毁时间:在服务器启动的时候会为每个web项目创建一个ServletContext对象,代表这个web项目;服务器关闭了。
存值、取值、移除值api:
	存值:request.setAttribute(String name,Object value);
	取值:Object value=request.getAttribute(String name);
	移除值:request.removeAttribute(String name);

6.ServletContext对象读取文件IO流路径(重点4)

1.获取文件在服务器中的真实IO流路径:
	String path1=servletContext.getRealPath("/a.txt"); //a.txt在web目录中
	String path2=servletContext.getRealPath("/WEB-INF/b.txt");//b.txt在web/WEB-INF目录里面
	String path3=servletContext.getRealPath("/WEB-INF/classes/c.txt");  //c.txt在src目录中

2.一步到位获取文件输入流
	InputStream is1 = servletContext.getResourceAsStream("/a.txt");
	InputStream is2 = servletContext.getResourceAsStream("/WEB-INF/b.txt");
	InputStream is3 = servletContext.getResourceAsStream("/WEB-INF/classes/c.txt");

	特殊:src中的文件还可以使用类加载器获取
		InputStream is=xxxServlet.getClass().getClassLoader().getResourceAsStream("文件名");

7.response对象实现文件下载

  • 思路分析

文件下载思路.bmp

  • 代码实现

8.补充

  • 多个Servlet使用相同的访问路径异常

1548557196344

9.总结

1.重定向实现页面跳转(重点1)
	response.sendRedirect("/带虚拟目录的路径");
2.请求转发和重定向的区别?
	2.1. 请求转发一次请求一次响应,重定向是两次请求两次响应
	2.2. 请求转发浏览器地址栏不变,重定向浏览器地址栏发生改变
	2.3. 请求转发路径不带虚拟目录,重定向路径带虚拟目录
	2.4. 如果跳转前后使用request进行数据传递,那么只能使用请求转发,否则使用重定向。
3.访问路径问题:使用绝对路径,除了请求转发不需要写虚拟目录,其他路径都要写虚拟目录。(重点24.response对象响应数据以及中文乱码问题(重点3)
	响应数据:
		response.getWriter().write("数据");
	乱码的原因:response缓冲区字符集是iso-8859-1不支持中文,并且缓冲区字符集和浏览器字符集不一致。
	解决办法:在获取输出流之前设置缓冲区字符集以及告诉浏览器采用相同的字符集即可
		response.setContentType("text/html;charset=utf-8");
5.获取文件在服务器中的绝对路径(重点4)
	获取路径:String path=servletContext.getRealPath("/xx"); 默认是获取到web目录在服务器中的绝对路径;
	获取文件输入流:servletContext.getResourceAsStream("/xx");路径和getRealPath路径写法一样
6.文件下载的思路
	1.获取文件名
	2.根据文件名将文件加载进内存,得到InputStream
	3.使用response对象设置头信息:content-type、content-disposition
	4.使用response的字节输出和InputStream两个流对接,写出数据到客户端;

day16_Cookie&Session

1.会话技术-Cookie(客户端技术)

  • 一次会话: 从打开浏览器第一次访问服务器开始建立会话,到浏览器关闭就是一次会话;
  • 会话技术的作用:共享数据
  • 快速入门实现思路
一、在CookieDemo1的Servlet中想客户端发送Cookie
	1.创建Cookie对象:Cookie cookie=new Cookie(String name,String value);
	2.将Cookie通过response对象发送给客户端:response.addCookie(cookie);
二、在CookieDemo2的Servlet中获取客户端发送过来的数据
	1.通过request对象获取所有Cookie: Cookie[] cookies=request.getCookies();
	2.如果Cookie数组不为null,那么就遍历打印Cookie中的name和value值
  • Cookie的实现原理(重点1)

Cookie原理.bm

	Cookie属于客户端技术,当客户端浏览器第一次访问服务器项目时,服务器端创建Cookie对象通过response响应头发送给客户端保存。当客户端浏览器再次访问服务器该项目时,会自动将Cookie以request请求头的形式发送过去,我们在服务器端就可以获取到之前的Cookie,获取到保存的值,从而实现数据共享;
  • Cookie的使用细节
1.一次发送多个Cookie:允许;
2.Cookie的存储时间(掌握)
	1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
	2. 持久化存储:
		cookie.setMaxAge(int seconds) //单位是秒
		1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
		2. 负数:默认值
		3. 零:删除cookie信息
3.Cookie存储中文:可以存储
	在tomcat 8 之前 cookie中不能直接存储中文数据。
		需要将中文数据转码---一般采用URL编码(%E3),URLEncoder
	在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
	注意:我们使用的tomcat8.5.31版本的tomcat发送Cookie不允许存储空格。
4.Cookie的有效路径(了解)
	通过cookie.setPath("/虚拟目录/其他路径")方法设置有效路径
	注意:如果没有调用setPath方法,默认的有效路径是当前Servlet所在的路径,如果当前Servlet是在项目下,那么浏览器访问该项目的任何资源都会将Cookie方法过来
	cookie.setPath("/day15");   	//当浏览器访问day15项目下所有资源都会携带Cookie
	cookie.setPath("/itcast");		//当浏览器访问itcast项目下所有资源都会携带Cookie
	cookie.setPath("/itcast/aaa");	//当浏览器访问itcast项目中aaa以及aaa路径下所有资源都会携带Cookie
  • Cookie的使用场景以及缺点
cookie的应用场景
	记住用户名、网站无登录状态保存设置信息、记住上一次访问时间。
缺点:
	cookie只能存储字符串类型的简单不重要的数据,浏览器保存cookie的数量和大小都有限制;
  • 记住上一次访问时间-案例分析

Cookie案例_记住上次访问时间-详细.bmp

  • CookieUtils工具类
/**
 * 根据指定名称从cookie数组中获取cookie
 */
public class CookieUtils {
    public static Cookie findCookie(Cookie[] cookies,String name){
        if(cookies!=null){
            for (Cookie cookie : cookies) {
                //找到我们要的cookie
                if(cookie.getName().equals(name)){
                    //找到了
                    return cookie;
                }
            }
        }
        //如果Cookie数组为null,第一次访问;如果遍历完了之后还没有进if,那也是第一次访问
        return null;
    }
}
  • 第一次访问时间代码实现
 实现思路:
    1.获取浏览器发送过来的所有Cookie
    2.判断是否是第一次访问,根据cookie的名称找到我们要的Cookie
    3.如果是第一次访问:
        3.1 响应“欢迎第一次访问”
    4.如果不是第一次访问:
        4.1 从cookie中获取上一次访问时间
        4.2 将“上一次访问时间”响应在浏览器上展示
    5.记录本次的访问时间到Cookie中,发送给客户端保存,那么这个时间就是下一次访问要展示的时间。
@WebServlet("/lastVisitServlet")
public class LastVisitServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决响应中文乱码问题
        response.setContentType("text/html;charset=utf-8");
        //1.获取浏览器发送过来的所有Cookie
        Cookie[] cookies = request.getCookies();
        //2.判断是否是第一次访问,根据cookie的名称找到我们要的Cookie
        Cookie cookie = CookieUtils.findCookie(cookies, "lastVisit");
        if (cookie==null) {
            //3.如果是第一次访问:
            //3.1 响应“欢迎第一次访问”
            response.getWriter().write("欢迎老板第一次光临...");
        }else{
            //4.如果不是第一次访问:
            //4.1 从cookie中获取上一次访问时间
            String value = cookie.getValue();//%4E%56%AC
            //解码回去
            value=URLDecoder.decode(value,"utf-8");
            //4.2 将“上一次访问时间”响应在浏览器上展示
            response.getWriter().write("你上一次访问的时间是: "+value);
        }
        //5.记录本次的访问时间到Cookie中,发送给客户端保存,那么这个时间就是下一次访问要展示的时间。
        //5.1 获取系统当前时间并格式化
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String dateStr = sdf.format(new Date());
        //在存储之前对dateStr进行url编码
        dateStr=URLEncoder.encode(dateStr,"utf-8"); //%4E%56%AC
        //5.2 创建Cookie对象,保存当前时间
        Cookie c=new Cookie("lastVisit",dateStr);
        //持久化存储
        c.setMaxAge(60*60*24*7);
        //5.3将Cookie响应个客户端保存
        response.addCookie(c);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

2.jsp本质以及脚本元素

  • jsp的本质:本质是一个Servlet。
  • jsp脚本元素
1. <%  代码 %>:代码片段脚本,比较常用,此处可以定义局部变量,for循环、if判断...
	定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
2. <%! 代码 %>:成员声明脚本,很少用,定义成员变量和成员方法
	定义的java代码,在jsp转换后的java类的成员位置。
3. <%= 代码 %>:输出脚本,比较常用,输出的结果在浏览器页面上
	定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
  • 例如
<%--使用for循环在页面上打印10赵洋贼帅....  脚本元素可以和html混着写--%>
<%
	for (int i = 0; i < 10; i++) {
%>
	<h1>赵洋贼鸡儿帅<%=i%>......</h1>
<%
	}
%>

3.会话技术-Session(服务端技术,重点)

  • session的实现原理(重点2)

	session属于服务端技术,session是依赖于cookie实现。当我们第一次在服务器端调用request.getSession()方法时,服务器会创建session对象,同时生产一个唯一的sessionid,将sessionid保存在cookie中发送给浏览器保存;当浏览器再次访问服务器时会自动将sessionid携带过来,那么服务器端再次调用getSession()方法时就不是创建session对象,而是根据sessionid获取之前的session对象使用。
  • session的使用细节
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
	* 默认情况下。不是。
	* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
		Cookie c = new Cookie("JSESSIONID",session.getId());
         c.setMaxAge(60*60);
         response.addCookie(c);

2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
	* 不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
		* session的钝化:
			* 在服务器正常关闭之前,将session对象系列化到硬盘上
		* session的活化:
			* 在服务器启动后,将session文件转化为内存中的session对象即可。
		
3. session什么时候被销毁?
	1. 服务器关闭
	2. session对象调用invalidate()3. session默认失效时间 30分钟
		选择性配置修改	
		<session-config>
	        <session-timeout>30</session-timeout>
	    </session-config>
  • session作为域对象存值、取值、移除值(重点3)
作用范围:默认是一次会话范围。
创建和销毁时间:
	创建:在服务器端第一次调用request.getSession()方法时创建
	销毁:服务器关闭;手动调用invalidate()方法;默认的30分钟到期了。
api:
	存值:request.setAttribute(String name,Object value);
	取值:Object value=request.getAttribute(String name);
	移除值:request.removeAttribute(String name);

4.总结

  • 什么时候使用Cookie,什么时候使用session?
由于Cookie只能保持字符串并且是不重要的数据,所以通常用来保持用户名、上一次访问时间...而session是服务器端技术,可以保持任意类型的数据,当做域对象使用即可
  • 什么时候使用request,什么时候使用session?
根据作用范围判断,如果是一次请求范围数据共享那么使用request,如果是多次请求范围数据共享,那么使用session。

day17_EL&JSTL

1.jsp的九大内置对象(了解)

  • 记住5个内置对象(4个域对象+response)
pageContext,request,session,application,response
  • pageContext的作用
1.作为域对象存值、取值、移除值
	作用范围:当前jsp页面,离开这个页面就获取不到了。
2.可以获取另外8个内置对象
	pageContext.getRequest(),pageContext.getSession(),......

2.MVC开发模式

  • MVC开发模式(知道3层代表的含义就行了)
概念:mvc要求我们将代码按照功能进行分层;
M:model层,也叫模型层,主要负责操作数据库以及封装结果;一般是普通的java类
V:view层,也叫视图层,主要负责展示结果,一般是jsp或者html页面
C:controller层,也叫控制层,主要负责接收客户端的请求,调用model层获取结果,将结果响应给view层展示;
  • MVC开发模式图

MVC开发模式

3.EL表达式

3.1 EL 表达式的语法和作用

语法:${表达式}
作用:简化jsp页面java代码的书写,代替jsp页面java代码的输出部分;代替<%=表达式%>

3.2 执行运算(了解)

1. 算数运算符: + - * /(div) %(mod)
2. 比较运算符: > < >= <= == !=
3. 逻辑运算符: &&(and) ||(or) !(not)
4. 空运算符: empty
	* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
	* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
	* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0

3.3 EL从域中获取数据(重点1)

语法
    1. ${域范围名称.键名}:从指定域中获取指定键的值
        域范围名称:
            1. pageScope		--> pageContext
            2. requestScope 	--> request
            3. sessionScope 	--> session
            4. applicationScope --> application(ServletContext)
        举例:在request域中存储了name=张三
        获取:${requestScope.name}
    2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
    3.EL表达式获取对象值
    	${域范围名称.键名.属性名},域范围名称可以省略表示从最小域范围获取,本质是调用对象的getter方法,
    4.EL表达式获取list和map集合中的数据
    	list:
    		${域范围名称.键名[索引]},域范围名称可以省略表示从最小域范围获取
		map:
			${域范围名称.键名.map集合的key名称},域范围名称可以省略表示从最小域范围获取
			${域范围名称.键名["map集合的key名称"]},如果map集合中的key有特殊字符,那么就需要使用这种方法,比如map集合中的key有个.或者-;
			例如:map.put("s.name","李四")
                   request.setAttribute("smap",map)
                   必须:${smap["s.name"]}
  • EL内置对象以及empty运算符
empty运算符:判断对象为空或者长度为0,如果是判断非空并且长度>使用 not empty
	${empty list} //list集合为null或者长度为0就返回true
	${not empty list} //list集合不为null并且长度大于0就返回true
三元运算符:${a>b?a:b}
	例如:${empty errorMsg?"请速速上车!":errorMsg}
内置对象:pageContext,获取另外8个内置对象,常见用法:动态获取虚拟路径
	${pageContext.request.contextPath}
  • 注意:jsp内置对象和EL内置对象的区别?(jsp中的pageContext和EL中的pageContext、pageScope的区别;jsp中的request和EL中的requestScope的区别?)

    1.jsp中的pageContext和EL中的pageContext是同一个对象;

    2.jsp中的域对象和EL中的域范围对象不是同一个对象,例如pageContext和pageScope不一样,request和requestScope不一样,requestScope表示的是request域范围不是域对象。requestScope和request是一一对应关系但是不是同一个东西。在jsp中 不能使用requestScope,在EL中不能直接使用request对象,如果要使用request对象,那么可以通过${pageContext.request}来获取

4.JSTL的使用步骤

  • 使用步骤
1.导入开发jar包
2.在jsp页面使用taglib指令引入标签库
	<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.使用标签库中的标签
  • 标签库中常见的标签
if标签:表示判断,相当于java中的if判断
	<c:if test="${判断条件}">
		条件成立的情况...
    </c:if>
choose标签:表示判断,相当于java中的if...else if...else...
    <%
        request.setAttribute("score",158);
    %>
    <c:choose>
        <c:when test="${score>0 && score<60}">
            不及格...
        </c:when>
        <c:when test="${score>=60 && score<=100}">
            及格了...
        </c:when>
        <c:otherwise>
            输入不合法
        </c:otherwise>
    </c:choose>
foreach标签:遍历list集合
	<%
        request.setAttribute("list",list);  //list表示的是list集合,创建list集合代码省略了
    %>
    <c:foreach items="${list}" var="s">  //s表示的是遍历出来的集合中的每一个元素
    	${s}
    </c:foreach>

5.javaEE三层架构

三层架构.bmp

6.案例-用户列表展示

6.1 案例分析

6.2 代码实现

  • 入手点:在index.jsp页面点击“查询所有用户信息”超链接
<a
         href="${pageContext.request.contextPath}/userListServlet" style="text-decoration:none;font-size:33px">查询所有用户信息
</a>
  • UserListServlet代码实现
@WebServlet("/userListServlet")
public class UserListServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.调用UserService完成查询
        UserService service = new UserServiceImpl();
        List<User> users = service.findAll();
        //2.将list存入request域
        request.setAttribute("users",users);
        //3.转发到list.jsp
        request.getRequestDispatcher("/list.jsp").forward(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • UserServiceImpl代码实现
public class UserServiceImpl implements UserService {
    private UserDao dao = new UserDaoImpl();
    @Override
    public List<User> findAll() {
        //调用Dao完成查询
        return dao.findAll();
    }
}
  • UserDaoImpl代码实现
public class UserDaoImpl implements UserDao {
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    @Override
    public List<User> findAll() {
        //使用JDBC操作数据库...
        //1.定义sql
        String sql = "select * from user";
        //2.调用query方法
        List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
        return users;
    }
}
  • list.jsp页面展示所有用户信息
<c:forEach items="${users}" var="user" varStatus="s">
    <tr>
        <td><input type="checkbox" name="uid" value="${user.id}"></td>
        <td>${s.count}</td>
        <td>${user.name}</td>
        <td>${user.gender}</td>
        <td>${user.age}</td>
        <td>${user.address}</td>
        <td>${user.qq}</td>
        <td>${user.email}</td>
        <td><a class="btn btn-default btn-sm" href="">修改</a>&nbsp;
            <a class="btn btn-default btn-sm" href="">删除</a></td>
    </tr>
</c:forEach>

day18_综合练习

1.登录功能

1.1 验证码实现换一换

<script type="text/javascript">
    //切换验证码
    function refreshCode(){
        //1.获取验证码图片对象
        var vcode = document.getElementById("vcode");
        //2.设置其src属性,加时间戳
        vcode.src = "${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
    }
</script>

1.2 登录后台代码实现

  • LoginServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.设置编码
    request.setCharacterEncoding("utf-8");
    //2.获取数据
    //2.1获取用户填写验证码
    String verifycode = request.getParameter("verifycode");
    //3.验证码校验
    HttpSession session = request.getSession();
    String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
    session.removeAttribute("CHECKCODE_SERVER");//确保验证码一次性
    if(checkcode_server!=null && !checkcode_server.equalsIgnoreCase(verifycode)){
        //验证码不正确
        //提示信息
        request.setAttribute("login_msg","验证码错误!");
        //跳转登录页面
        request.getRequestDispatcher("/login.jsp").forward(request,response);
        return;
    }
    //4.封装User对象
    User user = new User();
    try {
        BeanUtils.populate(user,request.getParameterMap());
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    //5.调用Service查询
    UserService service = new UserServiceImpl();
    User loginUser = service.login(user);
    //6.判断是否登录成功
    if(loginUser != null){
        //登录成功
        //将用户存入session
        session.setAttribute("user",loginUser);
        //跳转页面
        response.sendRedirect(request.getContextPath()+"/index.jsp");
    }else{
        //登录失败
        //提示信息
        request.setAttribute("login_msg","用户名或密码错误!");
        //跳转登录页面
        request.getRequestDispatcher("/login.jsp").forward(request,response);
    }
}
  • UserServiceImpl中的login方法
@Override
public User login(User user) {
    return dao.findUserByUsernameAndPassword(user.getUsername(),user.getPassword());
}
  • UserDaoImpl中的findUserByUsernameAndPassword方法
@Override
public User findUserByUsernameAndPassword(String username, String password) {
    try {
        String sql = "select * from user where username = ? and password = ?";
        User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username, password);
        return user;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

2.添加功能

2.1 案例分析

3.添加功能

2.2 代码实现

  • AddUserServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.设置编码
    request.setCharacterEncoding("utf-8");
    //2.获取参数
    Map<String, String[]> map = request.getParameterMap();
    //3.封装对象
    User user = new User();
    try {
        BeanUtils.populate(user,map);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    //4.调用Service保存
    UserService service = new UserServiceImpl();
    service.addUser(user);
    //5.跳转到userListServlet
    response.sendRedirect(request.getContextPath()+"/userListServlet");
}
  • UserServiceImpl的addUser方法实现
@Override
public void addUser(User user) {
    dao.add(user);
}
  • UserDaoImpl的add方法实现
@Override
public void add(User user) {
    //1.定义sql
    String sql = "insert into user values(null,?,?,?,?,?,?,null,null)";
    //2.执行sql
    template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail());
}

3.删除功能

3.1 案例分析

4.删除功

3.2 代码实现

  • 入手点-点击删除后弹出确认框
<a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a>
<!--声明deleteUser方法-->
function deleteUser(id){
    //用户安全提示
    if(confirm("您确定要删除吗?")){
        //访问路径
        location.href="${pageContext.request.contextPath}/delUserServlet?id="+id;
    }
}
  • DelUserServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.获取id
    String id = request.getParameter("id");
    //2.调用service删除
    UserService service = new UserServiceImpl();
    service.deleteUser(id);
    //3.跳转到查询所有Servlet
    response.sendRedirect(request.getContextPath()+"/userListServlet");
}
  • UserServiceImpl中deleteUser代码实现
@Override
public void deleteUser(String id) {
    dao.delete(Integer.parseInt(id));
}
  • UserDaoImpl中delete方法实现
@Override
public void delete(int id) {
    //1.定义sql
    String sql = "delete from user where id = ?";
    //2.执行sql
    template.update(sql, id);
}

4.修改功能

4.1 案例分析

5.修改功能

4.2 根据用户id查询用户信息展示到update.jsp页面

  • 入手点-点击修改按钮,将id发送给服务器
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>
  • FindUserServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.获取id
    String id = request.getParameter("id");
    //2.调用Service查询
    UserService service = new UserServiceImpl();
    User user = service.findUserById(id);
    //3.将user存入request
    request.setAttribute("user",user);
    //4.转发到update.jsp
    request.getRequestDispatcher("/update.jsp").forward(request,response);
}
  • UserServiceImpl中的findUserById方法实现
@Override
public User findUserById(String id) {
    return dao.findById(Integer.parseInt(id));
}
  • UserDaoImpl中findById方法实现
@Override
public User findById(int id) {
    String sql = "select * from user where id = ?";
    return template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id);
}
  • update.jsp页面展示用户信息
<!--  隐藏域 提交id-->
<input type="hidden" name="id" value="${user.id}">
<!--回显性别-->
<div class="form-group">
    <label>性别:</label>
    <input type="radio" name="gender" value="男" ${user.gender == '男'?"checked":""}/>男
    <input type="radio" name="gender" value="女" ${user.gender == '女'?"checked":""}/>女
</div>
<!--回显年龄-->
<div class="form-group">
    <label for="age">年龄:</label>
    <input type="text" class="form-control" value="${user.age}" id="age"  name="age" placeholder="请输入年龄" />
</div>
<!--回显籍贯-->
<select name="address" id="address" class="form-control" >
    <option value="陕西" ${user.address == '陕西'?"selected":""}>陕西</option>
    <option value="北京" ${user.address == '北京'?"selected":""}>北京</option>
    <option value="上海" ${user.address == '上海'?"selected":""}>上海</option>
</select>

4.3 点击提交按钮正式修改用户信息

  • UpdateUserServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.设置编码
    request.setCharacterEncoding("utf-8");
    //3.封装对象
    User user = new User();
    try {
        BeanUtils.populate(user,request.getParameterMap());
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    //4.调用Service修改
    UserService service = new UserServiceImpl();
    service.updateUser(user);
    //5.跳转到查询所有Servlet
    response.sendRedirect(request.getContextPath()+"/userListServlet");
}
  • UserServiceImpl中updateUser方法实现
@Override
public void updateUser(User user) {
    dao.update(user);
}
  • UserDaoImpl实现
@Override
public void update(User user) {
    String sql = "update user set name = ?,gender = ? ,age = ? , address = ? , qq = ?, email = ? where id = ?";
    template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail(), user.getId());
}

5.删除选中功能

5.1 案例分析

6.删除选中功能

5.2 代码实现

  • 在用户列表的table外面包裹form表单来提交选中状态
<form id="form" action="${pageContext.request.contextPath}/delSelectedServlet" method="post">
 table...
</form>
  • 给“删除选中”按钮添加单击事件提交form表单
window.onload = function(){
    //给删除选中按钮添加单击事件
    document.getElementById("delSelected").onclick = function(){
         //表单提交
        document.getElementById("form").submit();
    }
}
  • DelSelectedServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.获取所有id
    String[] ids = request.getParameterValues("uid");
    //2.调用service删除
    UserService service = new UserServiceImpl();
    service.delSelectedUser(ids);
    //3.跳转查询所有Servlet
    response.sendRedirect(request.getContextPath()+"/userListServlet");
}
  • UserServiceImpl中delSelectedUser方法实现
@Override
public void delSelectedUser(String[] ids) {
    if(ids != null && ids.length > 0){
        //1.遍历数组
        for (String id : ids) {
            //2.调用dao删除
            dao.delete(Integer.parseInt(id));
        }
    }
}
  • 前台实现全选和全不选以及弹出警告框(可选)
window.onload = function(){
    //给删除选中按钮添加单击事件
    document.getElementById("delSelected").onclick = function(){
        if(confirm("您确定要删除选中条目吗?")){
            var flag = false;
            //判断是否有选中条目
            var cbs = document.getElementsByName("uid");
            for (var i = 0; i < cbs.length; i++) {
                if(cbs[i].checked){
                    //有一个条目选中了
                    flag = true;
                    break;
                }
            }
            if(flag){//有条目被选中
                //表单提交
                document.getElementById("form").submit();
            }
        }
    }
    //1.获取第一个cb
    document.getElementById("firstCb").onclick = function(){
        //2.获取下边列表中所有的cb
        var cbs = document.getElementsByName("uid");
        //3.遍历
        for (var i = 0; i < cbs.length; i++) {
            //4.设置这些cbs[i]的checked状态 = firstCb.checked
            cbs[i].checked = this.checked;
        }
    }
}

总结

  • web层Servlet中代码思路
1.如果有请求参数,那么第一步就是获取请求参数并封装;
		BeanUtils.populate(javabean,request.getParameterMap())
2.调用service完成操作,获取最终结果:获取所有用户信息,登录、添加用户信息、删除用户信息。。。
3.根据结果,需不需要域对象数据传递,最后页面跳转;
  • service层代码思路
1.创建dao对象:抽取到成员变量了
2.在service层方法中直接调用dao层方法操作数据库
  • dao层代码思路
1.创建JdbcTemplate对象,已经抽取到成员变量了
	private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
2.在dao方法中定义sql
3.调用JdbcTemplate的update、query、queryForObject方法

6.分页查询功能

6.1 案例分析

  • 前后台数据传递

7.分页查询功能

  • 实现思路

7_2.分页查询功能2

6.2 代码实现

  • PageBean类封装结果
public class PageBean<T> {
    private int totalCount; // 总记录数
    private int totalPage ; // 总页码
    private List<T> list ; // 每页的数据
    private int currentPage ; //当前页码
    private int rows;//每页显示的记录数
   // getter、setter、toString方法都省略
}
  • findUserByPageServlet代码实现
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    //1.获取参数
    String currentPage = request.getParameter("currentPage");//当前页码
    String rows = request.getParameter("rows");//每页显示条数
    //给当前页数和每页显示条数赋默认值
    if(currentPage==null||"".equals(currentPage)){
        currentPage="1";
    }
    if(rows==null||"".equals(rows)){
        rows="5";
    }
    //2.调用service查询
    UserService service = new UserServiceImpl();
    PageBean<User> pb = service.findUserByPage(currentPage,rows);

    System.out.println(pb);
    //3.将PageBean存入request
    request.setAttribute("pb",pb);
    //4.转发到list.jsp
    request.getRequestDispatcher("/list.jsp").forward(request,response);
}
  • UserServiceImpl中findUserByPage方法实现
@Override
public PageBean<User> findUserByPage(String _currentPage, String _rows) {

    int currentPage = Integer.parseInt(_currentPage);
    int rows = Integer.parseInt(_rows);
    //1.创建空的PageBean对象
    PageBean<User> pb = new PageBean<User>();
    //2.设置参数
    pb.setCurrentPage(currentPage);
    pb.setRows(rows);
    //3.调用dao查询总记录数
    int totalCount = dao.findTotalCount();
    pb.setTotalCount(totalCount);
    //4.调用dao查询List集合
    //计算开始的记录索引
    int start = (currentPage - 1) * rows;
    List<User> list = dao.findByPage(start,rows);
    pb.setList(list);

    //5.计算总页码
    // int totalPage = (totalCount % rows)  == 0 ? totalCount/rows : (totalCount/rows) + 1;
    int totalPage= (int) Math.ceil(totalCount*1.0/rows);
    pb.setTotalPage(totalPage);
    return pb;
}
  • UserDaoImpl实现
@Override
public int findTotalCount() {  //查询总记录数
    //1.定义sql
    String sql="select count(*) from user";
    //2.调用queryForObject方法
    return template.queryForObject(sql,Integer.class);
}
@Override
public List<User> findByPage(int start, int rows) { //查询当前页用户信息
    //1.定义sql
    String sql="select * from user limit ?,?";
    //2.调用query方法
    return template.query(sql,new BeanPropertyRowMapper<User>(User.class),start,rows);
}
  • 前台展示用户信息和分页条信息
<form id="form" action="${pageContext.request.contextPath}/delSelectedServlet" method="post">
    <table border="1" class="table table-bordered table-hover">
        <tr class="success">
            <th><input type="checkbox" id="firstCb"></th>
            <th>编号</th>
            <th>姓名</th>
            <th>性别</th>
            <th>年龄</th>
            <th>籍贯</th>
            <th>QQ</th>
            <th>邮箱</th>
            <th>操作</th>
        </tr>
        
        <c:forEach items="${pb.list}" var="user" varStatus="s">
            <tr>
                <td><input type="checkbox" name="uid" value="${user.id}"></td>
                <td>${s.count}</td>
                <td>${user.name}</td>
                <td>${user.gender}</td>
                <td>${user.age}</td>
                <td>${user.address}</td>
                <td>${user.qq}</td>
                <td>${user.email}</td>
                <td><a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>&nbsp;
                    <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a></td>
            </tr>
        </c:forEach>
    </table>
</form>
<!--分页条信息-->
<div>
    <nav>
        <ul class="pagination">
            <%--上一页--%>
            <c:if test="${pb.currentPage==1}">
                <li class="disabled">
                    <a href="javascript:void(0)" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
            </c:if>
            <c:if test="${pb.currentPage!=1}">
                <li>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pb.currentPage-1}&rows=5" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>
            </c:if>
            <%--页码--%>
            <c:forEach begin="1" end="${pb.totalPage}" var="i" step="1">
                <li ${i==pb.currentPage?"class='active'":""}><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5">${i}</a></li>
            </c:forEach>
            <%--下一页--%>
            <c:if test="${pb.currentPage==pb.totalPage}">
                <li class="disabled">
                    <a href="javascript:void(0)" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            </c:if>
            <c:if test="${pb.currentPage!=pb.totalPage}">
                <li>
                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pb.currentPage+1}&rows=5" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>
            </c:if>
            <span style="font-size: 25px;margin-left: 5px;">
                共${pb.totalCount}条记录,共${pb.totalPage}页
            </span>
        </ul>
    </nav>
</div>

7.复杂条件查询功能

7.1 案例分析

7.2 代码实现

  • findUserByPageServlet获取查询条件并传递给service
//获取查询条件
Map<String, String[]> condition = request.getParameterMap();

//2.调用service查询
UserService service = new UserServiceImpl();
PageBean<User> pb = service.findUserByPage(currentPage,rows,condition);
  • UserServiceImpl中将查询条件传递给dao的两个方法
//3.调用dao查询总记录数
int totalCount = dao.findTotalCount(condition);
pb.setTotalCount(totalCount);
//4.调用dao查询List集合
//计算开始的记录索引
int start = (currentPage - 1) * rows;
List<User> list = dao.findByPage(start,rows,condition);
pb.setList(list);
  • 核心–UserDaoImpl中带条件查询总记录数据
@Override
public int findTotalCount(Map<String, String[]> condition) {
    //1.定义模板初始化sql
    String sql = "select count(*) from user where 1 = 1 ";
    StringBuilder sb = new StringBuilder(sql);
    //2.遍历map
    Set<String> keySet = condition.keySet();
    //定义参数的集合
    List<Object> params = new ArrayList<Object>();
    for (String key : keySet) {
        //排除分页条件参数
        if("currentPage".equals(key) || "rows".equals(key)){
            continue;
        }
        //获取value
        String value = condition.get(key)[0];
        //判断value是否有值
        if(value != null && !"".equals(value)){
            //有值
            sb.append(" and "+key+" like ? ");
            params.add("%"+value+"%");//?条件的值
        }
    }
    return template.queryForObject(sb.toString(),Integer.class,params.toArray());
}
  • 核心–UserDaoImpl中带条件查询当前页数据
@Override
public List<User> findByPage(int start, int rows, Map<String, String[]> condition) {
    String sql = "select * from user  where 1 = 1 ";
    StringBuilder sb = new StringBuilder(sql);
    //2.遍历map
    Set<String> keySet = condition.keySet();
    //定义参数的集合
    List<Object> params = new ArrayList<Object>();
    for (String key : keySet) {
        //排除分页条件参数
        if("currentPage".equals(key) || "rows".equals(key)){
            continue;
        }
        //获取value
        String value = condition.get(key)[0];
        //判断value是否有值
        if(value != null && !"".equals(value)){
            //有值
            sb.append(" and "+key+" like ? ");
            params.add("%"+value+"%");//?条件的值
        }
    }
    //添加分页查询
    sb.append(" limit ?,? ");
    //添加分页查询参数值
    params.add(start);
    params.add(rows);
    //打印结果
    System.out.println(sb.toString());
    System.out.println(params);
    return template.query(sb.toString(),new BeanPropertyRowMapper<User>(User.class),params.toArray());
}
  • 查询条件回显
1. 在findUserByPageServlet中将查询条件存储到request域中
	//3.将PageBean存入request
    request.setAttribute("pb",pb);
    request.setAttribute("condition",condition);
    //4.转发到list.jsp
    request.getRequestDispatcher("/list.jsp").forward(request,response);
2.在list.jsp页面表单中回显查询条件,核心是value="${condition.name[0]}"
<form class="form-inline" action="${pageContext.request.contextPath}/findUserByPageServlet" method="post">
    <div class="form-group">
        <label for="exampleInputName2">姓名</label>
        <input type="text" name="name" value="${condition.name[0]}" class="form-control" id="exampleInputName2" >
    </div>
    <div class="form-group">
        <label for="exampleInputName3">籍贯</label>
        <input type="text" name="address" value="${condition.address[0]}" class="form-control" id="exampleInputName3" >
    </div>

    <div class="form-group">
        <label for="exampleInputEmail2">邮箱</label>
        <input type="text" name="email" value="${condition.email[0]}" class="form-control" id="exampleInputEmail2"  >
    </div>
    <button type="submit" class="btn btn-default">查询</button>
</form>
  • 点击分页条带条件查询
1.以页码为例,上一页和下一页同理:在rows=5后面拼接查询条件
<li ${i==pb.currentPage?"class='active'":""}><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${i}</a></li>

day19_Filter&Listener

1.过滤器的概念和入门案例

  • 入门案例
@WebFilter("/*")
public class FilterDemo1 implements Filter {
    public void destroy() {}
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("拦截到了请求...");
        //放行
        chain.doFilter(req, resp);
    }
    public void init(FilterConfig config) throws ServletException {}
}
  • 修改Filter模板

5.修改Filter模板.bmp

2.Filter过滤器的相关配置

2.1.web.xml配置Filter过滤器(了解)

<filter>
    <filter-name>demo1</filter-name>
    <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
    <filter-name>demo1</filter-name>
    <!-- 拦截路径 -->
    <url-pattern>/*</url-pattern>
</filter-mapping>

2.2.过滤器的执行流程和生命周期(会描述)

  • 执行流程
	当过滤器拦截到请求之后,先执行放行(chain.doFilter(req, resp))上面的代码,放行之后请求到达目标资源,执行目标资源中的代码,目标资源做出响应之后,响应会被过滤器再次拦截,最后执行放行下面的代码。
  • 生命周期
	当服务器启动的时候,会创建Filter对象,执行init方法,只执行一次,一般用于加载资源文件;每次拦截到请求之后执行doFilter方法;doFilter方法中经过判断之后决定是否放行;最后当服务器正常关闭时执行distory方法,只执行一次,一般用于释放资源。

2.3.过滤器的url-pattern配置:拦截路径(重点1)

1.完全路径匹配:以/开头,不包含通配符*  例如:/servletDemo1  只有当访问servletDemo1时过滤器才会拦截
2.目录匹配:以/开头,以*结尾;在浏览器访问时*表示任意字符  例如:/abc/*  /*  (常用)
3.扩展名匹配:以*开头,以固定的后缀名结尾  例如  *.jsp  *.abc   但是/abc/*.do错误 

2.4.过滤器拦截方式配置(重点2)

@WebFilter(urlPatterns = "/*",dispatcherTypes ={DispatcherType.REQUEST,DispatcherType.FORWARD} )
DispatcherType.REQUEST:默认值,表示拦截浏览器直接访问的请求
DispatcherType.FORWARD:表示连接转发的请求

3.过滤器案例

3.1.案例1:登录验证

  • 案例分析

  • 代码实现
@WebFilter(value = "/jsp/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class LoginFilter implements Filter {
    public void destroy() {
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request= (HttpServletRequest) req;
        //1.从session中获取用户信息
        Object user = request.getSession().getAttribute("user");
        //2.判断user是否为空
        if(user==null){
            //没有登录,保存错误信息,跳转到登录页面
            request.setAttribute("login_msg","您还没登录,无权访问!");
            request.getRequestDispatcher("/login.jsp").forward(request,resp);
        }else{
            //已经登录了,放行
            chain.doFilter(req, resp);
        }
    }
    public void init(FilterConfig config) throws ServletException {}
}

3.2.案例2:统一解决请求和响应中文乱码问题

  • 代码实现
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    //1.解决请求和响应中文乱码问题
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    //放行
    chain.doFilter(req, resp);
}

3.3.案例3:过滤敏感词汇

  • 案例需求

  • 动态代理模式图

  • 动态代理代码示例
//这个测试类就相当于调用者,在这里面调用代理对象的方法,由代理对象调用目标对象的方法
public class ProxyTest {
    public static void main(String[] args) {
        //1.创建目标对象
        Lenovo lenovo=new Lenovo();
        //2.创建代理对象
        /**
         * ClassLoader loader,类加载器:用于生成代理对象的Class对象;
           Class<?>[] interfaces,接口的Class对象:规定代理对象要实现和目标对象相同的接口,保证功能一直;
           InvocationHandler h,接口:只要调用代理对象的方法,InvocationHandler的invoke方法就执行,
         我们可以在这个方法中对目标对象的方法进行增强
            返回值:就是代理对象
         */
        ClassLoader loader = lenovo.getClass().getClassLoader();
        Class<?>[] interfaces = lenovo.getClass().getInterfaces();
        SaleComputer proxyObj = (SaleComputer) Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {
            /**
             * @param proxy 表示代理对象
             * @param method 表示代理对象调用的方法对象
             * @param args  表示代理对象调用方法传的参数
             * @return 将结果进一步返回给代理对象调用的方法
             * @throws Throwable
             */
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
                //找目标对象
                // String computer = lenovo.sale(5000);
                String computer= (String) method.invoke(lenovo,args);
                //替换敏感词汇“联想”,用"华为"代替
                if(computer.contains("联想")){
                    computer = computer.replace("联想", "华为");
                }
                return computer+",送鼠标垫,送垃圾键盘";
            }
        });
        //3.调用代理对象的方法
        String computer = proxyObj.sale(8000);
        System.out.println("computer = " + computer);
    }
}
  • 案例代码实现
@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.创建代理对象,增强getParameter方法
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强getParameter方法
                //判断是否是getParameter方法
                if(method.getName().equals("getParameter")){
                    //增强返回值
                    //获取返回值
                    String value = (String) method.invoke(req,args);//你是笨蛋
                    if(value != null){
                        for (String str : list) {
                            if(value.contains(str)){
                                //包含敏感词汇,那么就替换成***
                                value = value.replaceAll(str,"***");
                            }
                        }
                    }
                    return  value;
                }
                return method.invoke(req,args);
            }
        });
        //2.放行
        chain.doFilter(proxy_req, resp);
    }
    private String[] list = new String(){"笨蛋","坏蛋"};//敏感词汇集合
    public void init(FilterConfig config) throws ServletException {}
    public void destroy() {}
}

4.监听器

  • 监听器的实现步骤
1.创建一个类实现监听器接口,实现抽象方法
public class MyListener implements ServletContextListener {
    /**
     * 当ServletContext被创建的时候调用
     * @param sce
     */
    public void contextInitialized(ServletContextEvent sce) {}
    /**
     * 当ServletContext被销毁的时候调用
     * @param sce
     */
    public void contextDestroyed(ServletContextEvent sce) {}
}
2.配置
	2.1 在类上面添加@WebListener注解
	2.2 在web.xml中配置(了解)
	<listener>
        <listener-class>cn.itcast.web.listener.MyListener</listener-class>
    </listener>

day20_JQuery基础

1.jquery概念和快速入门

  • jquery概念:是一个js框架,封装了js代码,本质是一个js文件,简化我们js代码的书写。
  • 使用步骤
1.将jquery文件复制到项目中,在需要的html引入js文件
	<script src="js/jquery-3.3.1.min.js"></script>
2.使用jquery提供的函数;

2.jQuery核心函数(重点)

2.1 jquery核心函数:$():参数值不一样作用就不一样

  • $(匿名函数):页面加载完成事件
$(function(){
    //当页面加载完成之后,匿名函数会执行
});
  • $(html/js对象)
如果传递的是html代码:创建html代码对应的标签元素对象(可以包含子元素)
	例如:$("<div><p>Hello</p></div>").appendTo("body");//动态创建一个 div 元素(以及其中的所有内容),并将它追加到 body 元素中
如果传递的是js对象:将js对象转换成jquery对象
	 js -- > jq : $(js对象)
  • $(“selector”):传递css选择器,用于根据css选择器获取询元素对象
$("p"):获取所有的p元素;
$("#pid"):获取id="pid"的元素

2.2. jquery对象和js对象相互转换(重点)

js对象:使用document.getElementByxxx获取的对象都是js对象;
jquery对象:我们自己使用$()函数获取对象都是jquery对象,jquery对象也是js对象的一个包装对象;

js对象和jquery对象之间的关系类型于java中String和StringBuilder的关系?
	js对象相当于String对象,jquery对象相当于StringBuilder;String和StringBuilder可以相互转换,但是方法不能混着调用;同理js对象和jquery对象也可以相互转换,但是各自的方法不能相互调用;
    jq -- > js : jq对象[索引] 或者 jq对象.get(索引),如果jquery对象不是数组,那么索引值就是0;
    js -- > jq : $(js对象)

3.jQuery事件绑定以及样式控制(重点)

3.1 常见的事件(重点)

0.页面加载完成事件
    $(function(){
		//当页面加载完成之后,匿名函数会执行
    });
1.单击事件
    jquery对象.click(function(){
		//当元素被单击之后,匿名函数就会执行
    })
	使用代码触发单击事件:jquery对象.click(); //触发之后上述的匿名函数就执行
2.失去焦点事件
	jquery对象.blur(function(){
		//当元素失去焦点之后,匿名函数就会执行
    })
3.表单提交事件
    $("form").submit( function () {
      return false; //return true表示运行提交,return false表示阻止提交,但是不写默认提交
    });

3.2 样式控制

css函数:既可以或者样式值,还可以设置样式值;
	获取样式值:var value=jquery元素对象.css("属性名");
    设置样式值:
    	jquery对象.css("属性名","属性值"); //设置一组样式值;
		$("p").css({"属性名": "属性值", "属性名": "属性值" });//设置多组样式值;
	说明:{"属性名": "属性值", "属性名": "属性值"}在js中称为对象;

3.3 补充:js自定义对象

1.方式1:构造声明对象  了解
	//1.1 声明
     function User(name,score){
            this.name=name;//声明属性并赋值
            this.score=score;
            this.show=function(){
                alert(name+"考了"+score+", shut up");
            }
        }
        //1.2 创建对象
        var user=new User("陈天宇","6");
        console.info(user.name);
        console.info(user.score);
        //对象创建完成之后还可以声明属性并赋值
        user.age=20;
        console.info(user.age);
        //调用show方法
        user.show();
2.方式2:直接量方式  格式: {属性名:属性值,属性名:属性值,.....}
        var person = {
            "name": "陈天宇很2",
            "score": 6,
            "show":function () {
                alert(this.name+"考了"+this.score+", shut up");
            }
        };

4.jQuery选择器

1. 基本选择器(掌握)
	1. 标签选择器(元素选择器)
		* 语法: $("html标签名") 获得所有匹配标签名称的元素
	2. id选择器 
		* 语法: $("#id的属性值") 获得与指定id属性值匹配的元素
	3. 类选择器
		* 语法: $(".class的属性值") 获得与指定的class属性值匹配的元素
	4. 并集选择器:
		* 语法: $("选择器1,选择器2....") 获取多个选择器选中的所有元素
2. 层级选择器
	1. 后代选择器
		* 语法: $("A B ") 选择A元素内部的所有B元素		
	2. 子选择器
		* 语法: $("A > B") 选择A元素内部的所有B子元素
3. 属性选择器
	1. 属性名称选择器 
		* 语法: $("A[属性名]") 包含指定属性的选择器
	2. 属性选择器
		* 语法: $("A[属性名='值']") 包含指定属性等于指定值的选择器
	3. 复合属性选择器
		* 语法: $("A[属性名='值'][]...") 包含多个属性条件的选择器
4. 过滤选择器
	1. 首元素选择器 
		* 语法: :first 获得选择的元素中的第一个元素
	2. 尾元素选择器 
		* 语法: :last 获得选择的元素中的最后一个元素
	3. 非元素选择器
		* 语法: :not(selector) 不包括指定内容的元素
	4. 偶数选择器
		* 语法: :even 偶数,从 0 开始计数
	5. 奇数选择器
		* 语法: :odd 奇数,从 0 开始计数
	6. 等于索引选择器
		* 语法: :eq(index) 指定索引元素
	7. 大于索引选择器 
		* 语法: :gt(index) 大于指定索引元素
	8. 小于索引选择器 
		* 语法: :lt(index) 小于指定索引元素
	9. 标题选择器
		* 语法: :header 获得标题(h1~h6)元素,固定写法
5. 表单过滤选择器
	1. 可用元素选择器 
		* 语法: :enabled 获得可用元素
	2. 不可用元素选择器 
		* 语法: :disabled 获得不可用元素
	3. 选中选择器 
		* 语法: :checked 获得单选/复选框选中的元素
	4. 选中选择器 
		* 语法: :selected 获得下拉框选中的元素

5.jQuery的DOM操作

5.1 内容操作

1. html(): 获取/设置元素的标签体内容   <a><font>内容</font></a>  --> <font>内容</font>
	不传参:获取内容体html代码;
    传参:设置内容体html代码
2. text(): 获取/设置元素的标签体纯文本内容   <a><font>内容</font></a> --> 内容
3. val(): 获取/设置元素的value属性值

5.2 属性设置

1. attr(): 获取/设置元素的属性
	获取属性值:	var value=jquery对象.attr("属性名")
	设置属性:
    	jquery对象.attr("属性名","属性值");//设置一组属性
		jquery对象.attr({ "属性名": "属性值","属性名": "属性值",... });
2. removeAttr():删除属性
3. prop():获取/设置元素的属性
4. removeProp():删除属性

注意:如果操作的是checked、selected、disable等状态属性,使用prop()方法,操作其他属性使用attr()方法

5.3 class属性设置

1. addClass():添加class属性值
2. removeClass():删除class属性值
3. toggleClass():切换class属性
    * toggleClass("one"): 
    * 判断如果元素对象上存在class="one",则将属性值one删除掉。  如果元素对象上不存在class="one",则添加

5.4 CRUD操作

1.追加子元素也叫添加子元素
	父元素.append(子元素/html代码)//在父元素内容后面追加子元素
    子元素.appendTo(父元素)//子元素添加到父元素内部后面
2.删除元素
	被删除元素.remove();
3.清空所有子元素
	父元素.empty();

6.jQuery案例

6.1 隔行换色

<script>
    //需求:将数据行的奇数行背景色设置为 pink,偶数行背景色设置为 yellow
    $(function () {
        //1. 获取数据行的奇数行的tr,设置背景色为pink
        $("tr:gt(1):odd").css("backgroundColor","pink");
        //2. 获取数据行的偶数行的tr,设置背景色为yellow
        $("tr:gt(1):even").css("backgroundColor","yellow");
    });
</script>

6.2 全选和全不选

<script>
    //分析:需要保证下边的选中状态和第一个复选框的选中状态一致即可
    function selectAll(obj){
        //获取下边的复选框
        $(".itemSelect").prop("checked",obj.checked);
    }
</script>

6.3 QQ表情选择

<script>
    //需求:点击qq表情,将其追加到发言框中
    $(function () {
        //1.给img图片添加onclick事件
        $("ul img").click(function () {
            //2.追加到p标签中即可。
            $(".word").append($(this).clone());
        });
    });
</script>

6.4 下拉列表中条目左右移动

<script>
    //需求:实现下拉列表选中条目左右选择功能
    $(function () {
        //toRight
        $("#toRight").click(function () {
            //获取右边的下拉列表对象,append(左边下拉列表选中的option)
            $("#rightName").append($("#leftName>option:selected"));
        });
        //toLeft
        $("#toLeft").click(function () {
            //appendTo   获取右边选中的option,将其移动到左边下拉列表中
            $("#rightName > option:selected").appendTo($("#leftName"));
        });
    });
</script>

7.总结

1.jquery核心函数:$();
	$(function(){}) //入口函数,页面加载完成之后执行匿名函数
	$(html/js对象)$(html):创建html代码对应的元素对象;
        $(js对象):将js对象转换成jquery对象;
     $("css选择器"):根据css选择器获取指定元素对象;
2.jquery对象和js对象相互转换
	js对象:通常通过document.getElementByxxx获取的元素,this也是js对象
	jquery对象:通常通过$()获取到的对象,也可以看成是js对象的包装对象;
	js对象转换成jquery对象:var jquery对象=$(js对象)
    jquery对象转换成js对象:var js对象=jquery对象[索引]var js对象=jquery对象.get(索引);
3.jquery常用事件绑定
	入口函数:
    	$(funtion(){
      
      	});
	单击事件:
        jquery对象.click(function(){

        });
	失去焦点事件:
    	jquery对象.blur(function(){

        });
	表单提交事件
    	jquery对象.submit(function(){
			return true/false;
        });
4.DOM操作常用方法
	4.1 操作内容体:
    	html()方法
        	不传参:获取内容体html代码
        	传参:设置内容体html代码
         text()方法:(了解,很少用)
         	不传参:获取内容体纯文本字符串
        	传参:设置内容体纯文本字符串
         val()方法:
         	不传参:获取表单的value属性
        	传参:设置表单的value属性
    4.2 操作属性:
    	attr():获取/设置元素的属性
	    removeAttr(name):移除元素的属性
        prop():获取/设置元素的属性
		removeProp(name):移除元素的属性
        注意:当操作的是元素的选中或者是否可用等状态属性(checked、selected、disabled)时,使用prop方法,操作其他属性使用attr方法
        
        addClass():添加属性值
        removeClass():移除属性值
        toggleClass(name):切换属性,有属性就移除,没有属性就添加
    4.3 操作样式:
    	css():获取/设置样式值
		获取:css("属性名");
        设置:
        	css("属性名","属性值");
			css({"属性名":"属性值","属性名":"属性值",...});
    4.4 CRUD操作:
           添加元素:
                 父元素.append(子元素/html);
                 子元素.appendTo(父元素);
           删除元素:
                 要删除的元素.remove();
           清空元素:
                 父元素.empty();

day21_jQuery高级&ajax&json

1.jquery动画(了解)

动画api.png

2.jquery遍历(重点)

2.1 fori遍历(重点)

for(var i=0;i<数组对象.length;i++){ //快捷键:itar+回车
    
}
//方式1.for(初始化值;循环结束条件;步长)
var citys = $("#city>li");
for (var i = 0; i < citys.length; i++) {
    //输出到浏览器控制台
    console.info(citys[i].innerHTML);
}

2.2 each()遍历(了解)

jquery数组对象.each(function(index,element){//参数都是可选的
    //每次遍历都会执行匿名函数,index表示遍历的索引,element表示遍历出来的元素,想当this,都是js对象
    return true/false//根据需求返回true或者false,返回true想当continue,返回false相当于break;
});
例如:
	var citys = $("#city>li");
 	citys.each(function (index,element) {
         console.info($(this).html());
     })
$.each(数组对象,function(index,element){//参数都是可选的
  //每次遍历都会执行匿名函数,index表示遍历的索引,element表示遍历出来的元素,想当于this,都是js对象
    return true/false//根据需求返回true或者false,返回true想当continue,返回false相当于break;
})
例如:
	var citys = $("#city>li");
	$.each(citys,function (index,element) {
       	console.info($(this).html());
     })

2.3 for…of增强for循环遍历(重点)

for (let obj of citys) { //快捷键:iter+回车
    //let关键字和var类似,用于声明变量
    //obj是遍历出来的每一个元素,是一个js对象
    console.info(obj.innerHTML)
}

3.jquery事件绑定

//1.使用on给按钮绑定单击事件  click
$("#btn").on("click",function () {
    alert("我被点击了。。。")
}) ;

//2. 使用off解除btn按钮的单击事件
$("#btn2").click(function () {
    //解除btn按钮的单击事件
    //$("#btn").off("click");
    $("#btn").off();//将组件上的所有事件全部解绑
});

4.jquery案例

  • 广告的显示和隐藏
<script>
    /*
            需求:
                1. 当页面加载完,3秒后。自动显示广告
                2. 广告显示5秒后,自动消失。

            分析:
                1. 使用定时器来完成。setTimeout (执行一次定时器)
                2. 分析发现JQuery的显示和隐藏动画效果其实就是控制display
                3. 使用  show/hide方法来完成广告的显示
         */

    //入口函数,在页面加载完成之后,定义定时器,调用这两个方法
    $(function () {
        //定义定时器,调用adShow方法 3秒后执行一次
        setTimeout("adShow();",3000);//传递字符串表示要执行的js代码
        //定义定时器,调用adHide方法,8秒后执行一次
        setTimeout(adHide,8000);//传递函数对象,表示8s之后要执行的函数
    });
    //显示广告
    function adShow() {
        //获取广告div,调用显示方法
        $("#ad").show("slow");
    }
    //隐藏广告
    function adHide() {
        //获取广告div,调用隐藏方法
        $("#ad").hide("slow");
    }
</script>
  • 抽奖
<script language='javascript' type='text/javascript'>
    /*
            分析:
                1. 给开始按钮绑定单击事件
                    1.1 定义循环定时器
                    1.2 切换小相框的src属性
                        * 定义数组,存放图片资源路径
                        * 生成随机数。数组索引
                2. 给结束按钮绑定单击事件
                    1.1 停止定时器
                    1.2 给大相框设置src属性
         */
    var imgs = ["../img/man00.jpg",
                "../img/man01.jpg",
                "../img/man02.jpg",
                "../img/man03.jpg",
                "../img/man04.jpg",
                "../img/man05.jpg",
                "../img/man06.jpg",
               ];
    var startId;//开始定时器的id
    var index;//随机角标
    $(function () {
        //处理按钮是否可以使用的效果
        $("#startID").prop("disabled",false);
        $("#stopID").prop("disabled",true);

        //1. 给开始按钮绑定单击事件
        $("#startID").click(function () {
            //处理按钮是否可以使用的效果
            $("#startID").prop("disabled",true);
            $("#stopID").prop("disabled",false);
            // 1.1 定义循环定时器 20毫秒执行一次
            startId = setInterval(function () {
                //1.2生成随机角标 0-6
                index = Math.floor(Math.random() * 7);//0.000--0.999 --> * 7 --> 0.0-----6.9999
                //1.3设置小相框的src属性
                $("#img1ID").attr("src",imgs[index]);
            },50);
        });
        //2. 给结束按钮绑定单击事件
        $("#stopID").click(function () {
            //处理按钮是否可以使用的效果
            $("#startID").prop("disabled",false);
            $("#stopID").prop("disabled",true);
            // 1.1 停止定时器
            clearInterval(startId);
            // 1.2 给大相框设置src属性
            $("#img2ID").attr("src",imgs[index]).hide();
            //显示1秒之后
            $("#img2ID").show(1000);
        });
    });
</script>

5.ajax概念以及ajax实现方式

5.1 概念

Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术

5.2 jquery 的ajax操作

  • $.ajax()方式
$.ajax({
    url:"./ajaxServlet",//请求路径
    // data:"username="+username,
    data:{"username":username},//请求参数
    type:"post",//请求方式
    dataType:"text",//响应的数据类型
    success:function (data) { //响应成功的回调函数
        // alert(data);
    }
});
  • $.get()和$.post()方式(绝对重点)
格式:
    $.get(url,param,function(data){//响应成功的回调函数
		url:请求路径
        param:请求参数,可有可无。写法:name=value&name=value&...或者{name:value,name:value,...}
        data:响应回来的数据
        type:期望响应回来的数据类型
    },type);
	$.post(url,param,function(data){//响应成功的回调函数
	    url:请求路径
        param:请求参数,可有可无。写法:name=value&name=value&...或者{name:value,name:value,...}
        data:响应回来的数据
        type:期望响应回来的数据类型
    },type);
例如:
    $.get("ajaxServlet",{"username":"赵洋"},function (data) {
        alert(data);
    },"text");
	$.post("ajaxServlet",{"username":"赵洋"},function (data) {
        alert(data);
    },"text");

6.json的概念以及语法

  • json数据格式

json数据格式.bmp

7.json和java对象之间相互转换

  • java对象转换成json数据(绝对重点)
0.导入开发jar包,有31.创建ObjectMapper对象:		ObjectMapper mapper=new ObjectMapper();
2.调用writeValueAsString方法:	String json = mapper.writeValueAsString(javabean/list/map);
3.将json响应给客户端:	response.getWriter.write(json)
    
或者:

1.创建ObjectMapper对象:		ObjectMapper mapper=new ObjectMapper();
2.将java对象转换成json通过流响应给客户端:
	mapper.writeValue(response.getWriter(),javabean/list/map);

8.案例–校验用户名是否可用

8.1 前台发送异步请求以及处理json

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册页面</title>
        <script src="js/jquery-3.3.1.min.js"></script>
        <script>
            //在页面加载完成后
            $(function () {
                //给username绑定blur事件
                $("#username").blur(function () {
                    //获取username文本输入框的值
                    var username = $(this).val();
                    //发送ajax请求
                    //期望服务器响应回的数据格式:{"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
                    //                         {"userExsit":false,"msg":"用户名可用"}
                    $.get("findUserServlet",{username:username},function (data) {
                        //判断userExsit键的值是否是true
                        // alert(data);
                        var span = $("#s_username");
                        if(data.userExsit){
                            //用户名存在
                            span.css("color","red");
                            span.html(data.msg);
                        }else{
                            //用户名不存在
                            span.css("color","green");
                            span.html(data.msg);
                        }
                    },"json");

                }); 
            });
        </script>
    </head>
    <body>
        <form>
            <input type="text" id="username" name="username" placeholder="请输入用户名">
            <span id="s_username"></span>
            <br>
            <input type="password" name="password" placeholder="请输入密码"><br>
            <input type="submit" value="注册"><br>
        </form>
    </body>
</html>

8.2 后台处理请求并且响应json

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.获取用户名
    String username = request.getParameter("username");
    //2.调用service层判断用户名是否存在
    //期望服务器响应回的数据格式:{"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
    //                         {"userExsit":false,"msg":"用户名可用"}
    //设置响应的数据格式为json
    response.setContentType("application/json;charset=utf-8");
    Map<String,Object> map = new HashMap<String,Object>();
    if("tom".equals(username)){
        //存在
        map.put("userExsit",true);
        map.put("msg","此用户名太受欢迎,请更换一个");
    }else{
        //不存在
        map.put("userExsit",false);
        map.put("msg","用户名可用");
    }
    //将map转为json,并且传递给客户端
    //将map转为json
    ObjectMapper mapper = new ObjectMapper();
    //并且传递给客户端
    mapper.writeValue(response.getWriter(),map);
}

补充:

  • 当使用ajax发送异步请求时,页面跳转不能使用请求转发或者重定向,因为ajax发送的任何请求都不会重新加载当前页面。如果想页面跳转,那么只能在前端使用js的location对象的href属性实现页面跳转;
  • json字符串中不能使用单引号
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值