JavaWeb基础02
JSP
什么是JSP
Java Servlet Pages Java服务器端页面 也和Servlet一样 用于动态Web技术
xxxxxxxxxx19 1
写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页面中使用
在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标签 了解
核心标签 ( 掌握部分 ) --> 示例
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 模型 视图 控制器
早些年的架构 -->
用户直接访问控制层 控制层就可以直接操作数据库
servlet--CRUD-->数据库
弊端 程序十分臃肿 不利于维护 servlet的代码中 处理请求 响应 视图跳转 处理JDBC 处理业务代码 处理逻辑代码
架构 没有什么是加一层解决不了的
程序员调用
|
JDBC
|
Mysql Oracle sqlServer...
MVC三层架构
Model
- 业务处理 --> 业务逻辑 (Service)
- 数据持久层 --> CRUD (Dao)
View
- 展示数据
- 提供连接发起Servlet请求 (a form img...)
Controller ( Servlet )
- 接收用户的请求 --> (req --> 请求参数 Session信息)
- 交给业务层处理对应的代码
- 控制视图的跳转
登录 --> 接收用户的登录请求 --> 处理用户的请求(获取用户登陆的参数 username password) -->
交给业务层处理登录业务(判断用户名 密码是否正确: 业务) --> Dao层查询用户名和密码是否正确 --> 数据库
Filter 重点
Filter --> 过滤器 用来过滤网站的数据
- 处理中文乱码
- 登录验证...
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>
监听器
实现一个监听器的接口
-
编写一个监听器
实现监听器的接口 重写里面的方法
// 统计网站在线人数监听 统计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. 自动销毁
*/
}
- web.xml中注册监听器
<!--配置Session自动销毁时间 以分钟为单位-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
- 看情况是否使用
过滤器和监听器常见应用
监听器在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);
}
});
}
}
用户登录之后才能进入主页 用户注销之后就不能进入主页
- 用户登录之后 向Session中放入用户的数据
- 进入主页的时候要判断用户是否已经登录
要求在过滤器中实现
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
需要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注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行

浙公网安备 33010602011771号