一、MVC设计模式
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。
使用MVC设计模式被分成三个核心层:
1、模型层(Model):操作数据库的独立的操作控件,或使用JavaBean(POJO)保存数据。
2、视图层(View):此层主要是负责将内容显示给用户。比如:JSP。
3、控制层(Contruller):此层主要负责所有的用户请求参数,判断请求参数是否合法,根据请求的类型调用模型层执行操作并将最终的处理结果交由显示层进行显示。例如:Servlet
实例:本实例采用MVC模式实现一个前端与后台的交互--登录与注册,并且用到MySQL数据库中的查询与插入,在实例中数据库的相关操作被放在模型层中,并且用pojo来保存数据,控制层则使用Servlet对前端提交来的数据进行处理然后交给数据库,视图层则用JSP来展示,将相应的结果显示在浏览器上。
数据库工具代码:
package util;
import java.sql.*;
import pojo.User;
public class DBUtil {
static {
try {
//加载数据库驱动程序
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","076249");
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//注册方法
public static int register(String regName,String regPwd) {
int count = 0;
Connection conn = getConnection();
PreparedStatement ps = null;
if(conn != null) {
String sql = "insert into user(name,pass)values(?,?)";
try {
ps = conn.prepareStatement(sql);
ps.setString(1,regName);
ps.setString(2,regPwd);
count = ps.executeUpdate();//执行插入语句,返回影响行数
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
ps.cancel();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return count;
}
//登录方法
public static User login(String logName,String logPwd) {
User user = null;
Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
if(conn != null) {
String sql = "select u_id,name,pass from user where name=? and pass=?";
try {
ps = conn.prepareStatement(sql);
ps.setString(1,logName);
ps.setString(2,logPwd);
rs = ps.executeQuery();//查询,返回结果集
if(rs.next()) {
int id = rs.getInt("u_id");
String name = rs.getString("name");
String pass = rs.getString("pass");
user = new User(id,name,pass);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
ps.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return user;
}
}
Java通用类--User,用来保存从数据库中查询到的数据,进行封装
package pojo;
public class User {
private Integer u_id;
private String name;
private String pass;
public User() {
}
public User(Integer u_id, String name, String pass) {
this.u_id = u_id;
this.name = name;
this.pass = pass;
}
public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
}
在本实例中先写注册界面
注册的前端用JSP写:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>注册界面</title>
</head>
<body>
<form action="${pageContext.servletContext.contextPath}/registerServlet" method="post">
注册用户名:<input type="text" name="regName" /> <br/><br/>
注册密码:<input type="password" name="regPwd" /> <br/><br/>
<input type="submit" value="注册" />
<input type="reset" value="重置" />
</form>
</body>
</html>
后台代码:
package z2k.org.servlet;
import java.io.IOException;
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 util.DBUtil;
@WebServlet(name="RegisterServlet",urlPatterns={"/registerServlet"})
public class RegisterServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String regName = req.getParameter("regName");
String regPwd = req.getParameter("regPwd");
int count = DBUtil.register(regName, regPwd);
if(count > 0) {
//重定向到登录页面
resp.sendRedirect("/JSPProject/transaction/login.jsp");
}
}
}
之后我们将项目部署到服务器中,然后在浏览器中输入http://localhost/JSPProject/transaction/register.jsp,回车之后就能显示注册界面,输入用户名和密码正确无误后会自动跳转到登录界面,然后在数据库中就能查询到注册的用户名和密码
再写登录界面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录界面</title>
</head>
<body>
<form action="${pageContext.servletContext.contextPath}/loginServlet" method="post">
用户名:<input type="text" name="logName" /> <br/><br/>
密码:<input type="password" name="logPwd" /> <br/><br/>
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</form>
</body>
</html>
后台代码:
package z2k.org.servlet;
import java.io.IOException;
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 pojo.User;
import util.DBUtil;
@WebServlet(name="LoginServlet",urlPatterns= {"/loginServlet"})
public class LoginServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String logName = req.getParameter("logName");
String logPwd = req.getParameter("logPwd");
User user = DBUtil.login(logName, logPwd);
if(user != null) {
HttpSession session = req.getSession();
session.setAttribute("user",user);//只有登录成功后,才设置该sesison属性
req.getRequestDispatcher("/transaction/welcome.jsp").forward(req, resp);
}else {
req.setAttribute("msg", "用户名或密码错误");
req.getRequestDispatcher("/transaction/fail.jsp").forward(req, resp);
}
}
}
重启服务器,在浏览器中输入http://localhost/JSPProject/transaction/login.jsp,,回车之后,就能跳转到欢迎或者失败界面
前端的失败与欢迎界面的代码:
欢迎界面:
<%@page import="pojo.User"%>
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎界面</title>
</head>
<body>
<%
User user = (User)session.getAttribute("user");
if(user != null){
%>
<h3>欢迎<%=user.getName()%>访问本网站</h3>
<%
}else{
%>
<h3>您还未登录,请先<a href="/JSPProject/transaction/login.jsp">登录</a></h3>
<%
}
%>
</body>
</html>
失败界面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录失败页面</title>
</head>
<body>
<h3 style="color:red">用户名或密码错误,请重新<a href="/JSPProject/transaction/login.jsp">登录</a></h3>
</body>
</html>
完整的项目放在GitHub中了,感兴趣的朋友可以点击链接https://github.com/AnsrFor/web.git进行下载查看
二、JSP内置对象
在JSP中为了简化用户的开发,提供了九个内置对象,这些内置对象将由容器为用户进行实例化,而用户直接使用即可,不用像在java中那样,必须通过关键字new进行实例化对象之后才可以使用。
JSP中的九个内置对象
实例:JSP内置对象中的response、config、exception对象
用response内置对象实现页面的定时跳转,跳转到其他页面
原网页代码:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>response内置对象</title>
</head>
<body>
<h3>3秒之后跳转到index页面</h3>
<%
response.setHeader("refresh","3;URL=index.jsp"); // 定时跳转
%>
</body>
</html>
跳转网页代码:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>index.jsp</title>
</head>
<body>
<h3>跳转过来了</h3>
</body>
</html>
实现结果:
3秒之后跳转至如下页面:
config内置对象:
在使用这个之前,我们需要在web.xml中进行配置如下:
<!-- context-param配置的是上下文参数,给应用设置参数,所有的Servlet(JSP)共享这个参数 -->
<context-param>
<param-name>ctx</param-name>
<param-value>ContextParamValue</param-value>
</context-param>
<jsp-config>
<taglib>
<taglib-uri>http://www.xxx.com</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</jsp-config>
页面代码:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>config内置对象</title>
</head>
<body>
<%
ServletContext sc=config.getServletContext(); // 通过config内置对象获取ServletContext对象
String value=sc.getInitParameter("ctx");
out.println("<h3>获取到的上下文参数是:"+value+"</h3>");
%>
</body>
</html>
实现结果:
exception内置对象:
在要出现错误的页面的配置信息中如上面的<%@ page ....>中用errorPage="error.jsp"来标识要跳转的处理错误的页面,在另一个处理错误页面的配置信息中用isErreoPage="true"表明这是处理错误的页面
出错误的页面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" errorPage="error.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<%
int x=100/0;
%>
</body>
</html>
处理错误的页面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>处理错误的页面</title>
</head>
<body>
<%
String errorMsg=exception.getMessage();
out.println("<h3>有点问题:"+errorMsg+"</h3>");
%>
</body>
</html>
实现结果:
三、EL表达式语言
表达式语言(Expression Language)是JSP2.0中新增的功能。使用表达式语言(EL)可以在JSP页面进行方便的输出内容。
EL语法为:${表达式}
EL也有自己的内置对象:
pageContext、pageScope、requestScope、sessionScope、applicationScope、param、paraValues、header、headerValues、cookie、initParam
1、使用EL访问不同的属性范围:
${pageScope.属性名}
${requestScope.属性名}
${sessionScope.属性名}
${applicationScope.属性名}
注意:如果使用"${属性名}"的方式访问属性范围,则属性范围的访问顺序是pageContext、request、session、application
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL访问不同属性范围的值</title>
</head>
<body>
<%
pageContext.setAttribute("info","page范围的属性值");
request.setAttribute("info","request范围的属性值");
session.setAttribute("info","session范围的属性值");
application.setAttribute("info","application范围的属性值");
%>
<h3>page===> ${pageScope.info}</h3>
<h3>request===> ${requestScope.info}</h3>
<h3>session===> ${sessionScope.info}</h3>
<h3>application===> ${applicationScope.info}</h3>
<h3>${info}=====> ${info}</h3>
</body>
</html>
运行结果:
2、EL访问JSP内置对象
使用EL的pageContext内置对象访问JSP的内置对象。
${pageContext.对应的jsp内置对象}
例如:
EL获取上下文路径:
特殊:
${pageContext.servletContext.contextPath}
EL访问session的ID:
${pageContext.session.id}
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL访问jsp内置对象</title>
</head>
<body>
<%
String contextPath=application.getContextPath();
%>
<h3>直接通过JSP内置对象获取上下文路径:<%=contextPath%></h3>
<h3>通过EL获取上下文路径:${pageContext.servletContext.contextPath}</h3>
<h3>通过EL获取sessionID: ${pageContext.session.id}</h3>
<h3>通过EL判断当前的请求方式: ${pageContext.request.method}</h3>
</body>
</html>
运行结果:
3、EL访问参数(访问客户端发送的参数、全局参数、一组参数)
用途一:
使用EL的param内置对象访问客户端发送的参数
${param.参数名}
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL访问客户端发送的请求参数</title>
</head>
<body>
<h3>客户端发送来的username参数是:${param.username}</h3>
<h3>客户端发送来的pwd参数是:${param.pwd}</h3>
</body>
</html>
运行结果:
用途二:
使用EL的initParam内置对象访问上下文参数(全局参数)
在web.xml中配置上下文参数:
<context-param>
<param-name>admin</param-name>
<param-value>administrator</param-value>
</context-param>
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL访问全局参数(上下文参数)</title>
</head>
<body>
<h3>全局参数为ctx的值是:${initParam.ctx}</h3>
</body>
</html>
实现结果:
用途三:
使用EL的paramValues访问一组参数
${paramValues.参数名[0]} 获取提交来的第一个参数值
${paramValues.参数名[n]} 获取提交来的第(n+1)个参数
实例:用checkbox写一个爱好选择界面,当点击提交时,paranValues就会接收到选择的内容
hobby页面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>兴趣爱好页面</title>
</head>
<body>
<form action="paramValues.jsp" method="post">
运动: <input type="checkbox" name="hobby" value="sport"/> <br/>
电影: <input type="checkbox" name="hobby" value="movie"/> <br/>
读书: <input type="checkbox" name="hobby" value="reading"/> <br/>
音乐: <input type="checkbox" name="hobby" value="music"/> <br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
paramValues页面:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL访问一组参数</title>
</head>
<body>
<h3>爱好是:</h3>
<h3> ${paramValues.hobby[0]} </h3>
<h3> ${paramValues.hobby[1]} </h3>
<h3> ${paramValues.hobby[2]} </h3>
<h3> ${paramValues.hobby[3]} </h3>
</body>
</html>
运行结果:
4、访问cookie
通过EL的cookie内置对象访问JSESSIONID名称的cookie语法:
${cookie["JSESSIONID"].name}
${cookie["JSESSIONID"].value}
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL的cookie内置对象访问Cookie</title>
</head>
<body>
<h3>Cookie名为JSESSIONID的值为: ${cookie["JSESSIONID"].value}</h3>
<h3>sessionID为:${pageContext.session.id}</h3>
</body>
</html>
运行结果:
5、访问header
使用EL的header内置对象请求header信息
${header["cookie"]}
EL的运算符
1、算数运算符
+ - * /(div) %(mod)
eg:${param.num1+param.num2} 参数相加
2、关系运算符
<(lt) >(gt) ==(eq) !=(ne) >=(ge) <=(le)
3、逻辑运算符
&&(and) ||(or) !(not)
4、empty运算符
${empty 表达式} 判断是否为null或空字符串
5、三目运算符
${返回true或false的表达式?"为true时输出的内容":"为false时输出的内容"}
6、括号运算符
()用来改变运算顺序
实例:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>EL运算符</title>
</head>
<body>
<h3>num1+num2= ${param.num1+param.num2}</h3>
<h3>num1/num2= ${param.num1 / param.num2} 也可以div ${param.num1 div param.num2}</h3>
<h3>num1是否等于num2: ${param.num1 == param.num2}</h3>
<h3>true && true: ${true && true}</h3>
<h3>true || false: ${true || false}</h3>
<h3>${empty param.abc}</h3>
<h3>三目运算符:${param.num1>param.num2 ? "num1真的大于num2":"num1不大于num2" }</h3>
</body>
</html>
运行结果:
四、JSTL(JSP Standard Tag Libraries)
引入JSTl的步骤:
第一步:将jstl-xx.jar导入/WEB-INF/lib文件夹下
第二步:将jstl-xx.jar解压后的META-INF文件夹下的xxx.tld文件拷贝到/WEB-INF/的某目录下
第三步:在JSP页面使用taglib指令引入xxx.tld文件
JSP页面使用taglib指令引入xxx.tld文件
<%@ taglib uri="指向xxx.tld文件的路径" prefix="JSTL标签前缀 "%>
注意:uri中指向xxx.tld文件的路径有两种写法:
第一种:直接指向xxx.tld文件的路径
第二种:在web.xml中配置taglib的uri
<jsp-config>
<taglib>
<taglib-uri>http://www.xxx.com</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</jsp-config>
1、输出标签
<c:out value="输出的内容,支持EL" default="默认值,支持EL" />
2、设置标签
设置属性范围的属性值
<c:set var="属性名" value="属性值,支持EL" scope="属性范围" />
设置对象的属性值
<c:set target="${perObj}" property="对象属性名" value="支持EL" />
3、捕获异常标签
<c:catch var="保存异常信息的属性名">
//又可能发生异常的代码
</c:catch>
4、判断标签
<c:if test="判断表达式,支持EL">
//判断结果为true,执行此处
</c:if>
5、forEach标签(遍历list集合或Map集合)
<c:forEach var="当前正在遍历的对象,作为属性用(msg)" items="要遍历的集合,支持EL">
${msg}
</c:forEach>
6、choose标签
<c:choose>
<c:when test="${param.score>=90}">
<h3>优秀</h3>
</c:when>
<c:when test="${param.score}>=80">
<h3>良好</h3>
</c:when>
<c:otherwise>
<h3>不及格,要努力</h3>
</c:otherwise>
</c:choose>