JavaWeb基础02

JSP

什么是JSP

Java Servlet Pages Java服务器端页面 也和Servlet一样 用于动态Web技术

xxxxxxxxxx19 12​3    4    5        javax.servlet6        javax.servlet-api7        4.0.18        provided9    10​11    12    13        javax.servlet.jsp14        javax.servlet.jsp-api15        2.3.316        provided17    18​19xml

写JSP就像是在写HTML

区别

HTML只给用户提供静态的数据

JSP页面中可以嵌入JAVA代码 为用户提供动态数据

JSP原理

思路 --> 思考JSP到底是怎么执行的 ?

代码层面没有任何问题

服务器内部工作

  • tomcat中有一个work目录
  • 在IDEA中使用tomcat的话 会在 IDEA 的 tomcat 中生成一个work目录

我的电脑中的网址 -->

C:\Users\qian\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\e0f29b75-76ca-410e-9b86-b00ad81ba4cd\work\Catalina\localhost\ROOT\org\apache\jsp

点开发现JSP页面转换成了Java程序

浏览器向服务器发送请求 不管访问什么资源 其实都是在访问Servlet

JSP最终也会被转换成一个 Java 类

JSP 本质上就是一个Servlet

请求判断

//初始化
public void _jspInit(){
    
}
//销毁
public void _jspbestroy(){
    
}
//JSPservice
public void ispservice(.HttpservletRequest request,HttpservletResponse response)

内置了一些对象

final javax.servlet.jsp.Pagecontext pagecontext;	//页面上下文
javax.servlet.http.Httpsession session =nul:		//session
final javax.servlet.servletcontext application;		//applicationcontext
final iavax.servlet.servletconfig config;			//config
javax.servlet.jsp.IspWriter out =nu11:				//out
final java.lang.object page = this;					//page:当前
HttpservletRequest request							//请求
HttpservletResponse response1						//响应

输出页面前增加的代码

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页面中使用

image-20240525232853350

在JSP页面中

只要是 JAVA代码 就会原封不动的输出

如果的HTML代码 就会被转换为

out.write("<html>\r\n");

这样的格数 输出到前端

JSP基础语法

任何语言都有自己的语法 JAVA中有 JSP作为java技术的一种应用 它拥有一些自己扩充的语法 ( 了解即可 ) Java 所有语法都支持

jsp表达式

<%@ page import="java.util.*" %>  
<%--JSP表达式
  作用  用来将程序的输出  输出到客户端
  <%= 变量或者表达式%>
  --%>

    <%= new Date()%>
  <hr>

jsp脚本片段

  <%--jsp脚本片段--%>
  <%
    int sum = 0;
    for (int i = 0; i < 10; i++) {
      sum = sum + i;
    }
    out.println("<h1>Sum" + sum + "</h1>");
  %>
  <hr>
  <%
  int x = 10;
  out.println("x --> " + x);
  %>
  <p>这是一个JSP文档</p>
  <%
  int y = 20;
  out.println("y --> " + y);
  %>
  <hr>

脚本片段的再实现

  <%--在代码中嵌入HTML语言--%>
  <%
    for (int i = 0; i < 5; i++) {
  %>
  <h1>Hello,JSP <%= i%></h1>
  <%
    }
  %>
  <hr>

JSP声明

  <%--
  jsp声明
  定义_jspService方法之外的代码  定义在了index_jsp类的下面  作用域更高--%>
  <%!
    static {
      System.out.println("Loading Servlet");
    }
    private int globalVar = 0;

    public void xiaoLiu(){
      System.out.println("进入了方法 小刘");
    }
  %>

JSP声明 --> 会被编译到JSP生成的JAVA类index_jsp中 其他的就会被生成到_jspService方法中

在JSP中嵌入JAVA代码即可

JSP的注释不会在客户端显示 HTML的注释会显示

JSP指令

9大内置对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application [ ServletContext ] 存东西
  • config [ ServletConfig ]
  • out
  • page 几乎不用
  • exception
pageContext.setAttribute("name01","小刘1号");  // 保存的数据只在一个页面中有效
request.setAttribute("name02","小刘2号");      // 保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name03","小刘3号");      // 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name04","小刘4号");  // 保存的数据只在服务器中有效,从打开服务器到关闭服务器

request --> 客户端向服务器发送请求 产生的数据 用户看完就没有了 比如 新闻

session --> 客户端向服务器发送请求 产生的数据 用户看完一会还有 比如 购物车

application --> 客户端向服务器发送请求 产生的数据 一个用户看完了,其他用户还可能使用 比如 聊天数据

JSP标签 JSTL标签 EL表达式

<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

EL表达式 $

获取数据

执行运算

获取web开发的常用对象

JSP标签

<h1>jspTag02</h1>

<%--jsp:include--%>

<%--
http://localhost:8080/jspTag.jsp?username=xiaoliu&age=12
--%>

<jsp:forward page="jsptag02.jsp">
    <jsp:param name="userName" value="xiaoLiu"/>
    <jsp:param name="userAge" value="21"/>
</jsp:forward>

JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足 JSTL自定义了许多标签可以供我们使用 标签的功能和java代码一样

**格式化标签 ** 了解

SQL标签 了解

XML标签 了解

核心标签 ( 掌握部分 ) --> 示例

image-20240530165146395

JSTL标签库使用步骤

引入对应的taglib

使用其中的方法

在Tomcat中 也需要引入jstl的包 否则会报错 --> JSTL解析错误

c:if

<h4>if测试</h4>

<hr>

<form action="coreif.jsp" method="get">
    <%--
    EL表达式获取表单中的数据
    ${param.参数名}
    --%>
        <input type="text" name="username" value="${param.username}">
        <input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,则登录成功--%>

<c:if test="${param.username == 'admin'}" var="isAdmin">
    <c:out value="检测到你的身份是管理员,你的权限级别无上限"/>
</c:if>

<%--自闭合标签--%>
<c:out value="${isAdmin}"/>


<%--
JAVA代码实现登录功能
<%
    if (request.getParameter("username").equals("admin")){
        out.print("登录成功");
    }
%>
--%>

c:choose

<%--定义一个变量score  值为85--%>
<c:set var="score" value="85"/>

<c:choose>
    <c:when test="${score >= 90}">
        你该科目期末考试成绩为A+
    </c:when>
    <c:when test="${score >= 80}">
        你该科目期末考试成绩为B+
    </c:when>
    <c:when test="${score >= 70}">
        你该科目期末考试成绩为C+
    </c:when>
    <c:when test="${score >= 60}">
        你该科目期末考试成绩为D+
    </c:when>
    <c:when test="${score < 60}">
        你该科目期末考试成绩不达标
    </c:when>
</c:choose>

c:forEach

<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田七");
    request.setAttribute("list",people);

%>


<%--

    for (String person : people) { }

var         每一次遍历出来的变量
items       要遍历的对象
--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/> <br>
</c:forEach>

<hr>

<%--

    for (int i = 0; i < ; i++) { }
         begin      end   step

begin   从哪里开始
end     到哪里结束
step    步长
--%>

<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
    <c:out value="${people}"/> <br>
</c:forEach>

JavaBean

实体类

JavaBean有特点的写法

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM

ORM 对象关系映射

表 --> 类

字段 --> 类的属性

行记录 --> 对象

people表

id name age address
1 小刘1号 21 ShangHai
2 小刘2号 22 BeiJing
3 小刘3号 23 JiaoZuo
class People{
	private int id;
    private String name;
    private int age;
    private String address;
}

class Student_A {
    new people(1,"小刘1号",21,"ShangHai");
    new people(1,"小刘2号",22,"BeiJing");
    new people(1,"小刘3号",23,"JiaoZuo");
}

MVC三层架构

什么是MVC Model view Controller 模型 视图 控制器

早些年的架构 -->

image-20240531103853346

用户直接访问控制层 控制层就可以直接操作数据库

servlet--CRUD-->数据库
弊端	程序十分臃肿	不利于维护	servlet的代码中		处理请求 响应	视图跳转 处理JDBC	处理业务代码 处理逻辑代码

架构  没有什么是加一层解决不了的
程序员调用
|
JDBC
|
Mysql	Oracle	sqlServer...

MVC三层架构

image-20240531105052024

image-20240531105235122

Model

  • 业务处理 --> 业务逻辑 (Service)
  • 数据持久层 --> CRUD (Dao)

View

  • 展示数据
  • 提供连接发起Servlet请求 (a form img...)

Controller ( Servlet )

  • 接收用户的请求 --> (req --> 请求参数 Session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
登录  -->  接收用户的登录请求  -->  处理用户的请求(获取用户登陆的参数 username password)  -->
交给业务层处理登录业务(判断用户名 密码是否正确: 业务)  -->  Dao层查询用户名和密码是否正确    -->  数据库

Filter 重点

Filter --> 过滤器 用来过滤网站的数据

  • 处理中文乱码
  • 登录验证...

image-20240531110854532

Filter开发步骤 -->

1.导包

2.编写过滤器

​ 1. 导包不要错

​ implements Filter javax.servlet

​ 2. 实现Filter接口 重写对应方法

public class CharacterEncodingFilter implements Filter {

    // 初始化: web服务器启动 就已经初始化了 随时等待过滤对象出现
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }


    /*
    Chain: 链
    1. 过滤器中的所有代码 在过滤特定请求的时候都会执行
    2. 必须要让过滤器继续通行  chain.doFilter(request,response)
    3.
    */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        System.out.println("CharacterEncodingFilter执行前...");
        chain.doFilter(request,response);   //让我们的请求继续走  如果不写,程序到这里就被拦截停止
        System.out.println("CharacterEncodingFilter执行后...");
    }

    // 销毁: web服务器关闭的时候 过滤销毁
    @Override
    public void destroy() {
        System.gc();
        System.out.println("CharacterEncodingFilter销毁");
    }
}
	3. 在web.xml中配置Filter
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.xiaoliu.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是 /servlet下的任何请求 都会经过这个过滤器-->
        <url-pattern>/servlet/*</url-pattern>
        <!--<url-pattern>/*</url-pattern>-->
    </filter-mapping>

监听器

实现一个监听器的接口

  1. 编写一个监听器

    实现监听器的接口 重写里面的方法

// 统计网站在线人数监听   统计session
// 监听  看你的一举一动  一旦创建Session就会触发一次这个事件
public class OnlineCountListener implements HttpSessionListener {

    // 创建session监听
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) context.getAttribute("OnlineCount");

        if (onlineCount == null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count + 1);
        }

        context.setAttribute("OnlineCount",onlineCount);
    }

    //销毁session监听
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();

        Integer onlineCount = (Integer) context.getAttribute("OnlineCount");

        if (onlineCount == null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count - 1);
        }

        context.setAttribute("OnlineCount",onlineCount);
    }

    /*
    Session销毁
    1. 手动销毁 getSession().invalidate();
    2. 自动销毁
    */
}
  1. web.xml中注册监听器
<!--配置Session自动销毁时间 以分钟为单位-->
<session-config>
    <session-timeout>1</session-timeout>
</session-config>
  1. 看情况是否使用

过滤器和监听器常见应用

监听器在GUI编程中经常使用

public class TextPanel {
    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,0));

        frame.add(panel);
        frame.setVisible(true);

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

用户登录之后才能进入主页 用户注销之后就不能进入主页

  1. 用户登录之后 向Session中放入用户的数据
  2. 进入主页的时候要判断用户是否已经登录

要求在过滤器中实现

HttpServletRequest  request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;

Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);

if (user_session == null){
    response.sendRedirect("/error.jsp");
}

chain.doFilter(req,resp);

JDBC

image-20240603113420889

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-connector-java 5.1.47.jar

导入数据库依赖

<!--MySQL的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

用IDEA连接上创建的数据库或者已经有的数据库

JDBC固定步骤:

1、加载驱动

2、连接数据库,代表数据库

3、向数据库发送SQL对象Statement,用来执行CRUD

4、编写SQL(根据业务,编写不同的SQL)

5、执行SQL

6、关闭连接

代码实现

public class TextJdbc {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 配置信息
        //useUnicode=true&characterEncoding=utf8 解决中文乱码问题
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
        String username = "root";
        String password = "631062568";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        //3.向数据库发送SQL的对象Statement:CRUD
        Statement statement = connection.createStatement();
        //4.编写SQL
        String sql = "select * from users";
        //5.执行SQL,返回一个ResultSet 结果集
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
            System.out.println("id = " + resultSet.getInt("id"));
            System.out.println("name = " + resultSet.getString("name"));
            System.out.println("password = " + resultSet.getString("password"));
            System.out.println("email = " + resultSet.getString("email"));
            System.out.println("birthday = " + resultSet.getDate("birthday"));
            System.out.println("============================================================");
        }

        //6.关闭连接,释放资源(一定要做)
        resultSet.close();
        statement.close();
        connection.close();

    }
}

预编译SQL

public class TextJdbc2 {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 配置信息
        //useUnicode=true&characterEncoding=utf8 解决中文乱码问题
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
        String username = "root";
        String password = "631062568";

        //1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2、连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3、编写SQL
        String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";

        //4、预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,6);
        preparedStatement.setString(2,"Tom");
        preparedStatement.setString(3,"123456");
        preparedStatement.setString(4,"123456@qq.com");
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));

        //5、执行SQL
        int i = preparedStatement.executeUpdate();

        if (i > 0){
            System.out.println("插入成功");
        }

        //6.关闭连接,释放资源(一定要做)
        preparedStatement.close();
        connection.close();

    }

}

事务

要么都成功,要么都失败

ACID原则:保证数据的安全

原子性:要么全部完成,要么都不完成

一致性:总数不变,数据不变且正确

隔离性:多个线程互不干扰

持久性:一旦提交不可逆,持久到数据库

隔离性的问题:

脏读:一个事务读取了另一个没有提交的事务

不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变

虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致

开启事务

事务提交 commit()

事务回滚 rollback()

关闭事务

Junit单元测试

依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行

posted @ 2025-02-26 17:03  LYQ学Java  阅读(18)  评论(0)    收藏  举报