①.Web概述
1. web概念概述
JavaWeb:使用Java语言开发基于互联网的项目
软件架构:
1. C/S: Client/Server 客户端/服务器端
* 在用户本地有一个客户端程序,在远程有一个服务器端程序
* 如:QQ,迅雷...
* 优点:
1. 用户体验好
2. 安全性比较好
* 缺点:
1. 开发、安装,部署,维护 麻烦
2. B/S: Browser/Server 浏览器/服务器端
* 只需要一个浏览器,用户通过不同的网址(URL),客户访问不同的服务器端程序
* 优点:
1. 开发、安装,部署,维护 简单
* 缺点:
1. 如果应用过大,用户的体验可能会受到影响
2. 安全性较差
2.web服务器软件
- 服务器:安装了服务器软件的计算机
- 服务器软件:接收用户的请求,处理请求,做出响应
- web服务器软件:接收用户的请求,处理请求,做出响应。
在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目web容器
②.Tomcat
1. Tomcat:web服务器软件
1. 下载:http://tomcat.apache.org/
2. 安装:解压压缩包即可。
* 注意:安装目录建议不要有中文和空格
3. 卸载:删除目录就行了
4. 启动:
* bin/startup.bat ,双击运行该文件即可
* 访问:浏览器输入:http://localhost:8080 回车访问自己
http://别人的ip:8080 访问别人
2. tomcat启动问题分析
一般tomcat的默认端口号是:8080
Http默认的端口号是:80
* 可能遇到的问题: 1. 黑窗口一闪而过: * 原因: 没有正确配置JAVA_HOME环境变量 * 解决方案:正确配置JAVA_HOME环境变量 2. 启动报错: 1. 暴力:找到占用的端口号,并且找到对应的进程,杀死该进程 * netstat -ano 2. 温柔:修改自身的端口号 * conf/server.xml * <Connector port="8888" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8445" /> * 一般会将tomcat的默认端口号修改为80。80端口号是http协议的默认端口号。 * 好处:在访问时,就不用输入端口号
3. tomcat 的关闭
①.正常关闭:(1).bin/shutdown.bat (2) ctrl+c [ 推荐 ]
②.强制关闭:点击启动窗口的×
4. 部署项目方式
* 部署项目的方式: 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文件的名称[浏览器访问的地址]
5. 静态目录和动态目录
//访问首页 <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>
6. Tomcat的目录结构 [ 重点 ]
(1)bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat6.exe、tomcat6w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要先配置JAVA_HOME环境变量才能启动,shutdawn.bat用来停止Tomcat;
(2)conf:这是一个非常非常重要的目录,这个目录下有四个最为重要的文件:
a. server.xml:配置整个服务器信息。例如修改端口号,添加虚拟主机等;下面会详细介绍这个文件;
b. tomcatusers.xml:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;
c. web.xml:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。MIME就是用来说明文档的内容是什么类型的!
d. context.xml:对所有应用的统一配置,通常我们不会去配置它。
(3)lib:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享之,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的Jar包了,所以建议只把Tomcat需要的Jar包放到这个目录下;
(4)logs:这个目录中都是日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,那么异常也会记录在日志文件中。
(5)temp:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!
(6)webapps:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的。项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。http://localhost:8080/examples,进入示例项目。其中examples就是项目名,即文件夹的名字。
(7)work:运行时生成的文件,最终运行的文件都在这里。通过webapps中的项目生成的!可以把这个目录下的内容删除,再次运行时会生再次生成work目录。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。
(8)LICENSE:许可证。
(9)NOTICE:说明文件。
③. Servlet
1. servlet 基础知识
1>.什么是Servlet
Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
①. 接收请求数据;②. 处理请求;③. 完成响应
2>. 实现Servlet的方式(由我们自己来写!)
实现javax.servlet.Servlet接口;
继承javax.servlet.GenericServlet类[ 这是一个抽象类, 父类是Servlet ];
继承javax.servlet.http.HttpServlet类 [ 父类是GenericServlet ];
通常我们会去继承HttpServlet类来完成我们的Servlet,但学习Servlet还要从javax.servlet.Servlet接口开始学习。
2. Servlet
1>. Servlet的源码分析
执行原理: 1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径 2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。 3. 如果有,则在找到对应的<servlet-class>全类名 4. tomcat会将字节码文件加载进内存,并且创建其对象
2>. Servlet的生命周期
所谓xxx的生命周期,就是说xxx的出生、服务,以及死亡。Servlet生命周期也是如此!与Servlet的生命周期相关的方法有:
①. void init(ServletConfig config);
②. void service(ServletRequest,ServletResponse);
③. void destroy();
(1)servlet的出生
服务器会在Servlet第一次被访问时创建Servlet,或者是在服务器启动时创建Servlet。如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置。也就是说默认情况下,Servlet是在第一次被访问时由服务器创建的。
而且一个Servlet类型,服务器只创建一个实例对象,例如在我们首次访问时,服务器通过“/helloworld”找到了绑定的Servlet名称为cn.itcast.servlet.HelloServlet,然后服务器查看这个类型的Servlet是否已经创建过,如果没有创建过,那么服务器才会通过反射来创建HelloServlet的实例。当我们再次访问时,服务器就不会再次创建HelloServlet实例了,而是直接使用上次创建的实例。
在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。请记住, Servlet出生后马上就会调用init()方法,而且一个Servlet的一生。这个方法只会被调用一次。这好比小孩子出生后马上就要去剪脐带一样,而且剪脐带一生只有一次。
我们可以把一些对Servlet的初始化工作放到init方法中!
(2)Servlet服务
当服务器每次接收到请求时,都会去调用Servlet的service()方法来处理请求。服务器接收到一次请求,就会调用service() 方法一次,所以service()方法是会被调用多次的。正因为如此,所以我们才需要把处理请求的代码写到service()方法中!
(3)Servlet的离去
Servlet是不会轻易离去的,通常都是在服务器关闭时Servlet才会离去!在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servlet的destroy()方法,我们可以把Servlet的临终遗言放到destroy()方法中,例如对某些资源的释放等代码放到destroy()方法中。
在首次访问HelloServlet时,init方法会被执行,而且也会执行service方法。再次访问时,只会执行service方法,不再执行init方法。在关闭Tomcat时会调用destroy方法
3>. ServletConfig
ServletConfig对象对应web.xml文件中的元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!
String getServletName():获取Servlet在web.xml文件中的配置名称,即指定的名称;
ServletContext getServletContext():用来获取ServletContext对象,ServletContext会在后面讲解;
String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
3. GenericServlet(抽象类)
将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象;将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
1>. GenericServlet类的源码分析
GenericServlet是Servlet接口的实现类,我们可以通过继承GenericServlet来编写自己的Servlet。下面是GenericServlet类的源代码
2>. GenericServlet的init( )方法
①. 在GenericServlet中,定义了一个ServletConfig config实例变量,并在init(ServletConfig)方法中把参数ServletConfig赋给了实例变量。然后在该类的很多方法中使用了实例变量config
②. 如果子类覆盖了GenericServlet的init(StringConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,那么去覆盖GenericServlet提供的init()方法,它是没有参数的init()方法,它会在init(ServletConfig)方法中被调用
3>. 实现了ServletConfig接口
GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。
4. HttpServlet [ 掌握 ]
1>. HttpServlet概述
HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。
(1) HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,
这个方法是HttpServlet自己的方法,不是从Servlet继承来的。在HttpServlet的
service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法,这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)方法即可,这就不用自己去
强转请求和响应对象了。
(2)其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)方法,因为HttpServlet还要做另一步简化操作,下面会介绍。
2>. doGet()和doPost()
①. 在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可
②. 如果只重写了doGet( )或doPost( ),当我们访问这个路径的时候,servlet中没有对应的doGet()或dopost的时候会抛出405
5. servet细节
1>.Servlet与线程安全
* Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
* 多个用户同时访问时,可能存在线程安全问题。
* 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
2>. 让服务器在启动时就创建Servlet
默认情况下,服务器会在某个Servlet第一次收到请求时创建它。也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。
在servlet元素中配置load-on-startup元素可以让服务器在启动时就创建该Servlet,其中load-on-startup元素的值必须是大于等于的整数,它的使用是服务器启动时创建Servlet的顺序。上例中,根据load-on-startup的值可以得知服务器创建Servlet的顺序为Hello1Servlet、Hello2Servlet、Hello3Servlet。
* 在<servlet>标签下配置 1. 第一次被访问时,创建 * <load-on-startup>的值为负数 2. 在服务器启动时,创建 * <load-on-startup>的值为0或正整数
3>.url-pattern
1. urlpartten:Servlet访问路径 1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"}) 注意:如果只配置一个那么{ }可以省略 2. 路径定义规则: 1. /xxx:路径匹配 2. /xxx/xxx:多层路径,目录结构 3. *.do:扩展名匹配(*不能配置多个 *不能配置在中间) 注意: 如果一个servlet配置了/*,他会将所有的jsp、html等静态资源都拦截掉 2. / 和 /* 的区别 / 不会拦截 xx.jsp /* 会拦截所有的包括xx.jsp在内
①. 可以在servlet-mapping中给出多个url-pattern,例如:
那么这说明一个Servlet绑定了两个URL,无论访问/AServlet还是/BServlet,访问的都是AServlet
②. 还可以在 url-pattern 中使用通配符,所谓通配符就是星号“*”,星号可以匹配任何URL前缀或后缀,使用通配符可以命名一个Servlet绑定一组URL,例如:
请注意,通配符要么为前缀,要么为后缀,不能出现在URL中间位置,也不能只有通配符。例如:/*.do就是错误的,因为星号出现在URL的中间位置上了。*.*也是不对的,因为一个URL中最多只能出现一个通配符。
④. ServletContext
6. ServletContext
1>.ServletContext概述
ServletContext对象的作用是在整个Web应用的动态资源之间共享数据!例如在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了
①. 服务器会为每个应用创建一个ServletContext对象:
②. ServletContext对象的创建是在服务器启动时完成的;
③. ServletContext对象的销毁是在服务器关闭时完成的。
2>. 获取ServletContext
①.在Servlet中获取ServletContext对象: public class MyServlet implements Servlet { public void init(ServletConfig config) { ServletContext context = config.getServletContext(); } … }
②.在GenericeServlet或HttpServlet中获取ServletContext对象:
public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) { ServletContext context = this.getServletContext(); } }
③. 通过request对象来调用方法获取
ServletContext context1=request.getServletContext( );
④. 通过监听器中获取
public void contextInitialized(ServletContextEvent servletContextEvent) { //加载资源文件 //1.获取ServletContext对象 ServletContext servletContext = servletContextEvent.getServletContext();
3>. 域对象的功能
所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:
①. void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同
②. Object getAttribute(String name):用来获取ServletContext中的数据,当前在获取之前需要先去存储才行,例如:String value = (String)servletContext.getAttribute(“xxx”);,获取名为xxx的域属性;
③. void removeAttribute(String name):用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
4>. 获取MIME类型
①. MIME类型:在互联网通信过程中定义的一种文本数据类型
②. 格式: 大类型/小类型 text/html image/jpeg
③. 获取:String getMimeType(String file)
//定义一个图片路径 String filename="a.jpg"; //2.获取ServletContext对象 ServletContext app = this.getServletContext(); //3.获取Mime类型 String mimeType = app.getMimeType(filename); System.out.println(mimeType);//image/jpeg
5>. 获取文件的真实(服务器)路径
方法:String getRealPath(String path)
⑤. 请求Http
1.Http的概述
概念:Hyper Text Transfer Protocol 超文本传输协议(传输协议:定义了,客户端和服务器端通信时,发送数据的格式)
2. 特点
①. 基于TCP/IP的高级协议
②. 默认端口号:80[www.baidu.com:80]
③. 基于请求/响应模型的:一次请求对应一次响应
④. 无状态的:每次请求之间相互独立,不能交互数据
3. 请求消息数据格式
1>. 请求行
请求方式 请求url 请求协议/版本(GET /login.html HTTP/1.1) //掌握 * 请求方式: * HTTP协议有7中请求方式,常用的有2种 * GET: 1. 请求参数在请求行中,在url后。 2. 请求的url长度有限制的 3. 不太安全 * POST: 1. 请求参数在请求体中 2. 请求的url长度没有限制的 3. 相对安全
2>. 请求头
请求头:客户端浏览器告诉服务器一些信息(格式:请求头名称: 请求头值)
常见的请求头:
(1).User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息(可以在服务器端获取该头的信息,解决浏览器的兼容性问题)
(2).Referer:http://localhost/login.html* 告诉服务器,我(当前请求)从哪里来?
* 作用:
1. 防盗链:
2. 统计工作:
3>.请求空行
空行,就是用于分割POST请求的请求头,和请求体的。
4>. 请求体(正文):
封装POST请求消息的请求参数的
⑥. request
1. request原理 和 response对象的原理
①. request和response对象是由服务器创建的。我们来使用它们
②. request对象是来获取请求消息,response对象是来设置响应消息
2.Request 继承体系
3. Request的方法
1>. 获取请求行数据
GET /day14/demo1?name=zhangsan HTTP/1.1
①. String getMethod( ) : 获取请求方式 :GET
②. String getContextPath( ) :获取虚拟目录:/day14
③. String getServletPath( ) : 获取Servlet路径: /demo1
④. String getQueryString( ) : 获取get方式请求参数:name=zhangsan
⑤. String getRequestURI( ): 获取请求URI:/day14/demo1
⑥. StringBuffer getRequestURL( ) :http://localhost/day14/demo1
区别:
URL:统一资源定位符 : http://localhost/day14/demo1 中华人民共和国
URI:统一资源标识符 : /day14/demo1 共和国(范围大)
⑦. String getProtocol( ):获取协议及版本:HTTP/1.1
⑧. String getRemoteAddr( ):获取客户机的IP地址:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* 1. 获取请求方式 :GET * String getMethod() 2. (*)获取虚拟目录:/day14 * String getContextPath() 3. 获取Servlet路径: /requestDemo1 * String getServletPath() 4. 获取get方式请求参数:name=zhangsan * String getQueryString() 5. (*)获取请求URI:/day14/demo1 * String getRequestURI(): /day14/requestDemo1 * StringBuffer getRequestURL() :http://localhost/day14/requestDemo1 6. 获取协议及版本:HTTP/1.1 * String getProtocol() 7. 获取客户机的IP地址: * String getRemoteAddr() */ //1. 获取请求方式 :GET String method = request.getMethod(); System.out.println(method); //2.(*)获取虚拟目录:/day14 String contextPath = request.getContextPath(); System.out.println(contextPath); //3. 获取Servlet路径: /demo1 String servletPath = request.getServletPath(); System.out.println(servletPath); //4. 获取get方式请求参数:name=zhangsan String queryString = request.getQueryString(); System.out.println(queryString); //5.(*)获取请求URI:/day14/demo1 String requestURI = request.getRequestURI(); StringBuffer requestURL = request.getRequestURL(); System.out.println(requestURI); System.out.println(requestURL); //6. 获取协议及版本:HTTP/1.1 String protocol = request.getProtocol(); System.out.println(protocol); //7. 获取客户机的IP地址: String remoteAddr = request.getRemoteAddr(); System.out.println(remoteAddr); }
2>. 获取请求头数据
①. String getHeader(String name):通过请求头的名称获取请求头的值
②. Enumeration<String> getHeaderNames( ):获取所有的请求头名称
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //演示获取请求头数据 //1.获取所有请求头名称 Enumeration<String> headerNames = request.getHeaderNames(); //2.遍历 while(headerNames.hasMoreElements()){ String name = headerNames.nextElement(); //根据名称获取请求头的值 String value = request.getHeader(name); System.out.println(name+"---"+value); } }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //演示获取请求头数据:user-agent String agent = request.getHeader("user-agent"); //判断agent的浏览器版本 if(agent.contains("Chrome")){ //谷歌 System.out.println("谷歌来了..."); }else if(agent.contains("Firefox")){ //火狐 System.out.println("火狐来了..."); } } }
3>. 获取请求体数据
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
①. BufferedReader getReader():获取字符输入流,只能操作字符数据
②. ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据 ( 在文件上传知识点后讲解 )
4>. 其他功能 ( 掌握 )
1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
①. String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
②. String[ ] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game
③. Enumeration getParameterNames( ):获取所有请求的参数名称
④. Map<String,String[ ]> getParameterMap( ):获取所有参数的map集合
* 中文乱码问题: * get方式:tomcat 8 已经将get方式乱码问题解决了 * post方式:会乱码 * 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //post 获取请求参数 //根据参数名称获取参数值 String username = request.getParameter("username"); /* System.out.println("post"); System.out.println(username);*/ //根据参数名称获取参数值的数组 String[] hobbies = request.getParameterValues("hobby"); /*for (String hobby : hobbies) { System.out.println(hobby); }*/ //获取所有请求的参数名称 Enumeration<String> parameterNames = request.getParameterNames(); /*while(parameterNames.hasMoreElements()){ String name = parameterNames.nextElement(); System.out.println(name); //如果是复选框选中多个,只能获取一个值 String value = request.getParameter(name); System.out.println(value); System.out.println("----------------"); }*/ // 获取所有参数的map集合 Map<String, String[]> parameterMap = request.getParameterMap(); //遍历 Set<String> keyset = parameterMap.keySet(); for (String name : keyset) { //获取键获取值 String[] values = parameterMap.get(name); System.out.println(name); for (String value : values) { System.out.println(value); } System.out.println("-----------------"); }
2. 请求转发:一种在服务器内部的资源跳转方式
①. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
②. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
特点:
1. 浏览器地址栏路径不发生变化
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request共享数据
3. 域对象(共享数据)
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
①. void setAttribute(String name,Object obj):存储数据
②. Object getAttitude(String name):通过键获取值
③. void removeAttribute(String name):通过键移除键值对
4.获取ServletContext
ServletContext getServletContext( )
4. 登录案列
1>.需求:
* 用户登录案例需求:
1.编写login.html登录页面
username & password 两个输入框
2.使用Druid数据库连接池技术,操作mysql,day14数据库中user表
3.使用JdbcTemplate技术封装JDBC
4.登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
5.登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
2>.开发步骤
1. 创建项目,导入html页面,配置文件,jar包 2. 创建数据库环境 CREATE DATABASE day14; USE day14; CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) UNIQUE NOT NULL, PASSWORD VARCHAR(32) NOT NULL ); 3. 创建包cn.itcast.domain,创建类User package cn.itcast.domain; /** * 用户的实体类 */ public class User { private int id; private String username; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
3>. 创建包cn.itcast.util,编写工具类JDBCUtils
/** * JDBC工具类 使用Durid连接池 */ public class JDBCUtils { private static DataSource ds ; static { try { //1.加载配置文件 Properties pro = new Properties(); //使用ClassLoader加载配置文件,获取字节输入流 InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); //2.初始化连接池对象 ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接池对象 */ public static DataSource getDataSource(){ return ds; } /** * 获取连接Connection对象 */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } }
4>. 创建包cn.itcast.dao,创建类UserDao,提供login方法
/** * 操作数据库中User表的类 */ public class UserDao { //声明JDBCTemplate对象共用 private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); /** * 登录方法 * @param loginUser 只有用户名和密码 * @return user包含用户全部数据,没有查询到,返回null */ public User login(User loginUser){ try { //1.编写sql String sql = "select * from user where username = ? and password = ?"; //2.调用query方法 User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword()); return user; } catch (DataAccessException e) { e.printStackTrace();//记录日志 return null; } } }
5>. 编写cn.itcast.web.servlet.LoginServlet类
@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.设置编码 req.setCharacterEncoding("utf-8"); //2.获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); //3.封装user对象 User loginUser = new User(); loginUser.setUsername(username); loginUser.setPassword(password); //4.调用UserDao的login方法 UserDao dao = new UserDao(); User user = dao.login(loginUser); //5.判断user if(user == null){ //登录失败 req.getRequestDispatcher("/failServlet").forward(req,resp); }else{ //登录成功 //存储数据 req.setAttribute("user",user); //转发 req.getRequestDispatcher("/successServlet").forward(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
6>.登录成功或失败
@WebServlet("/successServlet") public class SuccessServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取request域中共享的user对象 User user = (User) request.getAttribute("user"); if(user != null){ //给页面写一句话 //设置编码 response.setContentType("text/html;charset=utf-8"); //输出 response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您"); } } @WebServlet("/failServlet") public class FailServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //给页面写一句话 //设置编码 response.setContentType("text/html;charset=utf-8"); //输出 response.getWriter().write("登录失败,用户名或密码错误"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
5. BeanUtils工具类,简化数据封装
作用:用于封装JavaBean的
1>. JavaBean:标准的Java类
1. 要求:
1. 类必须被public修饰
2. 必须提供空参的构造器
3. 成员变量必须使用private修饰
4. 提供公共setter和getter方法
2. 功能:封装数据
2>. 概念:
成员变量:
属性:setter和getter方法截取后的产物
例如:getUsername() --> Username–> username
3>. 方法:
①. void setProperty(Object bean, String name, Object value ):操作的是属性,不是成员变量
②. String getProperty(Object bean, String name )
③. void populate(Object obj , Map map):将map集合的键值对信息,封装到对应的JavaBean对象中
关于热部署问题:一定要记得debug模式才生效
⑦.响应HTTP
1. HTTP响应消息
* 响应字符串格式 //请求行 HTTP/1.1 200 OK //请求头 Content-Type: text/html;charset=UTF-8 Content-Length: 101 Date: Wed, 06 Jun 2018 07:08:42 GMT //请求空行 //请求体 <html> <head> <title>$Title$</title> </head> <body> hello , response </body> </html>
2.响应行
HTTP/1.1 200 OK
1.组成 :协议/版本 响应状态码 状态码描述
2.响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
1. 状态码都是3位数字
2. 分类:
1. 1xx:服务器接收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
2. 2xx:成功。代表:200
3. 3xx:重定向。代表:302(重定向),304(访问缓存)
4. 4xx:客户端错误。
* 代表:
* 404(请求路径没有对应的资源)
* 405:请求方式没有对应的doXxx方法
5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
3.响应头
响应头
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Wed, 06 Jun 2018 07:08:42 GMT
1. 格式:头名称: 值
2. 常见的响应头:
1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* 值:
* in-line:默认值,在当前页面内打开
* attachment;filename=xxx:以附件形式打开响应体。文件下载
4.响应空行
5.响应体
传输的数据