一、Jsp使用
脚本+输出表达式
-
三大指令
1). 第一个指令:page 默认的属性: contentType:指定响应的编码格式 language:jsp支持java语言 buffer:缓冲区大小 默认指定8kb (需要给浏览器写入内容) 需要借助流对象:JspWriter import:导入相关的包 session: true:表示已经存在会话了 (自己使用:true) false:(不是禁用会话),阻止jsp和后台servlet之间针对没有产生用户的会话 高流量的网站,session设置为false,可以大大节省的服务器的内存空间! autoFlush:true 开启自动刷新 isELIgnored:是否忽略el表达式 true(忽略) false:不忽略 pageEncoding:当前页面编码格式
举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"
isELIgnored="false" session="true" autoFlush="true" import="java.util.*" buffer="8kb" %>
<%--
<html>
<head>
<title>page指令</title>
</head>
<body>
<%--
jsp注释
HttpSession:域对象 浏览器和服务器之间的产生的会话存储起来(用户相关的信息)
setAttribute("name","张三")
--%>
<%
//获取HttpSession
//public HttpSession getSession()
//
//在后台上:获取session,给session存储一个内容
//当前访问这个jsp页面,获取到绑定属性
HttpSession httpSession = request.getSession() ; //如果存在session对象,就获取sesison
String name = (String) httpSession.getAttribute("name");
out.write("获取到了"+name);
%>
</body>
</html>
web容器 servlet—>提供注解:@WebServlet
当前注解中的属性name指定 serlvet-name ,可以省略不写,默认当前类名
urlPatterns:指定映射路径 数组:一般指定一个路径即可!
/user/login
/user/register
loadOnStartup:配置servlet初始化时机 数字越大优先级越小
@WebServlet(urlPatterns = “/servletDemo”)
举例:
@WebServlet(value = "/servletDemo")
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//创建session
//如果第一次使用:就是创建
public HttpSession getSession():创建session
HttpSession session = request.getSession();
//存储内容
session.setAttribute("name","杨德财");
System.out.println("保存成功");
//Session的范围比request范围: 在一次会话中有效!
//请求转发
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
2). incluse:静态包含
<%@ include file="路径.jsp"%>
file可以包含任意的jsp页面:
公共jsp页面被其他页面共用的时候,就可以使用静态包含(不会将被包含进来的jsp页面单独进行翻译和编译)
特点:
节省内存空间
只是将被包含的jsp页面的内容加载进来!
共用的导航栏以及底部导航栏都可以使用@include指令静态包含
举例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--包含logo部分--%>
<%@include file="logo.jsp" %>
<%@include file="daohang.jsp"%>
<html>
<head>
<title>include指令</title>
</head>
<body>
</body>
</html>
jsp的常见的内置对象:
在jsp被翻译成对应的java文件
_jspService() 服务方法
四个域对象 作为jsp的内置对象
PageContext pageContext
HttpServletRequest request
HttpSession session
ServletContext application
ServletConfig config
JspWriter out 一种输出流对象
Object page(this):代表当前jsp翻译后的java文件所在的类的实例
Throwable t :异常对象:异常的顶层对象
内置对象经常使用的这个四个对象
PageContext pageContext
***HttpServletRequest request
***HttpSession session
ServletContext application
try{
int i = 10 ;
System.out.println(i/0);
}catch (ArithmeticException e){
e.printStackTrace();
}
3). taglib指令:导包jstl.jar、standed.jar
1)导包:
jstl核心包 :jstl-1.2.jar
standard-1.1.2.jar 标准包
2)在jsp页面上使用targlib指令
<%@targlib prefix="c" uri="" %>
3)就可以使用c标签
c:标签名称
4)前提条件要使用核心标签库,--->使用el表达式
el表达式${}替代jsp输出表达式
举例:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>targlib指令</title>
</head>
<body>
<h3>jsp输出表达式</h3>
<%
//给request域对象中存储String数据
pageContext.setAttribute("user","张三");
request.setAttribute("user","admin"); //相当于给Map集合中添加key,value
session.setAttribute("user","杨德财") ;
application.setAttribute("user","高圆圆");
String username = (String) request.getAttribute("user");
%>
<%--
输出表达式获取request域对象存储的数据
--%>
<%=username%>
${requestScope.user} <%--指定域访问属性--%>
<hr/>
${user}
</body>
</html>
${域对象.属性名称}
域对象:
el中使用域
内置对象
pageScope page域 pageContext
requestScope request域 HttpServletRequest
sessionScope session域 HttpSesison
applicationScope application域 ServletContext
通过域对象.属性即可 本质就是返回Map集合
Map<String,Object>
执行:
使用el内置对象.get(String key)---->Object
javaBean规范
javaBean导航
使用el内置对象.key--->Object
在${el内置对象.属性名称} ---继续优化
不需要书写内置对象
${属性名称}
在四个域对象中搜索哪一个域对象中绑定了user属性---获取内容
---->findAttribute(String name)
javaBean是一种规范:
1)当前类是一个具体类
2)有私有字段private修饰
3)提供setXXX()getXXX()方法
4)当前类如果需要在网络中传输,实现序列化接口:serializable (目前:不考虑第四点)
举例:
public class User {
//提供一个用户名和密码两字段
private String username ;
private String password ;
//getXXX() 获取内容的/setXXX()赋值的
// el表达式: ${域对象中存储属性.xXX} get()去掉 xXX
//name是bean属性
/* public String getName() {
return username;
}
public void setName(String username) {
this.username = username;
}*/
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;
}
//jsp页面中:javabean导航
//通过el表达式 可以直接调用getXXX()方法
//XXX---称为当前类的bean属性
}
javabean:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>javabean导航</title>
<%--
el表达式来操作 javabean属性
--%>
</head>
<body>
<%
//创建User对象
User user = new User() ;
//赋值
user.setUsername("高圆圆");
user.setPassword("123456");
//将user对象存储request域中
request.setAttribute("user",user);
%>
<%--通过el表达式操作bean属性
${user} ----> (User)(request.getAttribute("user")) ---->User
--%>
${user.username} - ${user.password}
</body>
</html>
二、jsp中核心标签库中常见的标签
- c:if标签 提供判断逻辑使用
test属性
使用${}判断 如果结果为true,则执行c:if语句体;否则不执行
c:if标签针对某种条件进行判断,没有c:else标签;如果需要在判断:在使用c:if
举例:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>核心标签库</title>
</head>
<body>
<%
User user = new User() ;
user.setUsername("eric");
user.setPassword("123456");
//request域对象中
request.setAttribute("user",user);
%>
<c:if test="${user.username.equals('eric')}">
用户名一致
</c:if>
<c:if test="${!user.username.equals('eric')}">
对不起,用户名存在问题
</c:if>
<%-- 选择结构语句--%>
</body>
</html>
-
核心标签库中提供 选择结构语句
c:choose
c:when test="${xxx}" 匹配结果
c:otherwise:上面c:when都不匹配的结果<c:choose> <c:when test=""> </c:when> <c:when test=""> </c:when> <c:otherwise> </c:otherwise> </c:choose>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c:choose</title>
</head>
<body>
<%
int number = 5 ;
//给request域对象中存储了number值
request.setAttribute("number",number);
%>
<h3>c:choose标签</h3>
<c:choose>
<c:when test="${number==1}">星期一</c:when>
<c:when test="${number==2}">星期二</c:when>
<c:when test="${number==3}">星期三</c:when>
<c:when test="${number==4}">星期四</c:when>
<c:when test="${number==5}">星期五</c:when>
<c:when test="${number==6}">星期六</c:when>
<c:when test="${number==7}">星期日</c:when>
<c:otherwise>
<strong>对不起,非法数据!</strong>
</c:otherwise>
</c:choose>
</body>
</html>
-
c:foreach 两种用法
1). 普通方式: 类上于java代码普通for循环的格式 属性: begin:当前起始角标 end:结束角标(包含的) step:步长语句 var:循环中的变量名 varStatus:循环中的状态 varStatus="status" status.index:访问角标(0) status.count: 序号:1开始 2). 跟业务相关的使用方式: 需要从后台获取域对象中存储的数据 items属性: c:foreach items = "${list}" var :循环中的变量 varStatus:循环中的状态
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>c:foreach标签</title>
</head>
<body>
<%
//java代码 写一个普通for循环
for(int x = 0 ; x < 10 ; x ++){
out.print(x+"<br/>");
}
%>
<hr/>
<h3>foreach标签</h3>
<c:forEach begin="0" end="10" var="i" step="1" varStatus="status" >
<%--
取值:el表达式
--%>
${status.count} - ${i} <br/>
</c:forEach>
<hr/>
<%
//创建List集合
List<String> list = new ArrayList<String>() ;
//添加数据
list.add("JavaEE") ;
list.add("Python") ;
list.add("Web") ;
list.add("C") ;
//将list集合存储到request域中
request.setAttribute("list",list);
%>
<c:forEach items="${list}" var="p" varStatus="status">
${status.count} - ${p} <br/>
</c:forEach>
</body>
</html>
三、jsp+servlet最佳实践
后台系统:
登录功能
1)准备工作:
mysql驱动
durid连接池
common-dbutils
jstl.jar
standed.jar
junit.jar
Junit的依赖包
2)准备管理表
id adminname adminpwd
3)分包:
实体类
业务层
数据库访问层
controller层
xxxServlet
引入MVC 架构思想
-
导包,首页
<%--使用boostrap环境--%> <%--使用el表达式获取上下文路径 pageContext:是jsp中的page域 获取其他三个域对象 public ServletRequest getRequest() request是当前pageContext的bean属性 public String getContextPath() --contextPath:HttpServletRequest的bean属性 public HttpSession getSession()
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>后台管理</title>
<%--导入jquery--%>
<script src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js"></script>
<%--boostrap的全局css样式--%>
<link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
<%--boostrap的js库--%>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</head>
<frameset rows="10%,*,20%">
<frame src="admin/logo.jsp">
<frameset cols="15%,*">
<frame src="admin/menu.jsp">
<frame src="admin/main.jsp">
</frameset>
<frame src="admin/footer.jsp" >
</frameset>
<body>
<%--<input type="button" value="点击" class="btn-primary" />--%>
<%--框架标签--%>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>logo</title>
<style>
.logo{
background-color: black;
}
</style>
</head>
<body>
<div class="logo">
<a href="logo.jsp">登录</a>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>main</title>
</head>
<body>
<p>欢迎访问...</p>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>菜单</title>
<%--导入jquery--%>
<script src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js"></script>
<%--boostrap的全局css样式--%>
<link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
<%--boostrap的js库--%>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</head>
<body>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button"
id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
用户管理
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a href="#">查询所有用户</a></li>
<li><a href="#">添加用户</a></li>
</ul>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>footer</title>
</head>
<body>
<div>
<p>
<a href="#">联系我们</a>
<a href="#">招贤纳士</a>
<a href="#">投诉建议</a>
<a href="#">问题反馈</a>
<a href="#">商城用户协议</a>
</p>
<p>
xxx商城<sup>©</sup> 2021-2023
</p>
</div>
</body>
</html>
- 跳转登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>后台登录</title>
<style>
.form-class{
/*边框样式*/
border: 1px solid #000;
/*容量大小*/
width: 420px;
height: 250px;
/*设置外边距属性*/
margin: 210px 0 0 470px;
background-color: darkgray;
/* background-image: url("img/qq.jpg");
background-repeat: no-repeat;
background-position: top left;*/
}
/*给class="username"所在标签设置样式*/
.username-class{
/*设置外边距*/
margin: 40px 0 0 100px;
}
/*给class="password-class"设置样式*/
.password-class{
/*设置外边距*/
margin: 20px 0 0 100px;
}
/*给class="btn-class"设置样式*/
.btn-class{
margin: 20px 0 0 150px;
}
/*给id="btn_regist"设置外边距*/
#btn_regist{
margin-left: 30px;
}
.hobit-class{
margin: 20px 0 0 100px;
}
.tip{
color: red;
font-size: 25px;
text-align: center;
}
</style>
</head>
<body>
<div class="form-class">
<!--提交表单-->
<form action="${pageContext.request.contextPath}/login" method="get">
<%--
name属性值必须和实体类的属性名称必须一致
--%>
<div class="username-class">
用户名:<input type="text" name="username" placeholder="请输入用户名" />
</div>
<div class="password-class">
密  码:<input type="password" name="password" placeholder="请输入密码" />
</div>
<div class="btn-class">
<input type="submit" value="登录"> <br/>
<input id="btn_regist" type="checkbox" /> remerber me
</div>
</form>
<div>
<font class="tip">${msg}</font>
</div>
</div>
</body>
</html>
- 准备工作,导jar包、js等文件
druid.properties配置文件:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myee_2104
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
- 实体类com.qf.entity
public class AdminUser {
//属性名称
private String adminName ;
private String adminPassword ;
public String getAdminName() {
return adminName;
}
public void setAdminName(String adminName) {
this.adminName = adminName;
}
public String getAdminPassword() {
return adminPassword;
}
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
@Override
public String toString() {
return "AdminUser{" +
"adminName='" + adminName + '\'' +
", adminPassword='" + adminPassword + '\'' +
'}';
}
}
- 控制器放置包com.qf.controller
接收用户相关的信息:用户名和密码
调用service层,通过方法查询
import com.qf.service.AdminService;
import com.qf.service.impl.AdminServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class AdminLoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1)获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
//System.out.println(username);
// System.out.println(password);
//2)调用service层:通过用户名查询用户
AdminService adService = new AdminServiceImpl() ;
boolean flag = adService.isLogin(username, password);
if(flag){
//true,就跳转主页
//一致,将用户名存储HttpSession(存储在服务器端)
//获取session
HttpSession session = request.getSession();
session.setAttribute("user",username);
//请求转发到index.jsp页面中
request.getRequestDispatcher("/index.jsp").forward(request,response);
}else{
//false:
//給request域中存储msg
request.setAttribute("msg","用户名或者密码输入错误");
request.getRequestDispatcher("/admin/login.jsp").forward(request,response);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- 业务接口层:抽象接口以及重写根据用户名查询用户的子实现类
import com.qf.entity.AdminUser;
/**
* 针对管理员操作业务接口层
*/
public interface AdminService {
//定义功能
//根据用户名查询用户
boolean isLogin(String username,String password) ;
}
import com.qf.dao.AdminDao;
import com.qf.dao.impl.AdminDaoImpl;
import com.qf.entity.AdminUser;
import com.qf.service.AdminService;
import java.sql.SQLException;
/**
* 针对管理员用户业务接口实现层
*/
public class AdminServiceImpl implements AdminService {
@Override
public boolean isLogin(String username,String password) {
//调用dao层:完成数据的查询
AdminDao ad = new AdminDaoImpl() ;
AdminUser adminUser = ad.selectUserByName(username);
//逻辑判断
//获取查询到的用户的密码
if(adminUser.getAdminPassword().equals(password)){
//一致
return true ;
}
return false ;
}
}
- 准备连接Mysql数据库的jdbc工具类
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 加入DruidDataSource(类 实现java.sql.DataSource:物理数据源的链接))以及ThreadLocal :线程(并发)
*/
public class MyJdbcUtils {
private static DataSource dataSource = null ;
private static ThreadLocal<Connection> t1 = new ThreadLocal<Connection>() ;
//一个链接对象---相当线程
private MyJdbcUtils(){}
static{
try {
//创建一个属性集合类
Properties prop = new Properties() ;
//读取druid.properties的参数
InputStream inputStream = MyJdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
//加载属性集合列表中
prop.load(inputStream);
//通过工厂类
dataSource = DruidDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据链接
public static Connection getCoonnection(){
//声明conn变量
Connection conn = null ;
try{
//获取连接对象
//先判断 ,如果当前conn 为null
if(conn==null){
//从连接池获取到
conn = dataSource.getConnection();
//一个连接相当一一个线程
//连接对象绑定ThreadLocal中
t1.set(conn);
}
return conn ;
}catch(Exception e){
e.printStackTrace();
}
return null ;
}
//获取数据源
public static DataSource getDataSource(){
return dataSource;
}
//释放资源
//提供关闭资源方法:针对DQL语句:查询获取结果集,关闭相关资源
public static void close(ResultSet rs, Statement stmt, Connection conn) throws SQLException {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
conn.close();
//解绑:从ThreadLocal (连接使用完毕,线程就执行完毕
t1.remove();
}
}
//针对DDL,DML操作:不需要ResultSet
public static void close(Statement stmt,Connection conn) throws SQLException {
close(null,stmt,conn);
}
//开启事务
public static void setAutoCommit(Connection conn){
try {
//开启事务
conn.setAutoCommit(false); //取消自动提交
} catch (SQLException e) {
e.printStackTrace();
}
}
//如果事务的操作没有问题,提交事务并释放连接
//使用 同一个连接对象
public static void commitAndClose(Connection conn) {
try {
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放连接
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
//解绑
t1.remove(); //线程(用户操作的时候,连接对象是完毕,线程执行完毕!)
}
}
//如果执行过程中出现问题,回滚事务
public static void rollbackAndClose(Connection conn) {
try {
//事务回滚
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放连接--归还到连接池
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
//解绑
t1.remove(); //线程(用户操作的时候,连接对象是完毕,线程执行完毕!)
}
}
public static void main(String[] args) {
Connection connection = MyJdbcUtils.getCoonnection();
System.out.println(connection);
DataSource dataSource = MyJdbcUtils.getDataSource();
System.out.println(dataSource);
}
}
- 数据库访问层com.qf.Dao
根据获得的用户名去数据库校对抽象方法、以及重写方法的子实现类
import com.qf.entity.AdminUser;
import java.sql.SQLException;
/**
* 针对管理员操作的数据库访问接口层
*/
public interface AdminDao {
//根据用户名查询用户
AdminUser selectUserByName(String username) ;
}
import com.qf.dao.AdminDao;
import com.qf.entity.AdminUser;
import com.qf.utils.MyJdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
/**
* 针对管理用户的数据库访问接口实现层
*/
public class AdminDaoImpl implements AdminDao {
/**
* 根据用户名查询用户
*/
@Override
public AdminUser selectUserByName(String username){
//common-dbutils工具类
//创建QueryRunner对象
try {
QueryRunner qr = new QueryRunner(MyJdbcUtils.getDataSource()) ;
//准备sql
String sql = "select * from admin_user where adminName= ? " ;
//执行查询
AdminUser adminUser = qr.query(sql, new BeanHandler<AdminUser>(AdminUser.class), username);
System.out.println(adminUser);
return adminUser;
} catch (SQLException e) {
e.printStackTrace();
}
return null ;
}
/* public static void main(String[] args) throws SQLException {
AdminDao dao = new AdminDaoImpl() ;
AdminUser admin = dao.selectUserByName("admin");
//System.out.println(admin);
}*/
}
- 最终,数据库访问得到数据库中的用户名和密码,返回到业务接口层判断用户名和密码,进行校对;返回结果到控制类Adminservlet,给前端网页反馈是否登陆成功,最终,在网页面显示是否登陆成功。