1.JSP(Java Serve Page)
1.1前情提要
为什么之前要将Control和View分开写呢?不是更麻烦么?
在昨天的代码中,View中只负责视图,主要代码是html代码,Java代码较少,使得修改代码很麻烦,因此就需要引入JSP技术,使得JSP专门负责视图部分代码的书写,使得修改视图的代码更加方便简单。
1.2JSP和html文件的关系
- 先查看apache-tomcat-9.0.90\work文件夹,发现没有内容
- 将存放在apache-tomcat-9.0.90\webapps\StuCour文件夹下的StuList.html文件改名为StuList.jsp
- 随后通过浏览器请求访问该资源(注意导包)
- 在apache-tomcat-9.0.90\work文件夹中出现一个新文件夹Catalina,进入文件夹后会发现存放的是webapps中的文件夹
- 选中StuCour,不断深入会发现StuList_jsp.java和StuList_jsp.class两个文件,如下图
- 打开StuList_jsp.java文件,浏览大致内容
- JSP页面翻译成的StuList_jsp继承了org.apache.jasper.runtime.HttpJspBase类,HttpJspBase类是HttpServlet的一个子类,因此JSP页面翻译成的StuList_jsp是HttpServlet的一个孙子类。所以jsp文件本质上是个Servlet
- 继续向下浏览,发现里面包含html代码,说明我们可以通过JSP来负责先前的View,用来书写html代码和Java代码,使修改浏览器显示界面更加简单便捷,这也是为什么要细分Control和View的一大原因。
1.3JSP实现Java代码
- 在JSP中写入Java代码
// <% Java表达式 %> <% int x = 1; %>
- 在JSP中写入变量
<%int x = 1; %> //法1 <%= x %> //法2 <% out.print(x)%>
- 在JSP中声明属性,方法
//声明属性 <%! int y =2; %> //声明方法 <%! public void fun(){ System.out.println("HelloWorld!"); } %>
- Page
//<%@ page 属性 = "属性值"%>常用来导包,import <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" import ="java.util.*,ser.*"%>
- jstl标签库 El表达式
1.先导入需要的jar包
2.利用表达式简化for循环语句
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" import ="java.util.*,ser.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% ArrayList <Student> stus =(ArrayList <Student>)request.getAttribute("stus"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table border = "1">
for循环建表的第一种方式
<tr> <th>No.</th> <th>name</th> <th>sex</th><th>age</th> </tr>
<% for(Student stu:stus) {
int id = stu.getId();
String name = stu.getName();
String sex = stu.getSex();
int age = stu.getAge();
%>
<tr><td><%=id%></td><td><%=name%></td><td><%=sex%></td><td><%=age%></td></tr>
<% } %>
///利用El表达式化简的for循环表达式
注意点1:${stu.id}中表示利用stu.getId来获得id,所以在创建Student类时就需要将getId等方法按规范书写清楚,如果当时是自己创建的名字GetId或其他,这句就会报错
/注意点2:<c:forEach items="${requestScope.stus}" var="stu"> 中的c,是第三行中prefix="c"定义的,c可改成其他名字,一般设置为c
///注意点3:"${requestScope.stus}" var="stu"中的stus表示从requestScope中接收过来的数据设置为stus,改为其他名字也不报错,stu为每组数据的名字,改为其他的也可以
<tr> <th>No.</th> <th>name</th> <th>sex</th><th>age</th> </tr>
<c:forEach items="${requestScope.stus}" var="stu">
<tr><td>${stu.id}</td><td>${stu.name}</td><td>${stu.sex}</td><td>${stu.age}</td></tr>
</c:forEach>
</table>
</body>
</html>
1.4原View代码与现JSP代码对比
在FirstWeb中,存放html文件位置新建一个JSP文件,用来代替先前的View的作用,更改StuListServlet.java中转发地址的"StuListView"为"StuList.jsp",发现浏览器搜索StuListServlet正常实现显示功能。
原StuListView代码:
package ser;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuListView extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据
ArrayList <Student> stus =(ArrayList <Student>)request.getAttribute("stus"); //request.getAttribute只能传回Object数据,所以需要我们向下转为String
System.out.println(stus.get(1).getId());
PrintWriter pw = response.getWriter();
//2.发送给浏览器 View
pw = response.getWriter();
pw.println("<!DOCTYPE html>");
pw.println("<html>");
pw.println("<head><title>Student List</title></head>");
pw.println("<body>");
pw.println("<table border='1'>");
pw.println("<tr><th>NO.</th><th>name</th><th>sex</th><th>age</th></tr>");
for(Student stu:stus) {
int id = stu.getId();
String name = stu.getName();
String sex = stu.getSex();
int age = stu.getAge();
pw.println("<tr><td>"+id+"</td><td>"+name+"</td><td>"+sex+"</td><td>"+age+"</td></tr>");
}
pw.println("</table>");
pw.println("</body></html>");
}
}
现JSP文件代码
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" import ="java.util.*,ser.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% ArrayList <Student> stus =(ArrayList <Student>)request.getAttribute("stus"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table border = "1">
<tr> <th>No.</th> <th>name</th> <th>sex</th><th>age</th> </tr>
<% for(Student stu:stus) {
int id = stu.getId();
String name = stu.getName();
String sex = stu.getSex();
int age = stu.getAge();
%>
<tr><td><%=id%></td><td><%=name%></td><td><%=sex%></td><td><%=age%></td></tr>
<% } %>
<tr> <th>No.</th> <th>name</th> <th>sex</th><th>age</th> </tr>
<c:forEach items="${requestScope.stus}" var="stu">
<tr><td>${stu.id}</td><td>${stu.name}</td><td>${stu.sex}</td><td>${stu.age}</td></tr>
</c:forEach>
</table>
</body>
</html>
运行结果正常:
2.学生选课系统
2.1MVC设计模式
约定大于配置,在书写代码时,都要按照该模式进行书写,虽然会繁琐点,但是在团队合作书写代码时会更加顺利便捷,而且广泛的约定可以不断推动新的更便捷的功能的实现。如上文中的${stu.id},如果在设计Student类时不使用getId()方法,使用其他名字的话,该功能就不能被正常使用。
2.2利用MVC设计模式实现学生选课系统
2.2.1实现Dao持久层
该模块的作用是访问数据库,读取数据,修改数据等
代码如下,只需将先前代码StuListServlet中与数据库相关代码复制过来,再进行异常处理即可
package ser;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
public class StuDao {
//对接数据库
public List <Student> stuListAll(){
Connection con = null; //因为在try外要使用con,所以con的定义必须在try外部
ArrayList <Student> stus = new ArrayList <Student> ();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/stucour" ,"root" ,"");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from student");
while(rs.next())
{
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setSex(rs.getString("sex"));
stu.setAge(rs.getInt("age"));
stus.add(stu);
}
}catch(Exception e)
{
e.printStackTrace();
}
try {
con.close();//为什么不放在第一个try中,而是放在后面,因为对于第一个异常处理来说,如果发现异常,那永远不会执行con.close();而这一步是必须要执行的,所以需要放在第一个异常处理之后
}catch (Exception e1) {
e1.printStackTrace();
}
return stus;//与con.close()原因一致
}
}
2.2.2实现Service类
该模块的作用是实现各种业务。
通过分析可知,这里要的业务,其实在Dao中已经实现了,这里的代码其实有点多此一举,实际上没什么用,但是这就是约定大于配置,大家都这样写,我们在书写代码时也要注意规范。具体代码如下
package ser;
import java.util.*;
public class StuService {
StuDao stuDao = new StuDao(); //将其写为属性,后续可以一直用,如果在方法内设置,有多个方法时
//查询全部学生
public List <Student> stuListAll(){
return stuDao.stuListAll();
}
}
2.2.3实现Controller类
该模块的功能是接收请求和决定请求去向,代码如下
package ser;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.*;
import java.util.*;
public class StuListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
StuService stuService = new StuServiceImp();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List <Student> stus = stuService.stuListAll();
request.setAttribute("stus", stus);
///界面为昨天的StuListView时
// request.getRequestDispatcher("StuListView").forward(request, response);
//界面为今天的StuList.jsp时
request.getRequestDispatcher("StuList.jsp").forward(request, response);
}
}
2.2.4接口
上述代码已经实现了学生选课系统的MVC设计模式,但是仍可以进行部分内容的优化,例如在Dao层和Service层,大部分情况下都是要实现多个方法的,使用接口来设计这两个模块会更加地规范,简单,再通过DaoImp类和ServiceImp类来具体实现功能,具体代码如下
package ser;
import java.util.*;
public interface StuDao {
public List <Student> stuListAll();
}
package ser;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
public class StuDaoImp implements StuDao{
//对接数据库
public List <Student> stuListAll(){
Connection con = null;
ArrayList <Student> stus = new ArrayList <Student> ();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/stucour" ,"root" ,"");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from student");
while(rs.next())
{
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setSex(rs.getString("sex"));
stu.setAge(rs.getInt("age"));
stus.add(stu);
}
}catch(Exception e)
{
e.printStackTrace();
}
try {
con.close();
}catch (Exception e1) {
e1.printStackTrace();
}
return stus;
}
}
package ser;
import java.util.*;
public interface StuService {
public List <Student> stuListAll();
}
package ser;
import java.util.*;
public class StuServiceImp implements StuService{
StuDao stuDao = new StuDaoImp();
@Override
public List<Student> stuListAll(){
return stuDao.stuListAll();
}
}
2.3Web model4.0和2.5的区别
2.3.1 Web 2.5
有Web.xml配置文件,内容如下:
2.3.2Web4.0
无web.xml文件,在代码中直接修改配置文件,如下:
2.3.3 优劣分析
Web2.5:
- 配置文件放在一块,便于查找
- 在代码编译后仍可以修改访问资源
Web4.0:
- 可直接在代码程序中修改,修改类名后会自动修改配置文件
使用4.0的原因:
- 即使被分开到各个代码程序块中,仍然很好查找,所以2.5优势不大
- 在代码编译后,为了规范性,一般与类名一致,不进行修改申请访问资源,所以2.5优势不大
2.4规范实现学生选课系统
2.4.1具体规范格式
- 学生选课系统(学生模块)
项目名称(StuCour)
student(package)
controller(package)
StuListServlet.java(/StuListServe)
model(package)
Student(实体类)
service(package)
StuService.java (服务层接口)
imp(package)
StuServiceImp(服务层实现类)
dao(package)
StuDao.java(持久层接口)
imp(package)
SyuDaoImp(持久层实现类)
WebApp
WEB-INF
META-INF
student(文件夹)
stuList.jsp
stuAdd.jsp
stuUpd.jsp
具体样例:
2.4.2代码实现
2.3.2.1实现model
package student.model;
public class Student {
private int id;
private String name;
private String sex;
private int age;
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 getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2.4.2.2实现Dao
package student.dao;
import student.model.*;
import java.util.*;
public interface StuDao {
//查询全部
public List <Student> listAll();
//根据id查询一个
public Student listById(int id);
//添加一个
public boolean save(Student stu);
//根据id修改一个
public boolean update(Student stu);
//根据id删除一个
public boolean del(int id);
}
package student.dao.imp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import student.dao.StuDao;
import student.model.*;
public class StuDaoImp implements StuDao{
@Override
public List<Student> listAll() {
// TODO Auto-generated method stub
Connection con = null;
ArrayList <Student> stus = new ArrayList <Student> ();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/stucour" ,"root" ,"");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from student");
while(rs.next())
{
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setSex(rs.getString("sex"));
stu.setAge(rs.getInt("age"));
stus.add(stu);
}
}catch(Exception e)
{
e.printStackTrace();
}
try {
con.close();
}catch (Exception e1) {
e1.printStackTrace();
}
return stus;
}
@Override
public Student listById(int id) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean save(Student stu) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean update(Student stu) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean del(int id) {
// TODO Auto-generated method stub
return false;
}
}
2.4.2.3实现Service
package student.service;
import java.util.*;
import student.model.*;
public interface StuService {
//查询全部
public List <Student> listAll();
//根据id查询一个
public Student listById(int id);
//添加一个
public boolean save(Student stu);
//根据id修改一个
public boolean update(Student stu);
//根据id删除一个
public boolean del(int id);
}
package student.service.imp;
import java.util.List;
import student.dao.imp.StuDaoImp;
import student.dao.StuDao;
import student.model.Student;
import student.service.StuService;
public class StuServiceImp implements StuService{
StuDao stuDao = new StuDaoImp();
@Override
public List<Student> listAll() {
// TODO Auto-generated method stub
return stuDao.listAll();
}
@Override
public Student listById(int id) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean save(Student stu) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean update(Student stu) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean del(int id) {
// TODO Auto-generated method stub
return false;
}
}
2.4.2.4实现Controller
package student.controller;
import java.io.IOException;
import java.util.List;
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 student.model.Student;
import student.service.*;
import student.service.imp.StuServiceImp;
/**
* Servlet implementation class StuListServlet
*/
@WebServlet("/StuListServlet")
public class StuListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
StuService stuService = new StuServiceImp();
List <Student> stus = stuService.listAll();
request.setAttribute("stus", stus);
request.getRequestDispatcher("student/stu_list.jsp").forward(request, response);
}
}
2.4.2.5实现View
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" import ="java.util.*,student.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table border = "1">
<tr> <th>No.</th> <th>name</th> <th>sex</th><th>age</th> </tr>
<c:forEach items="${requestScope.stus}" var="stu">
<tr>
<td>${ stu.id }</td>
<td>${ stu.name }</td>
<td>${ stu.sex }</td>
<td>${ stu.age }</td>
</tr>
</c:forEach>
</table>
</body>
</html>