java web学习笔记

创建java web项目

idea+tomcat7
新建web项目
在这里插入图片描述

目录结构如下
在这里插入图片描述

配置tomcat
在这里插入图片描述

在这里插入图片描述

运行,并通过浏览器访问
在这里插入图片描述

Servlet

什么是servlet

servlet 是java web 开发的基石,它是运行在servlet容器中(tomcat)中,负责与客户端进行通信。

  • servlet功能:

    1. 创建 并返回基于客户端请求的动态html页面。
    2. 与数据库进行通信
  • Servlet 使用
    Servlet本身是一组接口,自定义一个类,实现servlet接口,这个类就具备了接收客户端请求以及相应的功能
    在这里插入图片描述
    浏览器不能直接访问Servlet文件,只能通过映射的方式来间接访问servlet,映射需要开发者手动配置,有两种配置方式

  • 配置web.xml,将url地址与servlet进行映射:

   <servlet>
        <servlet-name>myservlet</servlet-name>
        <servlet-class>com.youzm.servlet.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myservlet</servlet-name>
        <url-pattern>/myservlet</url-pattern>
    </servlet-mapping>

  • 基于注解的方式:

在这里插入图片描述

启动调用

在这里插入图片描述

Servlet生命周期

  1. 当浏览器访问SErvlet的时候,tomcat会查询当前SErvlet的实例化对象是否存在,如果不存在,则通过反射机制动态创建对象
  2. 调用init方法完成初始化操作
  3. 调用service方法完成业务逻辑操作
  4. 关闭tomcat时,会调用destory方法,释放当前对象所占用资源

Servlet的生命周期方法,无参构造方法,init,service,destory

1、无参构造函数只调次,创建对象。
2、init 只调用1次,初始化对象。
3、service 调用 N 次,执行业务方法。
4、destory 只调一次,卸载对象。

Servlet的层次结构

Servlet–》GenericServlet–》HttpServlet

在servlet中,与业务相关且使用最多的方法为service方法,所以tomcat中为我们提供了GenericServlet和HttpServlet方法,他们都分别实现了servlet和继承GenericServlet,我们只需要编写自己的类并继承HttpServlet方法,并重写其doGet,doPost等方法。


@WebServlet("/httpdemo1")
public class HttpServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Get");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Post");
    }
}

JSP

jsp本质是一个servlet,主要负责与用户交互,将最终的页面呈现给用户,html+js+css+java混合文件

当服务器接收到一个后缀是jsp的请求是,将该请求交给jsp引擎去处理,每一个jsp页面第一次被访问的时候会翻译成一个servlet文件,再有web容器调用servlet完成响应

单纯看:jsp就是html中嵌入java程序

具体嵌入方式额三种:

  1. jsp脚本,执行java逻辑代码
	<% java 代码 %>
  1. jsp声明,定义Java方法
	<%! 声明java方法%>
  1. jsp 表达式
	<%= java 变量%>

示例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <$END$
  <body>
  <h1>第一个java web程序</h1>

  <%!
    public  String test(){
      return "Hello world";
    }
  %>
  <%
    String str=test();
  %>
  <%=
    str
  %>
  </body>
</html>

JSP内置对象9个

  • request:表示一次请求,HttpServletRequest
  • response:表示一次响应,HttpServletResponse
  • pageContext:页面上下文,获取页面信息,PageContext
  • session:表示一次会话,保存用户信息,HttpSession
  • application:表示当前web引用,全局对象,保存所有用户共享信息,ServletContext
  • config:当前jsp对应的servlet的servletConfig对象,获取当前servlet信息
  • out:向浏览器输出数据,jspWriter
  • page: :当前jsp对应的servlet对象,Servlet
  • exception:表示jsp页面发生的异常,Exception

常用的是request,response,session,application,pageContext

request常用方法

  1. String getParameter(String key):用来获取客户端传递的参数(key-value) ;
  2. void setAttribute(String key,Object value):通过键值对的形式保存数据;(服务端内部之间传递
  3. Object getAttribute(String key): 通过key获取value
  4. RequestDispatcher getRequestDispatcher(String path):返回一个RequestDispatch对象,该对象的forward方法用于请求转发
  5. String[] getParameterValues():获取客户端传来的多个同名参数;
  6. void setCharacterEncoding(String charset):指定每个请求的编码;

response常用方法

  1. sendRedirect(String path):重定向地址,页面之间的跳转;
    转发getRequestDispatcher和重定向sendRedirect的区别:
    - 转发是将同一个请求传给下一个页面,重定向是创建一个新请求传给下一个页面,之前的请求结束生命周期;
    - 转发:同一个请求在服务器之间传递,地址栏不变,也叫服务器跳转;
    - 重定向:由客户端发送一次新的请求来访问跳转后的目标资源,地址栏改变,也叫客户端跳转;
    ** 如果两个页面之间需要通过request来传值,则必须使用转发,不能使用重定向**

Session

用户会话
服务器无法识别每一次Http请求的出处,他只会接收到一个请求信号,所以就存在一个问题:将用户的响应发送给其他人,必须有一种技术来让服务器知道请求来自哪,这就是会话技术;
会话:就是客户端和服务端之间发生的一系列连续的请求响应的过程,–》打开浏览器操作到关闭浏览器的过程;
会话状态:值服务器和浏览器在会话过程中产生的状态信息,借助于会话状态,服务器能够把属于同义词绘画的一系列请求和响应关联起来;
实现会话的两种方式:

  • cookie
  • session

session:属于同一次会话的请求都会有一个相同的标识符(sessionId)
session 常用的方法:
String getId(): 获取当前sessionId
void setMaxInactiveInterval(int interval) 设置当前session失效时间,单位为s
int getMaxInactiveInterval(): 获取当前session的失效时间
void invalidate() 设置session立即失效
void setAttribute(String key,Object value)通过键值对的形式来存储数据
Object getAttribute(String key) 通过键值获取对应的数据;
void removeAttribute(String key) 通过键值删除

cookie

cookie是服务端在http响应中附带传给浏览器的一个小文本文件,一旦浏览器保存了某个cookie,在之后的请求和响应中,会将此cookie来回传递,这样可以以cookie为载体,完成客户端–服务端之间的数据交互

Cookie:

  • 创建
   Cookie coolie=new Cookie("name","zhangsan");
   response.addCookie(cookie);
  • 读取
 Cookie[] cookies=request.getCookies();
    for(Cookie c:cookies){
        out.write(c.getName()+":"+c.getValue());
    }

常用方法:
void setMaxAge(int age):设置Cookie的有效时间,单位s;销毁时设置为0;
int getMaxAge():获取cookie有效时间
String getName()获取Cookie的name
String getValue()获取Cookie的value

Session和Cookie的区别

session 保存在服务器
保存的数据类型为Object
随会话结束销毁
保存重要信息
cookie 保存在客户端
保存的数据类型为String
可长期保存,与会话无关
保存不重要信息

jsp内置对象的作用域

4个:
page,request,session,application
这四个有setAttribute和getAttribute方法存储数据,区别为范围不一样;

  • page作用域:对应的内置对象为pageContext,当前页面有效
  • request作用域:对应的内置对象是request,再一次请求内有效
  • session作用域:对应的内置对象是seesion,在一次会话有效
  • application作用域:对应的内置对象是application,对应蒸锅web应用。

page<reqeust<session<application

EL表达式

Expression Language表达式语言,代替jsp页面中数据访问时的复杂编码,可以非常便捷的取出域对象(page,request,session,application)中保存的数据,前提是一定要先setAttribute。
$(表达式)变量名是setAttribute对应的key值

EL对于4种域对象的查找顺序:
pageContext==》request==》session==》application
按照上述的顺序进行查找,找到立即返回,若没找到,则返回null;

也可以指定作用域查找
${requestScope.name}:在request中查找name

EL执行表达式
&& || ! < > <= >= ==

主要用来取数据

JSTL

jsp Standard Tag Library :jsp标准标签库,jsp为开发者提供了一系列的标签,使用这些标签可以完成一些逻辑处理,比如循环遍历集合,让代码更加简洁,不在出现jsp脚本穿插的情况

实际开发中EL和jstl结合使用,JSTL侧重于逻辑处理,EL负责数据展示
JSTL的是使用:

  1. 需要导入jar包 jstl.jarstandard.jar
  2. 在jsp页面开始的地方引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
  1. 在需要的地方使用
 	<c:forEach items="${list}" var="user">
        <tr>
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.adderss.value}</td>
        </tr>
    </c:forEach>

JSTL优点:

  1. 提供了统一的标签
  2. 可以用于编写各种动态功能吧

常用标签:
set out remove catch

set:向域对象中添加数据

向requst域中添加key为name,value为tom的数据
<c:set var="name" value="tom" scope="request"></c:set>

过滤器

Filter
功能:

  1. 用来拦截传入的请求和传出的响应。
  2. 修改或以某种方式正在客户端和服务端之间交换的数据流
    如何使用:
    与使用servlet类似,Filter是java web提供的一个接口,开发者只需要自定义一个类并且实现该接口即可;
public class CharacterFilter  implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

web.xml中配置Filter

	<filter>
    <filter-name>characterFilter</filter-name>
    <filter-class>com.youzm.filter.CharacterFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>characterFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Filter生命周期

当Tomcat启动时,通过反射机制调用Filter的无参构造函数创建实例化对象,同时调用init方法实现初始化,doFilter方法调用很多次,当tomcat关闭时,调用destory来销毁Filter对象。

  • 无参构造函数:只调用一次,当Tomcat启动时,(filter一定要进行配置(xml,注解@WebFilter))
  • init方法:只调用一次,当Filter实例化对象创建完成之后调用
  • doFilter:调用多次,访问Filter业务时调用
  • destory:关闭服务时调用

同时配置多个Filter,调用顺序是由web.xml中的配置顺序来决定。从上往下顺序读取;

实际开发中Filter的使用场景:

  1. 同一处理中文乱码;
  2. 屏蔽敏感词;
  3. 控制资源的访问权限;

文件上传下载

上传

  • jsp
  1. input的type设置为file
  2. form表单的method设置为post,get方式只会传入文件名
  3. form表单的enctype设置为multipart/form-data,以二进制的形式传输数据
  • servlet
    使用fileUpload组件,可以将所有的请求信息解析成FileIteam对象,可以沟通过对FileItem对象的操作完成上传,面向对象的思想
 		 DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
         ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
         List<FileItem> list = servletFileUpload.parseRequest(req);

使用示例:
jsp:

<form enctype="multipart/form-data"  action="/upload" method="post">
    <input type="file" name="img">
    <input type="submit" value="上传">
</form>

servlet

	 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        try {
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            List<FileItem> list = servletFileUpload.parseRequest(req);
            System.out.println(list);
            for(FileItem fileItem:list){
               if(fileItem.isFormField()){
                   String name=fileItem.getFieldName();
                   String value=fileItem.getString("utf-8");
                   System.out.println(name+":"+value);
               }else {
                   String fileName=fileItem.getName();
                   long size=fileItem.getSize();
                   System.out.println(fileName+":"+size);

                   InputStream inputStream=fileItem.getInputStream();
                   String path=req.getServletContext().getRealPath("file/"+fileName);
                   OutputStream outputStream=new FileOutputStream(path);
                   int temp=0;
                   while ((temp=inputStream.read())!=-1){
                       outputStream.write(temp);
                   }
                   outputStream.close();
                   inputStream.close();
                   System.out.println("上传成功");
               }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }

下载

get方式下载
jsp

<a href="/download" >1.png</a>

servlet


 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String filename="1.png";
        //设置响应方式
        resp.setContentType("application/x-msdownload");
        //设置下载后的文件名
        resp.setHeader("Content-Disposition","attachment;filename="+filename);
        //获取输出流
        OutputStream outputStream=resp.getOutputStream();
        String path=req.getServletContext().getRealPath("file/1.png");
        InputStream inputStream=new FileInputStream(path);
        int temp=0;
        while ((temp=inputStream.read())!=-1){
            outputStream.write(temp);
        }
        inputStream.close();
        outputStream.close();
    }

Ajax

Asynchronous JavaScript And Xml:异步的javaScript和xml

AJAX 不是新的编程,指的是一种交互方式,异步加载,客户端和服务器的数据交互更新在局部页面的
技术,不需要刷新整个页面(局部刷新)

优点:

  1. 局部刷新,效率更高
  2. 用户体验更好

基于jquery的ajax

使用示例:

<script type="text/javascript">
        $(function () {
           var btn=$("#btn");
           btn.click(function () {
              
               $.ajax({
                   url:"/ajax",
                   type:'post',
                   data:"id=1",
                   dataType:"text",
                   success:function (data) {
                       var text=$("#text");
                       text.before("<span>"+data+"<span><br/>")
                   }
               })
           });
        })
    </script>

</head>
<body>
    <input id="text" type="text" /><br/>
    <input id="btn" type="button" value="提交">
</body>

servlet

   @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id=(String)req.getParameter("id");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String str="Hello world";
        resp.getWriter().write(str);
    }

传统的web数据交互与ajax数据交互的区别

  1. 客户端请求的方式不一样:
    - 传统:浏览器发送同步请求(form表单,a标签)
    - ajax:异步引擎对象发送异步请求
  2. 服务器响应方式不同:
    - 传统:响应一个完整的jsp页面(视图)
    - ajax:响应需要的数据
  3. 客户端处理方式不同
    - 传统:需要等待服务器完成响应并且重新加载整个页面之后,用户才能进行后续的操作
    - ajax:动态更新页面中的局部信息,不影响用户的其他操作

基于jQuery的ajax的语法

$.ajax({属性})
常用的属性参数:
url:请求的后端服务地址
type:请求方式,默认get
data:请求参数
dataType:服务器返回的数据类型,text/json
success:请求成功的回调函数
error:请求失败的回调函数
complete:请求完成的会调函数(无论成功或失败,都会调用)

JDBC

java dataBase Connectivity java数据库连接技术,独立于特定数据库的管理系统,提供了通用的 sql数据库存取和操作的公共接口

定义了一组接口,为访问数据库提供了统一途径

JDBC API
提供者:java官方
内容:供开发者调用的接口
java.sql和javax.sql
- DriverManager类
- Connerction接口
- Statement接口
- ResultSet接口
DriverManager
提供者:java官方
作用:管理不同的jdbc驱动
jdbc驱动
提供者:数据库厂商
作用:负责连接不同数据库

使用

  1. 加载数据库驱动,java程序和数据库之间的桥梁
  2. 获取Connection,java程序与数据库的一次连接
  3. 创建Statement对象,有connection产生,执行sql语句
  4. 如果需要接受返回值,创建ResultSet对象,保存Statement执行之后所查询到的结果
 	public static void main(String[] args) {

        try {
            //加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            String url="jdbc:mysql://localhost:3306/sql?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
            String user="root";
            String password="root";
            Connection connection= DriverManager.getConnection(url,user,password);
//            System.out.println(connection);
//            String sql="insert into student(name,score,birthday) values ('李四',78,'2020-12-23')";
//            String sql="update student set name='李四'";
//            String sql="delete from student";
//            Statement statement=connection.createStatement();
//            int result=statement.executeUpdate(sql);
//            System.out.println(result);
            
            String sql="select * from student";
            Statement statement=connection.createStatement();
            ResultSet resultSet=statement.executeQuery(sql);
            while (resultSet.next()){
                Integer id=resultSet.getInt(1);
                String name=resultSet.getString("name");
                Integer score=resultSet.getInt(3);
                Date date=resultSet.getDate(4);
    			System.out.println(id+"-"+name+"-"+score+"-"+date);            
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

PreparedStatement

Statement子类,提供占位符

示例:登录功能:
使用前:

public static void main(String[] args) {
        try {
            //加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            String url = "jdbc:mysql://localhost:3306/sql?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
            String user = "root";
            String password = "root";
            Connection connection = DriverManager.getConnection(url, user, password);

            String username = "lisi";
            String mypassword = "000";
            String sql = "select * from user where name='" + username + "' and password= '" + mypassword+"'";
            System.out.println(sql);
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(sql);
            if (resultSet.next()) {
                System.out.println("登录成功");
            } else {
                System.out.println("登录失败");
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

使用Statement进行开发有两个问题

  • 需要频繁拼接String字符串,出错率高
  • 存在sql注入风险
    sql注入:利用某些系统没有对用户输入的信息进行充分检测,在用户输入的数据中心注入非法的sql语句,从而利用系统的dql引擎完成恶意行为的做法
     		 String username = "lisi";
            String mypassword = "000";
            String sql="select * from user where name=? and password=?";
            PreparedStatement preparedStatement=connection.prepareStatement(sql);
            preparedStatement.setString(1,username);
            preparedStatement.setString(2,mypassword);
            ResultSet resultSet=preparedStatement.executeQuery();

数据库连接池

JDBC开发流程

  • 加载驱动(只需要加载一次)
  • 建立数据库连接(Connection)
  • 执行sql语句(Statement)
  • Resultset接收结果(查询)
  • 断开连接,释放资源

数据库连接对象是通过DriverManager来获取,每次获取都需要向数据库申请获取连接,验证用户名密码,执行完sql后断开连接,这样的方式会造成资源的浪费,数据连接资源没有得到很多复用。

可以使用数据库连接池解决这一问题。
数据库连接池的基本思想是为数据库建立一个缓冲池,预先向缓冲池中放入一定数量的连接对象,当获取数据库连接时,只需要从缓冲翅中取出一个对象,用完之后再放回缓冲池中,供下次使用,做到了资源的复用,允许程序重复使用一个现有的数据库连接对象,而不是重新创建连接。

数据库连接池的实现

jdbc的数据库连接池使用javax.sql.DataSource接口来实现的,DataSource是java官方提供的接口,使用时开发者不需要来实现该接口,可以使用第三方工具,C3P0是一个常用的第三方实现,实际开发中直接使用c3p0即可完成数据库连接池的操作。

  1. 导入jar包c3p0-0.9.5.5.jarmchange-commons-java-0.2.19.jar
  2. 代码实现
  public static void main(String[] args) {
        try {
            //创建c3p0
            ComboPooledDataSource dataSource=new ComboPooledDataSource();
            dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/sql?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC");
            dataSource.setUser("root");
            dataSource.setPassword("root");

            //设置初始化连接个数
            dataSource.setInitialPoolSize(5);
            //设置最小
            dataSource.setMinPoolSize(2);
            //当连接对象不够,再次申请连接个数
            dataSource.setAcquireIncrement(5);
            //设置最大连接个数
            dataSource.setMaxPoolSize(20);

            Connection connection=dataSource.getConnection();
            /*
            * 执行sql
            * */
            System.out.println(connection);
            connection.close();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

实际开发中使用xml方式进行配置,修改不需要再次编译

xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <named-config name="c3p0">
        <!-- 指定连接数据源的基本属性 -->
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/sql?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC</property>
        <!-- 若数据库中连接数不⾜时, ⼀次向数据库服务器申请多少个连接 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始化数据库连接池时连接的数量 -->
        <property name="initialPoolSize">20</property>
        <!-- 数据库连接池中的最⼩的数据库连接数 -->
        <property name="minPoolSize">2</property>
        <!-- 数据库连接池中的最⼤的数据库连接数 -->
        <property name="maxPoolSize">40</property>
    </named-config>
</c3p0-config>

java代码

    public static void main(String[] args) {
        try {
            ComboPooledDataSource dataSource=new ComboPooledDataSource("c3p0");
            Connection connection=dataSource.getConnection();
            /*
             * 执行sql
             * */
            System.out.println(connection);
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

DBUtils

DBUtils 可以帮助开发者完成数据的封装(结果集到 Java 对象的映射)

  1. 导入jar包 mysql-connector-java-8.0.20.jar

  2. ResultHandler 接口是用来处理结果集,可以将查询到的结果集转换成 Java 对象,提供了 4 种实现类。

    • BeanHandler 将结果集映射成 Java 对象 Student
    • BeanListHandler 将结果集映射成 List 集合 List
    • MapHandler 将结果集映射成 Map 对象
    • MapListHandler 将结果集映射成 MapList 结合
      示例:
	 try {
            ComboPooledDataSource dataSource=new ComboPooledDataSource("c3p0");
            Connection connection=dataSource.getConnection();
            String sql="select * from student where id=1";
            QueryRunner queryRunner=new QueryRunner();
            Student student=queryRunner.query(connection,sql,new BeanHandler<>(Student.class));
            System.out.println(student);
            System.out.println(connection);
            connection.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

参考视频:
B站楠哥----java web从入门到实战

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值