静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。html
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不一样时间点访问web页面看到的内容各不相同。前端
静态web资源开发技术:HTML、CSS、JavaScript。java
动态web资源开发技术:JSP/Servlet、ASP、PHP等。在Java中,动态web资源开发技术统称为Java Web。mysql
ASP:微软,国内最先流行的是ASP,在HTML中嵌入了VB的脚本,ASP+COM,维护成本高。web
PHP:开发速度很快,功能很强大,跨平台,代码简单,可是没法承载大访问量的状况(局限性)。sql
JSP/Servlet:sun公司主推的B/S架构,基于java语言,能够承载三高问题(高并发,高可用,高性能)。数据库
B/S:浏览器和服务器;C/S:客户端和服务器。apache
服务器用来处理用户的一些请求,响应给用户一些数据。编程
IIS:微软的,主要用于ASP,Windows中自带的服务器。后端
Tomcat:Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范老是能在Tomcat 中获得体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。由于Tomcat 技术先进、性能稳定,并且免费,于是深受Java 爱好者的喜好并获得了部分软件开发商的承认,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是不少的场合下被广泛使用,是开发和调试JSP 程序的首选。对于一个JavWeb初学者来讲,是最好的选择。
Tomcat 实际上运行JSP 页面和Servlet。
安装Tomcat:官网下载(http://tomcat.apache.org/)压缩包,解压至指定目录(可选:配置环境变量)。
在bin目录下点击startup.bat启动,在浏览器网址栏输入localhost:8080测试。
网站是如何进行访问的:
Http(超文本传输协议):http是一个简单的请求-响应协议,它一般运行在TCP之上。(默认端口:80)
Https:443
Http请求
百度为例:
Request URL: https://www.baidu.com/ 请求地址 Request Method: GET 请求方法 Status Code: 200 OK 状态码 Remote Address: 180.101.49.11:443 远程地址 Referrer Policy: no-referrer-when-downgrade
Http响应
百度响应:
Cache-Control: private 缓存控制 Connection: keep-alive 保持链接 Content-Encoding: gzip 编码 Content-Type: text/html;charset=utf-8 类型
请求方式:
get:请求可以携带的参数比较少,大小有限制,会在浏览器地址栏显示参数的内容,不安全,可是高效。
post:请求可以携带的参数没有限制,大小没有限制,不会再浏览器地址栏显示参数的内容,安全,但不高效。
响应状态码:
200:请求响应成功
3**:请求重定向
404:找不到资源
500:服务器代码错误,502:网关错误
Maven:项目架构管理工具,自动导入jar包(约定大于配置)。
下载Maven后解压,配置环境变量,将bin目录的路径配置到path中,在cmd中输入mvn-version,查看是否配置成功
在conf目录下setting的
在conf目录下setting的
<!-- 设置阿里云镜像--> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>https://maven.aliyun.com/repository/public/</url> </mirror>
pom.xml:maven的核心配置文件
因为maven的约定大于配置,咱们以后写的配置文件可能没法导出或者没法生效,就须要在maven配置下面配置resouce。
servlet就是sun公司开发动态web的一门技术,sun公司在API中提供了一个接口叫Servlet,若是须要开发一个Servlet程序,须要编写一个类去实现Servlet接口,再把开发好的java类部署到web服务器中。
sun公司有两个Servlet接口的默认实现类:HttpServlet和GenericServlet
构建一个maven项目,删除里面的src项目,之后就直接新建model,这个空的工程就是Maven的主工程。
关于Maven父子工程的理解:
父项目中会有
<modules> <module>servlet-01</module> </modules>
子项目中有
<parent> <artifactId>javaweb-02-servlet</artifactId> <groupId>com.zr</groupId> <version>1.0-SNAPSHOT</version> </parent>
Maven环境优化:修改web.xml为最新的,将Maven的结构搭建完整。
编写一个普通类,实现Servlet接口,继承HttpServlet。
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //ServletOutputStream outputStream = resp.getOutputStream(); PrintWriter writer = resp.getWriter(); //响应流 writer.println("Hello Servlet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<!--注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.zr.servlet.HelloServlet</servlet-class> </servlet> <!--Servlet请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
Servlet是由Web服务器调用,web服务器收到请求后,会:
一个Servlet能够指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
一个Servlet能够指定多个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping>
一个Servlet能够指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
默认请求
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
一个Servlet能够指定一些后缀或者前缀映射路径
<!--*前面不能加任何映射的路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.zzr</url-pattern> </servlet-mapping>
优先级问题:
指定了固有的映射路径,优先级最高,找不到就会走默认的处理请求。
处理404页面
<!--404--> <servlet> <servlet-name>error</servlet-name> <servlet-class>com.zr.servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
web容器在启动的时候,它会为每个web程序都建立一个ServletContext对象,它表明了当前的 web应用。
共享数据
我在这个Servle中保存的数据能够在另一个Servle中拿到
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("hello"); //this.getInitParameter(); 初始化参数 //this.getServletConfig(); Servlet的配置 //this.getServletContext(); Servlet上下文 ServletContext context = this.getServletContext(); String username = "周周"; context.setAttribute("username",username);//将一个数据保存在ServletContext中 } }
public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String username = (String) context.getAttribute("username"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html"); resp.getWriter().println("名字:"+username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.zr.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet> <servlet-name>get</servlet-name> <servlet-class>com.zr.servlet.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>get</servlet-name> <url-pattern>/get</url-pattern> </servlet-mapping>
测试访问结果
获取初始化参数
<!--配置一个web应用的初始化参数--> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/mybaits</param-value> </context-param> <servlet> <servlet-name>gp</servlet-name> <servlet-class>com.zr.servlet.ServletDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>gp</servlet-name> <url-pattern>/gp</url-pattern> </servlet-mapping>
public class ServletDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); resp.getWriter().println(url); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
请求转发
public class ServletDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径 requestDispatcher.forward(req,resp);//转发 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>sd4</servlet-name> <servlet-class>com.zr.servlet.ServletDemo04</servlet-class> </servlet> <servlet-mapping> <servlet-name>sd4</servlet-name> <url-pattern>/sd4</url-pattern> </servlet-mapping>
读取资源文件
properties
发现都被打包到了target下的class目录下,咱们称这个路径为类路径classpath。
public class ServletDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Properties properties = new Properties(); properties.load(is); String username = properties.getProperty("username"); String password = properties.getProperty("password"); resp.getWriter().println("username:"+username); resp.getWriter().println("password:"+password); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<servlet> <servlet-name>sd5</servlet-name> <servlet-class>com.zr.servlet.ServletDemo05</servlet-class> </servlet> <servlet-mapping> <servlet-name>sd5</servlet-name> <url-pattern>/sd5</url-pattern> </servlet-mapping>
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>**/*.properties</exclude> <exclude>**/*.xml</exclude> </excludes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
//文件 db.properties username=root password=123456
web服务器接收到客户端的http请求,针对这个请求,分别建立一个表明请求的HttpServletRequest对象,表明响应一个HttpServletResponse。
简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException; PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1); void setContentLength(int var1); void setContentLengthLong(long var1); void setContentType(String var1); void setDateHeader(String var1, long var2); void addDateHeader(String var1, long var2); void setHeader(String var1, String var2); void addHeader(String var1, String var2); void setIntHeader(String var1, int var2); void addIntHeader(String var1, int var2);
响应的状态码
int SC_OK = 200; ... int SC_MULTIPLE_CHOICES = 300; int SC_BAD_REQUEST = 400; int SC_UNAUTHORIZED = 401; int SC_PAYMENT_REQUIRED = 402; int SC_FORBIDDEN = 403; int SC_NOT_FOUND = 404; ... int SC_INTERNAL_SERVER_ERROR = 500; int SC_BAD_GATEWAY = 502;
向浏览器输出消息
下载文件
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 获取下载文件的路径 String realPath = "D:\\IDEACode\\javaweb-02-servlet\\response\\src\\main\\resources\\1.PNG"; System.out.println("下载文件的路径:"+realPath); //2. 下载的文件名 String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); //3. 让浏览器支持下载咱们须要的东西 resp.setHeader("Content-Disposition","attachment;filename="+fileName); //4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5. 建立缓冲区 int len = 0; byte[] buffer = new byte[1024]; //6. 得到OutputStream对象 ServletOutputStream out = resp.getOutputStream(); //7. 将FileOutputStream流写入到buffer缓冲区 将OutputStream缓冲区中的对象输出到客户端 while ((len=in.read(buffer))>0){ out.write(buffer,0,len); } in.close(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
如何生成验证码:
public class ImageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //让浏览器5秒刷新一次 resp.setHeader("refresh","5"); //建立图片 BufferedImage image = new BufferedImage(300,60,BufferedImage.TYPE_INT_RGB); //获得图片 Graphics g = image.getGraphics(); //笔 //设置图片的背景颜色 g.setColor(Color.green); g.fillRect(0,0,300,60); //给图片写数据 g.setColor(Color.magenta); g.setFont(new Font(null,Font.BOLD,70)); g.drawString(makeNum(),0,60); //浏览器以图片的形式打开 resp.setContentType("image/png"); //网站存在缓存。不让浏览器缓存 resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache"); //把图片显示出来 boolean write = ImageIO.write(image,"jpg",resp.getOutputStream()); } //生成随机数 private String makeNum(){ Random random = new Random(); String num = random.nextInt(9999999) + ""; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 7-num.length(); i++) { sb.append("0"); } num = sb.toString()+num; return num; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<!--注册Servlet--> <servlet> <servlet-name>image</servlet-name> <servlet-class>com.zr.servlet.ImageServlet</servlet-class> </servlet> <!--Servlet请求路径--> <servlet-mapping> <servlet-name>image</servlet-name> <url-pattern>/image</url-pattern> </servlet-mapping>
void sendRedirect(String var1) throws IOException;//重定向
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* resp.setHeader("Location","/r/image"); resp.setStatus(302); */ resp.sendRedirect("/r/image"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
配置web.xml测试
重定向和转发的区别:
相同点:页面都会发生跳转
不一样点:
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h2>Hello World!</h2> <%--提交的路径须要寻找到当前项目的路径--%> <form action="${pageContext.request.contextPath}/login" method="post"> 用户名:<input type="text" name="username"><br> 密码 :<input type="password" name="password"><br> <input type="submit"> </form> </body> </html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>success</h1> </body> </html>
public class RequestTest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入这个请求了"); String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println("username:"+username); System.out.println("password:"+password); resp.sendRedirect("/r/success.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<!--注册Servlet--> <servlet> <servlet-name>test</servlet-name> <servlet-class>com.zr.servlet.RequestTest</servlet-class> </servlet> <!--Servlet请求路径--> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>
HttpServletRequest表明客户端的请求,用户经过http协议访问服务器,http请求中的全部的信息会被封装到HttpServletRequest,经过这个HttpServletRequest的方法,得到客户端的全部信息。
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbys = req.getParameterValues("hobbys"); System.out.println("=================================="); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbys)); //请求转发 //这里的/表明当前的web应用 req.getRequestDispatcher("/success.jsp").forward(req,resp); } }
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登陆</title> </head> <body> <h1>登陆</h1> <div style="text-align: center"> <form action="${pageContext.request.contextPath}/login" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> 爱好: <input type="checkbox" name="hobbys" value="唱歌">唱歌 <input type="checkbox" name="hobbys" value="女孩">女孩 <input type="checkbox" name="hobbys" value="写字">写字 <input type="checkbox" name="hobbys" value="代码">代码 <br> <input type="submit"> </form> </div> </body> </html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登陆成功</h1> </body> </html>
web.xml
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.zr.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>
cookie
session
常见应用:网站登陆一次后,下次能够直接进入。
从请求中拿到cookie信息
服务器响应给客户端cookie
//保存用户上一次访问的时间 public class CookieDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决中文乱码 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out= resp.getWriter(); //cookie,服务器端从客户端获取 Cookie[] cookies = req.getCookies();//返回数组,cookie可能存在多个 //判断cookie是否存在 if (cookies!=null){ //若是存在 out.write("你上一次访问的时间是:"); for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; //获取cookie的名字 if (cookie.getName().equals("lastlogintime")){ //获取cookie中的值 long lastlogintime = Long.parseLong(cookie.getValue()); Date date = new Date(lastlogintime); out.write(date.toLocaleString()); } } }else{ out.write("这是你第一次访问本站!"); } //服务器给客户端发一个cookie Cookie cookie = new Cookie("lastlogintime", System.currentTimeMillis()+""); //有效期为1天 cookie.setMaxAge(24*60*60); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
web.xml
<servlet> <servlet-name>CookieDemo01</servlet-name> <servlet-class>com.zr.servlet.CookieDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>CookieDemo01</servlet-name> <url-pattern>/c1</url-pattern> </servlet-mapping>
cookie:通常会保存在本地的用户目录下appdata;
删除cookie
session:
服务器会给每个用户(浏览器)建立一个session对象
一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
用户登陆以后,整个网站均可以访问,-->保存用户的信息
session和cookie的区别:
session保存数据
package com.zr.pojo; public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
public class SessionDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决中文乱码 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //获得session HttpSession session = req.getSession(); //给session存东西 session.setAttribute("name",new Person("周周",1)); //得到session的id String id = session.getId(); //判断session是否是新建立的 if(session.isNew()){ resp.getWriter().write("session建立成功,ID:"+ id); }else { resp.getWriter().write("session已经存在,ID:"+ id); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
public class SessionDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决中文乱码 req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //获得session的数据 HttpSession session = req.getSession(); Person person = (Person) session.getAttribute("name"); System.out.println(person); } @Overridejava protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<servlet> <servlet-name>SessionDemo01</servlet-name> <servlet-class>com.zr.servlet.SessionDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo01</servlet-name> <url-pattern>/s1</url-pattern> </servlet-mapping> <servlet> <servlet-name>SessionDemo02</servlet-name> <servlet-class>com.zr.servlet.SessionDemo02</servlet-class> </servlet> <servlet-mapping> <servlet-name>SessionDemo02</servlet-name> <url-pattern>/s2</url-pattern> </servlet-mapping>
session手动注销
public class SessionDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.removeAttribute("name"); //手动注销session session.invalidate(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
session自动注销
<!--设置session注销时间--> <session-config> <!--1分钟后自动失效--> <session-timeout>1</session-timeout> </session-config>
jsp:java server pages,Java服务器端界面,和servlet同样,用于开发动态web技术。
特色
在服务器内部,tomcat中有一个work目录,jsp最终被转化成了Java类, jsp本质就是一个servlet。
index_jsp.java源码
//初始化 public void _jspInit() { } //销毁 public void _jspDestroy() { } //jspService public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
判断请求
内置的一些对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config javax.servlet.jsp.JspWriter out = null; //out final java.lang.Object page = this; //page 当前页 HttpServletRequest request //请求 HttpServletResponse respons //响应
输出页面前增长的代码
response.setContentType("text/html"); //设置响应的页面类型 pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
以上的对象能够在jsp中直接使用
在jsp页面中,java代码会原封不动的输出,若是是html代码就会被转化为out.write(".....");
任何语言都有本身的语法 ,jsp做为Java技术的一种运用,它拥有一些本身扩充的语法(了解)。Java语法它都支持。
jsp表达式
<%--JSP表达式 输出时间到客户端--%> <%= new java.util.Date()%>
jsp脚本片断
<%--jsp脚本片断--%> <% int sum=0; for (int i = 0; i < 100; i++) { sum+=i; } out.println("<h1>sum="+sum+"</h1>"); %>
脚本片断的再实现
<% int x=10; out.print(x); %> <p>这是一个jsp文档</p> <% int y=20; out.print(y); %> <%--在代码中嵌入html元素--%> <% for (int i = 0; i < 5; i++) { %> <h1>helloworld<%=i%></h1> <% } %>
jsp声明
<%! static { System.out.println("loding..."); } private int globalvar=0; public void jspInit(){ System.out.println("进入了方法"); } %>
JSP声明:会被编译到jsp生成的Java类中。其它的会被生成到jspServer方法中。
JSP的注释不会在客户端源码显示,HTML的注释会在哭护短源码显示。
<error-page> <error-code>404</error-code> <location>/error/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error/500.jsp</location> </error-page>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <img src="img/500.jpg" alt="500"> </body> </html>
<%@page% args...> <%@include file=""%> <%--会将页面合二为一--%> <%@include file="common/header.jsp"%> <h1>主体</h1> <%@include file="common/footer.jsp"%> <hr> <%--jsp标签 拼接页面--%> <jsp:include page="common/header.jsp"/> <h1>主体</h1> <jsp:include page="common/footer.jsp"/>
<%--内置对象--%> <% pageContext.setAttribute("name1","周1");//保存的数据只在一个页面内有效 request.setAttribute("name2","周2");//保存的数据只在一次请求中有效,请求转发会携带 session.setAttribute("name3","周3");//保存的数据只在一次会话中有效,打开浏览器到关闭浏览器 application.setAttribute("name4","周4");//保存的数据在服务器中有效,打开服务器到关闭服务器 %> <%--经过pageContext取值--%> <% //经过寻找的方式 String name1 = (String) pageContext.findAttribute("name1"); String name2 = (String) pageContext.findAttribute("name2"); String name3 = (String) pageContext.findAttribute("name3"); String name4 = (String) pageContext.findAttribute("name4"); String name5 = (String) pageContext.findAttribute("name5");//不存在 %> <%--使用EL表达式输出 ${}--%> <h1>取出的值为:</h1> <h3>${name1}</h3> <h3>${name2}</h3> <h3>${name3}</h3> <h3>${name4}</h3> <h3>${name5}</h3> <hr> <%=name5%>
request:客户端向服务器发送数据,产生的数据,用户看完就没用了,好比:新闻
session:客户端向服务器发送数据,产生的数据,用户用完一会还会用,好比:购物车
application:客户端向服务器发送数据,产生的数据,一个用户使用完了,其它用户可能还用,好比:聊天记录
<!-- jstl表达式的依赖 --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <!-- standard标签库 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
EL表达式:${}
JSP标签:
<%--jsp:include--%> <%--转发时候携带参数--%> <jsp:forward page="/jsptag2.jsp"> <jsp:param name="name" value="zr"/> <jsp:param name="age" value="22"/> </jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义了许多的标签,能够供咱们使用,标签的功能和Java代码同样。
核心标签(掌握),格式化标签,SQL标签,XML标签
<%--引入JSTL核心标签库--%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
JSTL标签使用步骤
c:if
<body> <h1>if测试</h1> <hr> <form action="coreif.jsp" method="get"> <%-- EL表达式获取表单中的数据 ${param.参数名} --%> <input type="text" name="username" value="${param.username}"/> <input type="submit" name="登陆"> </form> <%-- 判断若是提交的用户是管理员,则登陆成功--%> <c:if test="${param.username=='admin'}" var="isadmin"> <c:out value="管理员欢迎你!"/> </c:if> <c:out value="${isadmin}"/> </body>
c:choose
<body> <%--定义一个变量score 值为88--%> <c:set var="score" value="88"/> <c:choose> <c:when test="${score>=90}"> 你的成绩优秀! </c:when> <c:when test="${score>=80}"> 你的成绩良好! </c:when> <c:when test="${score>=60}"> 你的成绩通常! </c:when> <c:when test="${score<=60}"> 你的成绩不合格! </c:when> </c:choose> </body>
c:forEach
<body> <% ArrayList<String> people = new ArrayList<String>(); people.add(0,"张三"); people.add(1,"李四"); people.add(2,"王五"); people.add(3,"赵六"); people.add(4,"田七"); request.setAttribute("list",people); %> <%-- var 每一次遍历的变量 items每次遍历的对象--%> <c:forEach var="people" items="${list}"> <c:out value="${people}"/><br> </c:forEach> <hr> <%--开始 结束 步长--%> <c:forEach var="people" items="${list}" begin="2" end="4" step="2"> <c:out value="${people}"/><br> </c:forEach> </body>
实体类
JavaBean有特定的写法:
通常用来和数据库的字段作映射 ORM;
ORM对象关系映射
people表
id | name | age | address |
---|---|---|---|
1 | 周1 | 18 | 武汉 |
2 | 周2 | 22 | 广州 |
3 | 周3 | 100 | 佛山 |
创建数据库相应的字段后建立java实体类
package com.zr.pojo; //实体类 通常是和数据库中的表结构一一对应的 public class People { private int id; private String name; private int age; private String address; public People() { } public People(int id, String name, int age, String address) { this.id = id; this.name = name; this.age = age; this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "People{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }
<%@ page import="com.zr.pojo.People" %><%-- Created by IntelliJ IDEA. User: zr Date: 2020/10/11 Time: 22:08 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% // People people = new People(); // people.setAddress(); // people.setId(); // people.setAge(); // people.setName(); //和下面的等价 %> <jsp:useBean id="people" class="com.zr.pojo.People" scope="page"/> <jsp:setProperty name="people" property="address" value="武汉"/> <jsp:setProperty name="people" property="id" value="1"/> <jsp:setProperty name="people" property="age" value="18"/> <jsp:setProperty name="people" property="name" value="小周"/> 姓名:<jsp:getProperty name="people" property="name"/> id:<jsp:getProperty name="people" property="id"/> 年龄:<jsp:getProperty name="people" property="age"/> 地址:<jsp:getProperty name="people" property="address"/> </body> </html>
MVC:model,view,controller 模型视图控制器
Model
View
Controller(Servlet)
登陆--->接收用户的登陆请求--->处理用户的请求(得到用户登陆的参数 username password)--->交给业务层处理登陆的业务(判断用户名密码是否正确)--->Dao层查询用户密码是否正确--->数据库
Filter:过滤器,用来过滤网站的数据:
Filter编写:先配置Servlet,jsp依赖
实现Filter(Servlet下的)接口,重写对应的方法
public class CharacterEncodingFilter implements Filter { //初始化 web服务器启动就初始化了,随时等待监听对象出现 public void init(FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化"); } //Chain :链 /* 1,过滤器中的全部代码,在过滤特定请求时都会执行 2,必需要让过滤器过滤同行 chain.doFilter(request,response); */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;character=UTF-8"); System.out.println("CharacterEncodingFilter执行前...."); chain.doFilter(request,response);//让咱们的请求继续走 若是不写,程序被拦截中止 System.out.println("CharacterEncodingFilter执行后...."); } //销毁 web服务器关闭的时候,过滤器销毁 public void destroy() { System.out.println("CharacterEncodingFilter销毁"); } }
servlet显示乱码
public class ShowServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //resp.setCharacterEncoding("utf-8"); //resp.setContentType("text/html"); resp.getWriter().write("你好世界"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
配置web.xml
<servlet> <servlet-name>showServlet</servlet-name> <servlet-class>com.zr.servlet.ShowServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>showServlet</servlet-name> <url-pattern>/servlet/show</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>showServlet</servlet-name> <url-pattern>/show</url-pattern> </servlet-mapping> <filter> <filter-name>CharacterEncoding</filter-name> <filter-class>com.zr.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncoding</filter-name> <!--只要是/servlet的任何请求,都会通过这个过滤器--> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
统计网站在线人数:
实现一个监听器的接口
//统计网站在线人数,统计Session public class OnlineCountListener implements HttpSessionListener { //建立Session监听 //一旦建立一个Session就会触发一次这个事件 public void sessionCreated(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); System.out.println(se.getSession().getId()); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(1); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count+1); } ctx.setAttribute("OnlineCount",onlineCount); } //销毁Session监听 //一旦销毁一个Session就会触发一次这个事件 public void sessionDestroyed(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(0); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count-1); } ctx.setAttribute("OnlineCount",onlineCount); } } /* Session销毁 1.手动销毁 se.getSession().invalidate(); 2.自动销毁 xml中配置<session-config> */
显示在线人数
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <h1>当前有<span style="color: hotpink"><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1> </body> </html>
配置web.xml
<!--注册监听器--> <listener> <listener-class>com.zr.listener.OnlineCountListener</listener-class> </listener>
监听器GUI编程中常用
GUI应用
public class TestPanel { public static void main(String[] args) { Frame frame = new Frame("中秋快乐!"); //新建一个窗体 Panel panel = new Panel(null); //面板 frame.setLayout(null); //设置窗体的布局 frame.setBounds(300,300,500,500); //坐标 frame.setBackground(new Color(0,0,255)); //背景颜色 panel.setBounds(50,50,300,300); panel.setBackground(new Color(0,255,255)); frame.add(panel); frame.setVisible(true); //监听事件,监听关闭事件 frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
用户登陆后才能进入主页,注销后不能进入主页
1.用户登陆以后向session中放入用户的数据
2.进入主页的时候判断用户是否登陆,要求在过滤器中实现login.jsp
login.jsp(web包下)
<body> <h1>登陆</h1> <form action=" /servlet/login" method="post"> <input type="text" name="username"> <input type="submit"> </form> </body>
success.jsp(web/sys包下)
<body> <h1>主页</h1> <a href="/servlet/loginout">注销</a> </body>
error.jsp(web包下)
<body> <h1>错误</h1> <h3>用户名错误</h3> <a href="/login.jsp">返回登陆页面</a> </body>
Login
public class login extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取前端请求的参数 String username = req.getParameter("username"); if (username.equals("admin")){ req.getSession().setAttribute("USER_SESSION",req.getSession().getId()); resp.sendRedirect("/sys/success.jsp"); }else { resp.sendRedirect("/error.jsp"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
LoginOut
public class LoginOut extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object user_session = req.getSession().getAttribute("USER_SESSION"); if (user_session!=null){ req.getSession().removeAttribute("USER_SESSION"); resp.sendRedirect("/login.jsp"); }else { resp.sendRedirect("/login.jsp"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
SysFilter:过滤器
public class SysFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; filterChain.doFilter(request, response); if (req.getSession().getAttribute("USER_SESSION")==null){ resp.sendRedirect("/error.jsp"); } } public void destroy() { } }
web.xml
<servlet> <servlet-name>login</servlet-name> <servlet-class>com.zr.servlet.login</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/servlet/login</url-pattern> </servlet-mapping> <servlet> <servlet-name>loginOut</servlet-name> <servlet-class>com.zr.servlet.LoginOut</servlet-class> </servlet> <servlet-mapping> <servlet-name>loginOut</servlet-name> <url-pattern>/servlet/loginout</url-pattern> </servlet-mapping> <filter> <filter-name>CharacterEncoding</filter-name> <filter-class>com.zr.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncoding</filter-name> <!--只要是/servlet的任何请求,都会通过这个过滤器--> <url-pattern>/servlet/*</url-pattern> </filter-mapping> <filter> <filter-name>SysFilter</filter-name> <filter-class>com.zr.filter.SysFilter</filter-class> </filter> <filter-mapping> <filter-name>SysFilter</filter-name> <!--只要是/sys的任何请求,都会通过这个过滤器--> <url-pattern>/sys/*</url-pattern> </filter-mapping>
Java链接数据库,导入JDBC依赖mysql-connector-java,IDEA中链接数据库
public class TestJdbc { public static void main(String[] args) throws ClassNotFoundException, SQLException { //配置信息 String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8"; String username = "root"; String password = "123456"; //加载驱动 Class.forName("com.mysql.jdbc.Driver"); //链接数据库 Connection connection = DriverManager.getConnection(url, username, password); //向数据库发送sql的对象 Statement statement = connection.createStatement(); //编写sql String sql = "select * from users"; //执行查询sql,返回一个结果集 ResultSet rs = statement.executeQuery(sql); while (rs.next()){ System.out.println("id="+rs.getObject("id")); System.out.println("name="+rs.getObject("name")); System.out.println("password="+rs.getObject("password")); System.out.println("email="+rs.getObject("email")); System.out.println("birthday="+rs.getObject("birthday")); } //关闭链接 rs.close(); statement.close(); connection.commit(); } }
预编译sql
public class TestJdbc2 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //配置信息 String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8"; String username = "root"; String password = "123456"; //加载驱动 Class.forName("com.mysql.jdbc.Driver"); //链接数据库 Connection connection = DriverManager.getConnection(url, username, password); //向数据库发送sql的对象 Statement statement = connection.createStatement(); String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,4); preparedStatement.setString(2,"周七"); preparedStatement.setString(3,"888888"); preparedStatement.setString(4,"666@qwq.com"); preparedStatement.setString(5, String.valueOf(new Date(new java.util.Date().getTime()))); int i = preparedStatement.executeUpdate(); if (i>0){ System.out.println("插入成功"); } //关闭链接 statement.close(); connection.commit(); } }
要么都成功,要么都失败 !
ACID原则,保证数据的安全。
开启事务
事务提交 commi ()
事务回滚 rollback ()
关闭事务
Junit单元测试
依赖
<!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
简单使用
@Test注解只在方法上有效,只要加了这个注解的方法,就能够直接运行。
public class TestJdbc3 { @Test public void test(){ System.out.println("Hello"); } }
转帐事务(建立account表,字段id,name,money),使用单元测试
public class TestJdbc3 { @Test public void test() { //配置信息 String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8"; String username = "root"; String password = "123456"; Connection connection=null; //加载驱动 try { Class.forName("com.mysql.jdbc.Driver"); //链接数据库 connection = DriverManager.getConnection(url, username, password); //通知数据库开启事务 connection.setAutoCommit(false); String sql1 = "update account set money=money-100 where name='A'"; connection.prepareStatement(sql1).executeUpdate(); //制造错误 int i=1/0; String sql2 = "update account set money=money+100 where name='B'"; connection.prepareStatement(sql2).executeUpdate(); connection.commit();//以上sql都执行成功才提交 System.out.println("提交成功!"); } catch (Exception e) { try { //若是出现异常,就回滚事务 connection.rollback(); System.out.println("转帐失败!"); } catch (SQLException throwables) { throwables.printStackTrace(); } e.printStackTrace(); }finally { try { connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } }