1. 会话技术
- 会话:一次会话中包含多次请求和响应
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内的多次请求间共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
1.1 Cookie
1.1.1 快速入门
-
概念:客户端会话技术,将数据保存在客户端
-
使用步骤:
-
创建Cookie对象,绑定数据
new Cookie(String name, String value)
-
发送Cookie对象
response.addCookie(Cookie cookie)
-
获取所有Cookie,拿到数据
Cookie[] getCookies()
package com.mark.cookie; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; /** * Cookie快速入门 */ @WebServlet("/cookieDemo1") public class CookieDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建Cookie对象,绑定数据 Cookie cookie = new Cookie("msg", "HeHe"); //2.发送Cookie对象 response.addCookie(cookie); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
@WebServlet("/cookieDemo2") public class CookieDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //3.获取Cookie Cookie[] cookies = request.getCookies(); //获取数据,遍历Cookies if (cookies != null) { for (Cookie c : cookies) { String name = c.getName(); String value = c.getValue(); System.out.println(name + ": " + value); } } /* JSESSIONID: 5F22E6A6804B8AB0A5E144849D7E51C1 msg: HeHe Webstorm-ec1c0726: 62f9d3ca-a2fa-4d36-aef6-9086650fec79 */ } }
-
1.1.2 实现原理分析
基于响应头set-cookie和请求体cookie实现
1.1.3 Cookie的细节
-
一次可否发送多个Cookie?
- 可以
- 创建多个Cookie对象,使用response调用多次addCookie()方法即可
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie1 = new Cookie("msg", "HeHe"); response.addCookie(cookie1); Cookie cookie2 = new Cookie("name","mark"); response.addCookie(cookie2); }
-
Cookie在浏览器中保存时间?
- 默认情况下当浏览器关闭后,Cookie数据被销毁
- 持久化存储:
setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的文件中。持久化存储。正数代表存活时间。
- 负数:默认值
- 零:删除Cookie信息
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie1 = new Cookie("msg", "setMaxAge"); // cookie1.setMaxAge(300);//设置存活时间,将cookie持久化硬盘,300s后删除cookie文件 // cookie1.setMaxAge(-1);//设置存活时间,默认值 cookie1.setMaxAge(0);//设置存活时间,删除Cookie信息 response.addCookie(cookie1); }
-
cookie能否存中文?
- 在tomcat8之前,Cookie不能直接存储中文数据
- 需要将中文数据转码---一般采用URL编码(%E3)
- 在tomcat8之后,Cookie支持中文数据。不支持特殊字符,建议使用URL编码存储
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie1 = new Cookie("msg", "你好"); response.addCookie(cookie1); //msg: 你好 }
- 在tomcat8之前,Cookie不能直接存储中文数据
-
Cookie共享问题
-
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享
- 默认情况下Cookie不能共享
setPath(String path)
:设置Cookie的获取范围。默认情况下,会去设置当前的虚拟目录
cookie1.setPath("/");//在当前服务器的根目录下的所有项目可共享数据
-
不同的tomcat服务器间Cookie共享问题?
setDomain(String path)
:如果设置一级域名相同,那么多个服务器之间cookie可以共享- eg:
setDomain(".baidu.com")
,那么tieba.baidu.com和news.baidu.com中cookie可以共享
- eg:
-
1.1.4 Cookie的特点和作用
- 特点
- Cookie存储数据在客户端浏览器
- 浏览器对于单个Cookie的大小有限制(4kb),以及对同一个域名下的总Cookie数量也有限制(20个)
- 作用:
- cookie一般用来存储少量的不太敏感的数据
- 在不登陆的情况下,完成服务器对客户端的身份识别
1.1.5 案例:记住上次访问时间
-
需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
-
分析:
- 可以采用Cookie完成
- 在服务器的Servlet中判断是否有一个名为lastTime的cooike
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:
- 写回Cookie:lastTime=
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=
- 有:不是第一次访问
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); boolean flag = false; //获取所有Cookie Cookie[] cookies = request.getCookies(); //遍历cookie数组 if (cookies != null && cookies.length > 0) { for (Cookie c : cookies) { //获取cookie的名称 String name = c.getName(); if ("lastTime".equals(name)) { flag = true; //响应数据 String value = c.getValue(); value = URLDecoder.decode(value, "utf-8"); response.getWriter().write("欢迎回来,您上次访问时间为:" + value); //设置cookie的value //获取当前时间字符串,重新设置cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); str_date = URLEncoder.encode(str_date, "UTF-8"); c.setValue(str_date); c.setMaxAge(60 * 60 * 24 * 30); response.addCookie(c); break; } } } if (cookies == null || cookies.length == 0 || flag == false) { flag = true; //设置cookie的value //获取当前时间字符串,重新设置cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); str_date = URLEncoder.encode(str_date, "UTF-8"); Cookie c = new Cookie("lastTime", str_date); response.addCookie(c); response.getWriter().write("您好,欢迎您首次访问"); } }
1.2 Session
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
1.2.1 快速入门
HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
-
步骤:
- 获取Session对象
- 存数据
- 获取Session对象
- 获取数据
@WebServlet("/sessionDemo1") public class SessionDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用Session共享对象 //1.获取session HttpSession session = request.getSession(); //2.存数据 session.setAttribute("msg","hello session"); } }
@WebServlet("/sessionDemo2") public class SessionDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用Session共享对象 //1.获取session HttpSession session = request.getSession(); //2.获取数据 Object msg = session.getAttribute("msg"); System.out.println(msg); } }
1.2.2 实现原理分析
Session的实现依赖于Cookie,通过请求头和响应头实现
1.2.3 Session细节
-
当客户端关闭后,服务器不关闭,两次获取Session是否为同一个?
- 默认情况下不是
//期望关闭客户端后,session也能相同:保存到客户端 Cookie cookie = new Cookie("JSESSIONID",session.getId()); cookie.setMaxAge(60*60);
-
客户端不关闭,服务器关闭,两次获取的Session是否为同一个?
- 不是同一个,但是要确保数据不丢失
- Session的钝化
- 在服务器正常关闭之前,将Session对象序列化到硬盘上
- Session的活化
- 在服务器启动后,将Session文件转化到内存中的Session对象即可
- Session的钝化
- 服务器会自动完成Session的钝化和活化,但是IDEA不会
- 不是同一个,但是要确保数据不丢失
-
Session什么时候被销毁?
- 服务器关闭
- Session对象调用方法
void invalidate()
- Session的默认失效时间:30min(可以在Tomcat的配置文件D:\Tomcat\apache-tomcat-8.5.81\conf\web.xml中修改<session-config>标签的值)
1.2.4 Session的特点
-
Session用于存储一次会话的多次请求的数据,存在服务器端
- 可以在重定向时代替ServletContext
-
Session可以存储任意类型、任意大小的数据
-
Session与Cookie的区别
- Session存储在服务器端,Cookie在客户端
- Session没有数据大小限制,而Cookie有
- Session数据安全,Cookie相对于较不安全
1.2.5 案例:登陆案例2.0
-
需求:
- 访问带有验证码的登录页面login.jsp
- 用户输入用户名,密码以及验证码。
- 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
-
分析:
-
实现:
-
创建login.jsp登录页面
<%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/3 Time: 18:28 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Login</title> <script> window.onload = function () { var img = document.getElementById("checkCode"); img.onclick = function () { img.src = "/LoginTest2/CheckCodeServlet?" + new Date().getTime(); } var a = document.getElementById("change"); a.onclick = function () { img.src = "/LoginTest2/CheckCodeServlet?" + new Date().getTime(); } } </script> <style> div { color: red; } </style> </head> <body> <form action="/LoginTest2/LoginServlet" method="post"> <table> <tr> <td>用户名</td> <td><input type="text" name="username" placeholder="请输入用户名"></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" placeholder="请输入密码"></td> </tr> <tr> <td>验证码</td> <td><input type="text" name="checkCode" placeholder="请输入验证码"></td> </tr> <tr> <td><img id="checkCode" src="/LoginTest2/CheckCodeServlet"></td> <td><a id="change" href="#">看不清,换一张</a></td> </tr> <tr> <td colspan="2"><input type="submit" value="登录"></td> </tr> </table> </form> <div> <%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%> </div> <div> <%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%> </div> </body> </html>
-
创建验证码img
package com.mark.web; import javax.imageio.ImageIO; 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 java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/CheckCodeServlet") public class CheckCodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //创建一个对象,在内存中代表图片(验证码图片对象) int width = 100; int height = 50; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); //美化图片 //填充背景色 Graphics g = image.getGraphics();//画笔对象 g.setColor(Color.PINK);//设置画笔颜色 g.fillRect(0, 0, width, height);//填充颜色 //画边框 g.setColor(Color.BLUE); g.drawRect(0, 0, width - 1, height - 1); //写验证码 String str = "QWERTYUIOPASDGFHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789"; //生成随机角标 Random random = new Random(); StringBuilder sb=new StringBuilder(); for (int i = 1; i <= 4; i++) { int index = random.nextInt(str.length()); //获取字符 char ch = str.charAt(index); sb.append(ch); g.drawString(ch + "", width / 5 * i, height / 2); } String checkCode_session = sb.toString(); request.getSession().setAttribute("checkCode_session",checkCode_session); //干扰线 g.setColor(Color.GREEN); for (int i = 1; i < 10; i++) { //随机生成坐标点 int x1 = random.nextInt(width); int x2 = random.nextInt(width); int y1 = random.nextInt(height); int y2 = random.nextInt(height); g.drawLine(x1, y1, x2, y2); } //将图片输出到页面展示 ImageIO.write(image, "jpg", response.getOutputStream()); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
创建JavaBean
package com.mark.domain;
/**
-
@ClassName User
-
@Description TODO 用户的JavaBean(实体类)
-
@Author Mark
-
@Date 2022/7/31 20:44
-
@Version 1.0
*/
public class User {
private int id;
private String username;
private String password;public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}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;
}@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + ''' +
", password='" + password + ''' +
'}';
}
}
```
-
-
创建JDBC工具类
package com.mark.util; 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.SQLException; import java.util.Properties; /** * @ClassName JDBCUtils * @Description TODO JDBC工具类 使用Druid连接池 * @Author Mark * @Date 2022/7/31 20:50 * @Version 1.0 */ public class JDBCUtils { private static DataSource ds; static { //加载配置文件 Properties pro =new Properties(); //使用classLoader加载配置文件,获取字节输入流 InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); try { pro.load(is); } catch (IOException e) { e.printStackTrace(); } //初始化连接池 try { ds = DruidDataSourceFactory.createDataSource(pro); } catch (Exception e) { e.printStackTrace(); } } //获取连接池对象 public static DataSource getDataSource(){ return ds; } //获取连接Connection对象 public static Connection getConnection() throws SQLException { return ds.getConnection(); } }
-
操作数据库中User表
package com.mark.dao; import com.mark.domain.User; import com.mark.util.JDBCUtils; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; /** * @ClassName UserDao * @Description TODO 操纵数据库中User表的类 * @Author Mark * @Date 2022/7/31 20:48 * @Version 1.0 */ public class UserDao { //声明JDBCTemplate对象共用 private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); /** * 登陆方法 * @param loginUser 只有用户名和密码 * @return User包含用户全部数据, 没有查询到,返回null */ public User login(User loginUser) { try { String sql = "select * from user where username=? and password = ?"; User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword()); return user; } catch (DataAccessException e) { e.printStackTrace();//记录日志 return null; } } }
-
创建登录LoginServlet
package com.mark.web; import com.mark.dao.UserDao; import com.mark.domain.User; import org.apache.commons.beanutils.BeanUtils; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置request编码格式为utf-8 request.setCharacterEncoding("utf-8"); //获取所有参数的map集合 Map<String, String[]> parameterMap = request.getParameterMap(); //创建User集合 User loginUser = new User(); //使用BeanUtils封装JavaBean try { BeanUtils.populate(loginUser, parameterMap); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //获取页面输入的验证码 String checkCode = request.getParameter("checkCode"); //获取Session HttpSession session = request.getSession(); //获取绘制的验证码 String checkCode_session = (String) session.getAttribute("checkCode_session"); //在获取后就移除session防止在登录后回退验证码还能生效 session.removeAttribute("checkCode_session"); //判断验证码输入是否正确 if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)) { //验证码正确 //查询数据库 UserDao dao = new UserDao(); User user = dao.login(loginUser); if (user == null) { //查询为空 //存储提示信息到request request.setAttribute("login_error", "用户名或密码错误"); //转发到登录页面 request.getRequestDispatcher("/login.jsp").forward(request, response); } else { //登陆成功 session.setAttribute("user", user.getUsername()); response.sendRedirect(request.getContextPath() + "/success.jsp"); } } else { //验证码正确 //存储提示信息到request request.setAttribute("cc_error", "验证码错误"); //转发到登录页面 request.getRequestDispatcher("/login.jsp").forward(request, response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
2. JSP(了解即可)
-
概念:Java Server Pages:java服务器页面
- 可理解为一个特殊的页面,其中既可以直接定义HTML的标签,又可以编写Java代码
- 用于简化书写
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <% System.out.println("hello jsp"); %> <h1>hi~jsp</h1> </body> </html>
2.1 原理
- JSP本质上就是Servlet
2.2 JSP的脚本
JSP的脚本:JSP定义Java代码的方式
-
<& 代码 &>
:定义的Java代码在service方法中。service中可以定义什么,该脚本就可以定义什么<% System.out.println("hello jsp"); int i = 5;//局部变量 %>
-
<&! 代码 &>
:定义的Java代码在jsp转换后的java类的成员位置。<%! int i = 3;//成员变量 %>
-
<&= 代码 &>
:定义的Java代码会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。<%= i + "hello" // 5hello 会打印局部变量%>
2.3 JSP的内置对象
-
在jsp页面中不需要获取和创建,直接可以使用的对象称为JSP的内置对象
-
一共有9个内置对象
-
request
-
response
-
out:字符输出流对象。可以将数据输出到页面上。和response.getWrite()类似
-
response.getWrite()和out.write()区别:前者永远会先于后者输出
在tomcat服务器真正给客户端浏览器做出响应前,会先找response缓冲区数据,再找out缓冲区数据
-
-
2.4 改造Cookie案例
<%@ page import="java.net.URLDecoder" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.net.URLEncoder" %><%--
Created by IntelliJ IDEA.
User: Mark
Date: 2022/8/2
Time: 19:39
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>
<%
boolean flag = false;
//获取所有Cookie
Cookie[] cookies = request.getCookies();
//遍历cookie数组
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
//获取cookie的名称
String name = c.getName();
if ("lastTime".equals(name)) {
flag = true;
//响应数据
String value = c.getValue();
value = URLDecoder.decode(value, "utf-8");
%>
<h1>欢迎回来,您上次访问时间为:<%=value%>></h1>
<%
//设置cookie的value
//获取当前时间字符串,重新设置cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
str_date = URLEncoder.encode(str_date, "UTF-8");
c.setValue(str_date);
c.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(c);
break;
}
}
}
if (cookies == null || cookies.length == 0 || flag == false) {
flag = true;
//设置cookie的value
//获取当前时间字符串,重新设置cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
str_date = URLEncoder.encode(str_date, "UTF-8");
Cookie c = new Cookie("lastTime", str_date);
response.addCookie(c);
%>
<h1>您好,欢迎您首次访问</h1>
<%
}
%>
</body>
</html>
2.5 JSP的指令
-
作用:用于配置JSP页面,导入资源文件
-
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2%>
-
分类:
-
page:配置JSP页面
-
contentType:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前JSP页面的编码(只能是高级的IDE才能生效,如果是低级工具,需要设置pageEncoding属性设置当前页面的字符集编码)
-
pageEcoding:设置当前JSP页面的编码
-
import:导包
-
errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
<%@ page errorPage="error.jsp" %>
-
isErrorPage:表示当前页面是否为错误页面。true/false
- 默认为false。当设置为true时就可以使用内置对象exception。可以将错误消息输出到日志文件中
-
-
include:在当前页面中导入项目中其他的页面
<%@ include file="top.jsp" %>
-
taglib:导入资源。一般用于导入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
prefix:前缀(自定义)
-
2.6 JSP的注释
-
html注释:
<!-- -->
:只能注释html代码片段 -
JSP注释:推荐使用
<%-- --%>
:可注释所有
2.7 所有的内置对象
在JSP页面中不需要创建,直接使用的对象
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 一次请求访问的对个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面(Servlet)的对象,可理解为this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
前四个:域对象。用于共享数据
3. MVC开发模式
3.1 jsp演变历史
- 早期只有Servlet,只能使用response输出标签数据,非常麻烦
- 后来有了JSP,简化可Servlet的开发。但如果过度使用JSP,在JSP中既写大量Java代码,又写HTML标签,会造成难以维护,难于分工协作,难于阅读
- 再后来,Java的Web开发,借鉴MVC开发模式,使得程序的设计更加合理性
3.2 MVC开发模式详解
MVC:将一个程序分为M、V、C三个部分。
- M:Model,模型。JavaBean
- 完成具体的业务操作,如查询数据库,封装对象
- V:View,视图。JSP
- 展示数据
- C:Controller,控制器。Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
3.3 MVC的优缺点
- 优点:
- 耦合性低,方便维护,利于分工协作
- 重用性高
- 缺点:
- 使得项目架构变得复杂,对开发人员要求很高
4. EL表达式
4.1 概述
- 概念:Expression Language 表达式语言
- 作用:替换和简化jsp页面中java代码的编写
- 语法:
${表达式}
eg:${3 > 4}
输出false - 注意:
- JSP默认支持EL表达式
- 当在page指令中设置
isELIgnored
为true时将不会解析此页面的EL表达式 - 在$前加反斜线将不会解析此EL表达式:
\${3 > 4}
4.2 使用
-
运算
-
运算符:
- 算术运算符:+ - * /(div) %(mod)
- 比较运算符: > < >= <= == !=
- 逻辑运算符:&&(and) ||(or) !(not)
- 空运算符:empty
- 用于判断字符串、集合、数组对象是否为null并且长度是否为0
${empty list}
<%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/7 Time: 17:22 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> ${3 > 4} \${3 > 4} <hr> <h3>算数运算符</h3> ${3 + 4}<br> ${3 / 4}<br> ${3 div 4}<br> ${3 % 4}<br> ${3 mod 4}<br> <h3>比较运算符</h3> ${3 == 4}<br> ${3 != 4}<br> <h3>逻辑运算符</h3> ${3 > 4 && 3 < 4}<br> ${3 > 4 and 3 < 4}<br> <h3>空运算符</h3> ${3 > 4 && 3 < 4}<br> ${3 > 4 and 3 < 4}<br> </body> </html>
-
-
获取值
-
EL表达式只能从域对象中获取值
-
语法:
${域名称.键名}
:从指定域中获取指定键的值- 域名称:
pageScope
--->pageContextrequestScope
--->requestsessionScope
--->sessionapplicationScope
--->application(ServletContext)
- 域名称:
${键名}
:表示依次从最小的域中查找是否又该键对应的值,直到找到为止。
<%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/7 Time: 22:32 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>获取域中的数据</title> </head> <body> <% //在域中存储数据 request.setAttribute("name", "zhangsan"); session.setAttribute("age", 21); session.setAttribute("name", "lisi"); %> <h3>EL获取值</h3> ${requestScope.name} ${sessionScope.age} ${sessionScope.haha}<%--当为null时返回空字符串,不会影响页面布局--%> ${name}<%--zhangsan--%> ${sessionScope.name}<%--lisi--%> </body> </html>
-
获取对象、List集合、Map集合的值
-
对象:
${域名称.键名.属性名}
- 本质上会去调用对象的getter方法
<%@ page import="com.mark.domain.User" %> <%@ page import="java.util.Date" %><%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/7 Time: 22:57 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>获取数据</title> </head> <body> <% User user = new User(); user.setName("zhangsan"); user.setAge(21); user.setBirthday(new Date()); request.setAttribute("u", user); %> <h3>获取对象的值</h3> ${requestScope.u}<br> <%-- 通过对象的属性获取 setter或getter方法,去掉set或get,再将剩余部分首字母变为小写,得到的内容称之为属性 setName ---> Name --->name --%> ${requestScope.u.name} ${requestScope.u.age} ${requestScope.u.birthday}<br> ${requestScope.u.birthday.month}<%--7--%><br> ${requestScope.u.birStr} <%-- 2022-08-07 23:14:37--%> </body> </html>
/** * 逻辑视图 * @return */ public String getBirStr() { //1.格式化日期 if (birthday != null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //2.返回字符串 return sdf.format(birthday); } else { return ""; } }
-
Map集合
${域名称.键名.key名称}
<%@ page import="com.mark.domain.User" %> <%@ page import="java.util.*" %><%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/7 Time: 23:20 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>获取集合数据</title> </head> <body> <% Map map = new HashMap<>(); map.put("name", "zhangsan"); map.put("gender", "male"); request.setAttribute("map", map); %> <h3>获取map值</h3> ${map.name} ${map.gender}<%--male--%> ${map["gender"]}<%--male--%> </body> </html>
-
-
-
空运算符的使用:
- 用于判断字符串、集合、数组对象是否为null并且长度是否为0
${empty str}
${not empty str}
:判断字符串、集合、数组对象是否不为null并且长度不为0
<h4>empty运算符</h4> <% // String str= "abc"; String str= null; request.setAttribute("str",str); %> ${empty str} <%--false--%> <%--true--%> ${not empty str} <%--false--%>
-
隐式对象:
- el表达式中有11个隐式对象
- pageContext:
- 获取其他8个内置对象
${pageContext.request.contextPath}
5. JSTL标签
5.1 概述
-
概念:JavaServer Page Tag Library JSP标准标签库
是由Apache组织提供的开源的JSP标签
-
作用:用于简化和替换jsp页面的java代码
-
使用步骤:
- 导入JSTL相关jar包
- 引入标签库:taglib指令
<%@ taglib%>
- 使用标签
5.2 常用的JSTL标签
-
if:相当于Java的if语句
- 属性
- test是必须属性 接收boolean表达式
- 如果表达式为ture,则显示if标签体内容,如果为false,则不显示标签体内容
- 如果有else情况,则可以再定义一个
c:if
标签
- test是必须属性 接收boolean表达式
- 属性
-
choose:相当于Java的switch语句
- 完成数字编号对应星期几案例
- 在域中存储数字
- 使用choose标签取出数字(相当于switch)
- 使用when标签做数字判断(相当于case)
- otherwise标签做其他情况声明(相当于default)
<% request.setAttribute("number",3); %> <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>你输入的数字有误</c:otherwise> </c:choose>
- 完成数字编号对应星期几案例
-
foreach:相当于Java的for循环语句
-
完成重复的操作
for(int i = 0;i < 10;i++){ ... }
- 属性:
- begin:开始值(包含)
- end:结束值(包含)
- var:临时变量
- stee:步长(临时遍历每次加几)
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
- 属性:
-
遍历容器
List<User> list = new ArrayList<>(); for(User user : list){ ... }
- 属性:
- items:容器对象
- var:容器中元素的临时变量
- 属性:
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s"> ${i} ${s.index} ${s.count}<br> </c:forEach> <%-- 1 1 1 3 3 2 5 5 3 7 7 4 9 9 5 --%> <%--遍历容器--%> <hr> <% List list=new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); request.setAttribute("list",list); %> <c:forEach items="${list}" var="str" varStatus="s" > ${s.index} ${s.count} ${str} <br> </c:forEach> <%--0 1 aaa--%> <%--1 2 bbb--%> <%--2 3 ccc--%>
-
5.3 小练习
- 需求:
- 在request域中有一个存有User对象的List集合
- 需要使用JSTL+EL将list集合数据展示到jsp页面的表格table中
<body>
<%
// User user =new User();
// List<User> list =new ArrayList<User>();
List<User> list = new ArrayList<>();
list.add(new User("zhangsan", 23, new Date()));
list.add(new User("lisi", 24, new Date()));
list.add(new User("wangwu", 25, new Date()));
request.setAttribute("list", list);
%>
<table border="1" width="500" align="center">
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>生日</th>
</tr>
<c:forEach items="${list}" var="user" varStatus="s">
<c:if test="${s.count % 2 == 0}">
<tr bgcolor="red">
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.birStr}</td>
</tr>
</c:if>
<c:if test="${s.count % 2 != 0}">
<tr bgcolor="green">
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.birStr}</td>
</tr>
</c:if>
</c:forEach>
</table>
</body>
6. 三层架构
三层架构:软件设计架构
- 界面层(表示层):用户看得到的界面,用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的
- 数据访问层:操作数据存储文件
6.1 用户信息列表展示案例
-
需求:用户信息的增删改查操作
-
设计:
-
技术选型:Servlet+JSP+MySql+JDBCTemplate+Durid+BeanUtils+Tomcat
-
数据库设计:
create Database db4; use db4; create table user( id int primary key auto_increment, name varchar(20) not null, gender varchar(6), age int, address varchar(32), qq varchar(20), email varchar(50) );
-
-
开发:
-
环境搭建
- 创建数据库环境
- 创建项目,导入需要的jar包
-
编码
- 分析:
-
实现⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐:
-
编写domain下的JavaBean
package com.mark.domain; /** * @ClassName User * @Description TODO * @Author Mark * @Date 2022/8/14 18:12 * @Version 1.0 */ public class User { private int id; private String name; private String gender; private int age; private String address; private String qq; private String email; 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 String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } 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; } public String getQq() { return qq; } public void setQq(String qq) { this.qq = qq; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", age=" + age + ", address='" + address + '\'' + ", qq='" + qq + '\'' + ", email='" + email + '\'' + '}'; } }
-
将index.html资源文件转化为index.jsp页面,修改超链接为
${pageContext.request.contextPath}/userListServlet
<%-- Created by IntelliJ IDEA. User: Mark Date: 2022/8/14 Time: 17:58 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>首页</title> <!-- 1. 导入CSS的全局样式 --> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- 2. jQuery导入,建议使用1.9以上的版本 --> <script src="js/jquery-2.1.0.min.js"></script> <!-- 3. 导入bootstrap的js文件 --> <script src="js/bootstrap.min.js"></script> <script type="text/javascript"> </script> </head> <body> <div align="center"> <a href="${pageContext.request.contextPath}/userListServlet" style="text-decoration:none;font-size:33px">查询所有用户信息 </a> </div> </body> </html>
-
在web目录下servlet包中创建UserListServlet,修改路径为
/userListServlet
package com.mark.web.servlet; import com.mark.domain.User; import com.mark.service.UserService; import com.mark.service.impl.UserServiceImpl; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.util.List; @WebServlet("/userListServlet") public class UserListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
在UserListServlet首先调用UserService完成查询
-
在service下创建接口UserService:用户管理的业务接口
package com.mark.service; import com.mark.domain.User; import java.util.List; //用户管理的业务接口 public interface UserService { /** * 查询所有用户信息 * @return */ public List<User> findAll(); }
-
在service下的impl包下创建UserService的实现类UserServiceImpl,调用Dao完成查询
package com.mark.service.impl; import com.mark.dao.UserDao; import com.mark.dao.impl.UserDaoImpl; import com.mark.domain.User; import com.mark.service.UserService; import java.util.List; /** * @ClassName UserServiceImpl * @Description TODO * @Author Mark * @Date 2022/8/14 18:20 * @Version 1.0 */ public class UserServiceImpl implements UserService { @Override public List<User> findAll() { //调用Dao完成查询 return dao.findAll(); } }
-
在dao下创建接口UserDao:用户操作的Dao
package com.mark.dao; import com.mark.domain.User; import java.util.List; //用户操作的Dao public interface UserDao { public List<User> findAll(); }
-
在dao下的impl包下创建UserDao的实现类UserDaoImpl,使用JDBC操作数据库
package com.mark.dao.impl; import com.mark.dao.UserDao; import com.mark.domain.User; import com.mark.util.JDBCUtils; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /** * @ClassName UserDaoImpl * @Description TODO * @Author Mark * @Date 2022/8/14 18:22 * @Version 1.0 */ public class UserDaoImpl implements UserDao { private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); @Override public List<User> findAll() { //使用JDBC操作数据库 } }
-
在UserServiceImpl中创建UserDao对象,使用dao.findAll()查询所有数据
private UserDao dao = new UserDaoImpl(); @Override public List<User> findAll() { //调用Dao完成查询 return dao.findAll(); }
-
在Servlet中完成业务逻辑
//1.调用UserService完成查询 UserService service = new UserServiceImpl(); List<User> users = service.findAll(); //将List存入request域 request.setAttribute("users", users); //转发到list.jsp页面 request.getRequestDispatcher("/list.jsp").forward(request,response);
-
完成UserDaoImpl中使用JDBC操作数据库
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); @Override public List<User> findAll() { //使用JDBC操作数据库 //1.定义sql String sql = "select * from user"; List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class)); return users; }
-
将list.html资源文件转化为list.jsp页面,将死数据修改为活数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <!-- 网页使用的语言 --> <html lang="zh-CN"> <head> <!-- 指定字符集 --> <meta charset="utf-8"> <!-- 使用Edge最新的浏览器的渲染方式 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。 width: 默认宽度与设备的宽度相同 initial-scale: 初始的缩放比,为1:1 --> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>用户信息管理系统</title> <!-- 1. 导入CSS的全局样式 --> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- 2. jQuery导入,建议使用1.9以上的版本 --> <script src="js/jquery-2.1.0.min.js"></script> <!-- 3. 导入bootstrap的js文件 --> <script src="js/bootstrap.min.js"></script> <style type="text/css"> td, th { text-align: center; } </style> </head> <body> <div class="container"> <h3 style="text-align: center">用户信息列表</h3> <table border="1" class="table table-bordered table-hover"> <tr class="success"> <th>编号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>籍贯</th> <th>QQ</th> <th>邮箱</th> <th>操作</th> </tr> <c:forEach items="${requestScope.users}" var="user" varStatus="s"> <tr> <td>${s.count}</td> <td>${user.name}</td> <td>${user.gender}</td> <td>${user.age}</td> <td>${user.address}</td> <td>${user.qq}</td> <td>${user.email}</td> <td><a class="btn btn-default btn-sm" href="update.html">修改</a> <a class="btn btn-default btn-sm" href="">删除</a></td> </tr> </c:forEach> <tr> <td colspan="8" align="center"><a class="btn btn-primary" href="add.html">添加联系人</a></td> </tr> </table> </div> </body> </html>
-
-
-
测试
-
部署运维
7. 综合练习
基于6.1案例完成
- 简单功能:
- 列表查询
- 登录
- 添加
- 删除
- 修改
- 复杂功能
- 删除选中
- 分页查询
- 复杂条件查询
7.1 登录功能
- 调整页面,加入验证码功能
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>管理员登录</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
//切换验证码
function refreshCode() {
//获取验证码的图片对象
var vcode = document.getElementById("vcode");
//设置其src属性,获取时间戳
vcode.src = "${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
}
</script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">管理员登录</h3>
<form action="${pageContext.request.contextPath}/loginServlet" method="post">
<div class="form-group">
<label for="user">用户名:</label>
<input type="text" name="username" class="form-control" id="user" placeholder="请输入用户名"/>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
</div>
<div class="form-inline">
<label for="vcode">验证码:</label>
<input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码"
style="width: 120px;"/>
<a href="javascript:refreshCode()"><img src="${pageContext.request.contextPath}/checkCodeServlet"
title="看不清点击刷新" id="vcode"/></a>
</div>
<hr/>
<div class="form-group" style="text-align: center;">
<input class="btn btn btn-primary" type="submit" value="登录">
</div>
</form>
<!-- 出错显示的信息框 -->
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span>×</span></button>
<strong>${requestScope.login_msg}</strong>
</div>
</div>
</body>
</html>
- 验证码Servlet
package com.mark.web.servlet;
import javax.imageio.ImageIO;
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 java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码
*/
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长80,宽30的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 80;
int height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体",Font.BOLD,24));
//向图片上写入验证码
g.drawString(checkCode,15,25);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
- 登录Servlet
package com.mark.web.servlet;
import com.mark.domain.User;
import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
request.setCharacterEncoding("utf-8");
//2.获取数据
//获取用户填写的验证码
String verifycode = request.getParameter("verifycode");
//获取所有数据
Map<String, String[]> map = request.getParameterMap();
//3.校验验证码
HttpSession session = request.getSession();
String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
//确保验证码一致性
session.removeAttribute("CHECKCODE_SERVER");
if (!checkcode_server.equalsIgnoreCase(verifycode)) {
//验证码不正确
//提示信息
request.setAttribute("login_msg", "验证码错误!");
//跳转登录页面
request.getRequestDispatcher("/login.jsp").forward(request, response);
return;
}
//4.封装User对象
User user = new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//5.调用Service对象查询
UserService service = new UserServiceImpl();
User loginUser = service.login(user);
//6.判断是否登录成功
if (loginUser != null) {
//登录成功
//将用户存到session
session.setAttribute("user", loginUser);
//跳转页面
response.sendRedirect(request.getContextPath() + "/index.jsp");
} else {
//登录失败
//提示信息
request.setAttribute("login_msg", "用户名或密码错误!");
//跳转登录页面
request.getRequestDispatcher("/login.jsp").forward(request, response);
return;
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
7.2 添加功能
- 功能分析
- 功能实现
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- HTML5文档-->
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>添加用户</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<center><h3>添加联系人页面</h3></center>
<form action="${pageContext.request.contextPath}/addUserServlet" method="post">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" name="gender" value="男" checked="checked"/>男
<input type="radio" name="gender" value="女"/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" class="form-control" id="address">
<option value="广东">广东</option>
<option value="广西">广西</option>
<option value="湖南">湖南</option>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交"/>
<input class="btn btn-default" type="reset" value="重置"/>
<input class="btn btn-default" type="button" value="返回"/>
</div>
</form>
</div>
</body>
</html>
package com.mark.web.servlet;
import com.mark.domain.User;
import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.beans.JavaBean;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet("/addUserServlet")
public class AddUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
request.setCharacterEncoding("utf-8");
//2.获取所有数据
Map<String, String[]> map = request.getParameterMap();
//3.封装对象
User user = new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//4.调用service完成保存
UserService service = new UserServiceImpl();
service.addUser(user);
//跳转到userListServlet
response.sendRedirect(request.getContextPath() + "/userListServlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
在UserService中添加addUser方法
@Override
public void addUser(User user) {
dao.addUser(user);
}
在UserDao中添加addUser方法
@Override
public void addUser(User user) {
String sql= "insert into user values(null,?,?,?,?,?,?,null,null)";
template.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail());
}
7.3 删除功能
- 功能分析
- 功能实现
修改删除按钮链接
<script>
function deleteUser(id) {
//用户安全提示
if(confirm("您确定要删除吗?")){
//访问路径
location.href="${pageContext.request.contextPath}/deleteUserServlet?id="+id;
}
}
</script>
<c:forEach items="${requestScope.users}" var="user" varStatus="s">
<tr>
<th><input type="checkbox"></th>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td>
<a class="btn btn-default btn-sm" href="update.html">修改</a>
<a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a>
<%--这里的user.id中的user就是forEach循环中var的user--%>
</td>
</tr>
</c:forEach>
添加DeleteUserServlet
package com.mark.web.servlet;
import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/deleteUserServlet")
public class DeleteUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取id
String id = request.getParameter("id");
//2.调用service删除
UserService userService = new UserServiceImpl();
userService.deleteUser(id);
//跳转到查询所有Servlet
response.sendRedirect(request.getContextPath() + "/userListServlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
在UserService添加方法deleteUser
@Override
public void deleteUser(String id) {
dao.deleteUser(Integer.parseInt(id));
}
在UserDao中添加方法deleteUser
@Override
public void deleteUser(int id) {
String sql = "delete from user where id = ?";
template.update(sql,id);
}
7.4 修改功能
- 功能分析
-
功能实现
-
回显操作
修改list.jsp页面的修改按钮超链接
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>
添加FindUserServlet
package com.mark.web.servlet; import com.mark.domain.User; import com.mark.service.UserService; import com.mark.service.impl.UserServiceImpl; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/findUserServlet") public class FindUserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取id String id = request.getParameter("id"); //2.调用Service查询 UserService service=new UserServiceImpl(); User user = service.findUserById(id); //3.将user存入request request.setAttribute("user",user); //4.将request转发到update.jsp request.getRequestDispatcher("/update.jsp").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
在UserService中添加findUserById方法
@Override public User findUserById(String id) { return dao.findUserById(Integer.parseInt(id)); }
在UserDao中添加findUserById方法
@Override public User findUserById(int id) { String sql = "select * from user where id = ?"; return template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id); }
修改update.jsp进行回显
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <!-- 网页使用的语言 --> <html lang="zh-CN"> <head> <!-- 指定字符集 --> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>修改用户</title> <link href="css/bootstrap.min.css" rel="stylesheet"> <script src="js/jquery-2.1.0.min.js"></script> <script src="js/bootstrap.min.js"></script> </head> <body> <div class="container" style="width: 400px;"> <h3 style="text-align: center;">修改联系人</h3> <form action="" method="post"> <div class="form-group"> <label for="name">姓名:</label> <input type="text" class="form-control" id="name" name="name" value="${user.name}" readonly="readonly" placeholder="请输入姓名"/> </div> <div class="form-group"> <label>性别:</label> <c:if test="${user.gender == '男'}"> <input type="radio" name="sex" value="男" checked />男 <input type="radio" name="sex" value="女"/>女 </c:if> <c:if test="${user.gender == '女'}"> <input type="radio" name="sex" value="男" />男 <input type="radio" name="sex" value="女" checked />女 </c:if> </div> <div class="form-group"> <label for="age">年龄:</label> <input type="text" class="form-control" id="age" value="${user.age}" name="age" placeholder="请输入年龄"/> </div> <div class="form-group"> <label for="address">籍贯:</label> <select name="address" class="form-control" id="address"> <c:if test="${user.address == '广东'}"> <option value="广东" selected>广东</option> <option value="北京">北京</option> <option value="广西">广西</option> <option value="湖南">湖南</option> </c:if> <c:if test="${user.address == '北京'}"> <option value="广东">广东</option> <option value="北京" selected>北京</option> <option value="广西">广西</option> <option value="湖南">湖南</option> </c:if> <c:if test="${user.address == '广西'}"> <option value="广东">广东</option> <option value="北京">北京</option> <option value="广西" selected>广西</option> <option value="湖南">湖南</option> </c:if> <c:if test="${user.address == '湖南'}"> <option value="广东">广东</option> <option value="北京">北京</option> <option value="广西">广西</option> <option value="湖南" selected>湖南</option> </c:if> </select> </div> <div class="form-group"> <label for="qq">QQ:</label> <input type="text" class="form-control" name="qq" id="qq" value="${user.qq}" placeholder="请输入QQ号码"/> </div> <div class="form-group"> <label for="email">Email:</label> <input type="text" class="form-control" name="email" id="email" value="${user.email}" placeholder="请输入邮箱地址"/> </div> <div class="form-group" style="text-align: center"> <input class="btn btn-primary" type="submit" value="提交"/> <input class="btn btn-default" type="reset" value="重置"/> <input class="btn btn-default" type="button" value="返回"/> </div> </form> </div> </body> </html>
-
修改操作
设置提交表单路径,设置隐藏域
<form action="${pageContext.request.contextPath}/updateUserServlet" method="post"> <div class="form-group"> <!--隐藏域 提交id--> <input type="hidden" name="id" value="${user.id}">
添加UpdateUserServlet
package com.mark.web.servlet; import com.mark.domain.User; import com.mark.service.UserService; import com.mark.service.impl.UserServiceImpl; import org.apache.commons.beanutils.BeanUtils; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.Set; @WebServlet("/updateUserServlet") public class UpdateUserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.设置编码 request.setCharacterEncoding("utf-8"); //2.获取map Map<String, String[]> map = request.getParameterMap(); /*Set<String> keyset =map.keySet(); for (String name : keyset) { //根据key键获取值 String[] values = map.get(name); System.out.println(name); for (String value : values) { System.out.println(value); } System.out.println("---------"); } */ //3.创建对象 User user = new User(); try { BeanUtils.populate(user, map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } // System.out.println(user); //html的name,要和封装属性值set的参数名称一致,如果不这样做,那么使用BeanUtils.populate()封装时,里面的键值就会为null //4.调用UserService UserService service = new UserServiceImpl(); service.updateUser(user); //5.查询所有Servlet response.sendRedirect(request.getContextPath() + "/userListServlet"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
在UserService中添加updateUser方法
@Override public void updateUser(User user) { dao.updateUser(user); }
在UserDao中添加updateUser方法
@Override public void updateUser(User user) { String sql = "update user set name = ? , gender = ? ,age = ? , address = ? , qq = ? , email = ? where id = ?"; template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail(), user.getId()); }
-
7.5 删除选中功能
- 功能分析
-
代码实现
选中id通过表单提交checkbox获取
<script> window.onload = function () { //给删除选中按钮添加单机事件 document.getElementById("delSelect").onclick = function () { //完成表单提交 document.getElementById("delForm").submit(); } } </script> <form id="delForm" action="${pageContext.request.contextPath}/delSelectedServlet" method="post"> <table border="1" class="table table-bordered table-hover"> <tr class="success"> <th><input type="checkbox"></th> <th>编号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>籍贯</th> <th>QQ</th> <th>邮箱</th> <th>操作</th> </tr> <c:forEach items="${requestScope.users}" var="user" varStatus="s"> <tr> <th><input type="checkbox" name="uid" value="${user.id}"></th> <td>${s.count}</td> <td>${user.name}</td> <td>${user.gender}</td> <td>${user.age}</td> <td>${user.address}</td> <td>${user.qq}</td> <td>${user.email}</td> <td> <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a> <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a> <%--这里的user.id中的user就是forEach循环中var的user--%> </td> </tr> </c:forEach> </table> </form>
编写delSelectedServlet
package com.mark.web.servlet; import com.mark.service.UserService; import com.mark.service.impl.UserServiceImpl; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/delSelectedServlet") public class DelSelectedServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取所有id String[] ids = request.getParameterValues("uid"); //调用Service UserService service = new UserServiceImpl(); service.delSelectedUser(ids); //跳转到查询所有Servlet response.sendRedirect(request.getContextPath() + "/userListServlet"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
在UserService下添加delSelectedUser方法
@Override public void delSelectedUser(String[] ids) { //遍历数字 for (String id : ids) { //调用dao删除 dao.deleteUser(Integer.parseInt(id)); } }
全选全不选功能实现
//全选全不选功能 //获取第一个checkbox document.getElementById("firstCheckBox").onclick = function () { //获取下边列表中所有的CheckBox var cbs = document.getElementsByName("uid") for (var i = 0; i < cbs.length; i++) { //设置这些cbs[i]的checked状态 = firstCheckBox.checked cbs[i].checked = this.checked; } }
在Sevice应该判断一下ids是否为空(或者在前端遍历cbs,有选中则提交),为空则不提交
@Override public void delSelectedUser(String[] ids) { if (ids != null && ids.length > 0) { //遍历数字 for (String id : ids) { //调用dao删除 dao.deleteUser(Integer.parseInt(id)); } } }