完整版通用分页
目录
后台
框架
先创建一个Job项目
后台
1、先导入jar架包
2.创建util
21.中文乱码处理
package com.tangxinlian.util;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 中文乱码处理
*
*/
@WebFilter(filterName="encodingFiter",urlPatterns="*.action")
public class EncodingFiter implements Filter {
private String encoding = "UTF-8";// 默认字符集
public EncodingFiter() {
super();
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// 中文处理必须放到 chain.doFilter(request, response)方法前面
res.setContentType("text/html;charset=" + this.encoding);
if (req.getMethod().equalsIgnoreCase("post")) {
req.setCharacterEncoding(this.encoding);
} else {
Map map = req.getParameterMap();// 保存所有参数名=参数值(数组)的Map集合
Set set = map.keySet();// 取出所有参数名
Iterator it = set.iterator();
while (it.hasNext()) {
String name = (String) it.next();
String[] values = (String[]) map.get(name);// 取出参数值[注:参数值为一个数组]
for (int i = 0; i < values.length; i++) {
values[i] = new String(values[i].getBytes("ISO-8859-1"),
this.encoding);
}
}
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
String s = filterConfig.getInitParameter("encoding");// 读取web.xml文件中配置的字符集
if (null != s && !s.trim().equals("")) {
this.encoding = s.trim();
}
}
}
2.2获得或关闭数据库
package com.tangxinlian.util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 提供了一组获得或关闭数据库对象的方法
*
*/
public class DBAccess {
private static String driver;
private static String url;
private static String user;
private static String password;
static {// 静态块执行一次,加载 驱动一次
try {
InputStream is = DBAccess.class
.getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(is);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("pwd");
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 获得数据连接对象
*
* @return
*/
public static Connection getConnection() {
try {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void close(ResultSet rs) {
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Statement stmt) {
if (null != stmt) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Connection conn) {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Connection conn, Statement stmt, ResultSet rs) {
close(rs);
close(stmt);
close(conn);
}
public static boolean isOracle() {
return "oracle.jdbc.driver.OracleDriver".equals(driver);
}
public static boolean isSQLServer() {
return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver);
}
public static boolean isMysql() {
return "com.mysql.jdbc.Driver".equals(driver);
}
public static void main(String[] args) {
Connection conn = DBAccess.getConnection();
DBAccess.close(conn);
System.out.println("isOracle:" + isOracle());
System.out.println("isSQLServer:" + isSQLServer());
System.out.println("isMysql:" + isMysql());
System.out.println("数据库连接(关闭)成功");
}
}
2.3 创建数据库连接
#oracle9i
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:ora9
#user=test
#pwd=test
#sql2005
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#url=jdbc:sqlserver://localhost:1423;DatabaseName=test
#user=sa
#pwd=sa
#sql2000
#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
#url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB
#user=sa
#pwd=888888
#mysql5
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/tangxinlian?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
user=root
pwd=123
2.4 空字符串
package com.tangxinlian.util;
public class StringUtils {
// 私有的构造方法,保护此类不能在外部实例化
private StringUtils() {
}
/**
*如果字符串等于null或去空格后等于"",则返回true,否则返回false
*
* @param s
* @return
*/
public static boolean isBlank(String s) {
boolean b = false;
if (null == s || s.trim().equals("")) {
b = true;
}
return b;
}
/**
* 如果字符串等于null或去空格后等于"",则返回true,否则返回false
*
* @param s
* @return
*/
public static boolean isNotBlank(String s) {
return !isBlank(s);
}
}
2.5 分页工具类
package com.tangxinlian.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
//上一次查询的url
private String url;
//上一次查询所携带的查询条件
private Map<String, String[]> parameterMap = new HashMap<String, String[]>();
//对pagebean进行初始化
public void setRequest(HttpServletRequest req) {
// 初始化jsp界面传递过来的当前页
this.setPage(req.getParameter("page"));
// 初始化jsp界面传递过来的页大小
this.setRows(req.getParameter("rows"));
// 初始化jsp界面传递过来是否分页
this.setPagination(req.getParameter("pagination"));
// 保留上一次的查询请求
this.setUrl(req.getRequestURL().toString());
// 保留上一次的查询条件
this.setParameterMap(req.getParameterMap());
}
private void setPagination(String pagination) {
// 只有填写false字符串。才代表不分页
this.setPagination(!"false".equals(pagination));
}
private void setRows(String rows) {
if(StringUtils.isNotBlank(rows))
this.setRows(Integer.valueOf(rows));
}
private void setPage(String page) {
if(StringUtils.isNotBlank(page))
this.setPage(Integer.valueOf(page));
}
public PageBean() {
super();
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public void setTotal(String total) {
this.total = Integer.parseInt(total);
}
public boolean isPagination() {
return pagination;
}
public void setPagination(boolean pagination) {
this.pagination = pagination;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
// 上一页
public int getPrevPage() {
return this.page > 1 ? this.page-1 : this.page;
}
// 下一页
public int getNextPage() {
return this.page < this.getMaxPage() ? this.page+1 : this.page;
}
// 最大页
public int getMaxPage() {
return this.total % this.rows == 0 ? this.total /this.rows : (this.total /this.rows)+1;
}
}
3、创建entity Job实体类
package com.tangxinlian.entity;
public class Job {
private String id;
private String job;
private String company;
private String address;
private String salary;
private String url;
private String limit;
private String time;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLimit() {
return limit;
}
public void setLimit(String limit) {
this.limit = limit;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public Job(String id, String job, String company, String address, String salary, String url, String limit,
String time) {
super();
this.id = id;
this.job = job;
this.company = company;
this.address = address;
this.salary = salary;
this.url = url;
this.limit = limit;
this.time = time;
}
public Job() {
super();
}
@Override
public String toString() {
return "Job [id=" + id + ", job=" + job + ", company=" + company + ", address=" + address + ", salary=" + salary
+ ", url=" + url + ", limit=" + limit + ", time=" + time + "]";
}
}
4、创建dao 包
简变化的通用增删改查
package com.tangxinlian.dao;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.tangxinlian.util.DBAccess;
import com.tangxinlian.util.PageBean;
public class BaseDao<T> {
//通用查询
public List<T> executeQuery(String sql,Class clz,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
List<T> list = new ArrayList<>();
Connection con = DBAccess.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
if(pageBean != null && pageBean.isPagination()) {
// 想要分页----》列表需求
// 查询出符合条件的总记录数
String countSql = getCountSql(sql);
ps = con.prepareStatement(countSql);
rs = ps.executeQuery();
if(rs.next()) {
pageBean.setTotal(rs.getObject(1).toString());
}
// 展示想要看到的数据,就比如说第3页的十条数据
String pageSql = getPageSql(sql,pageBean);
ps = con.prepareStatement(pageSql);
rs = ps.executeQuery();
}else {
// 不想分页----》下拉框需求
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
}
while(rs.next()) {
rs.getString("bname"), rs.getFloat("price")));
/**
* Book b = new Book();
* b.setBid(rs.getInt("bid"));
* b.setBname(rs.getString("bname"));
* b.setPrice(rs.getFloat("price"));
* list.add(b);
*
* 1、实例化了一个对象
* 2、给这一个空对象的每一个属性赋值
* 3、将赋值完的对象添加到list集合中返回
*/
T t = (T) clz.newInstance();
// Field[] declaredFields = clz.getDeclaredFields();
for (Field f : clz.getDeclaredFields()) {
f.setAccessible(true);
f.set(t, rs.getObject(f.getName()));
}
list.add(t);
}
DBAccess.close(con, ps, rs);
return list;
}
private String getPageSql(String sql, PageBean pageBean) {
return sql + " limit "+pageBean.getStartIndex()+","+pageBean.getRows();
}
private String getCountSql(String sql) {
return "select count(1) from ("+sql+") t";
}
/**
* 通用增删改
* @param sql
* @param t book
* @param attrs bid,bname,price
* @return
* @throws SQLException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public int executeUpdate(String sql,T t,String[] attrs) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Connection con = DBAccess.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
int loop = 1;
Field f = null;
for (String attr : attrs) {
f = t.getClass().getDeclaredField(attr);
f.setAccessible(true);
ps.setObject(loop++, f.get(t));
}
int code = ps.executeUpdate();
DBAccess.close(con, ps, null);
return code;
}
}
增删改查的sql语句
package com.tangxinlian.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.tangxinlian.entity.Job;
import com.tangxinlian.util.PageBean;
import com.tangxinlian.util.StringUtils;
public class JobDao extends BaseDao<Job>{
public List<Job> list(Job j,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
// 查询sql的语句
List<Job> list = new ArrayList<>();
String sql = "select * from t_solr_job where true";
// 可能需要带条件查询。那么是需要拼接查询sql
String job = j.getJob();
if(StringUtils.isNotBlank(job)) {
sql += " and job like '%"+job+"%'";
}
// 如果前台jsp传递了参数到后台
String id = j.getId();
if(StringUtils.isNotBlank(id)) {
sql += " and id = '"+id+"'";
}
return super.executeQuery(sql, Job.class, pageBean);
}
public int add(Job j) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
// jsp没有向后台传递ID
j.setId(UUID.randomUUID().toString());
// 新增插入当前表的所有列
String sql = "insert into t_solr_job values(?,?,?,?,?,?,?)";
// 调用父类完成新增功能
return super.executeUpdate(sql, j, new String[] {"id","job","company","address","salary","limit","time"});
}
public int edit(Job j) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
// 修改的sql语句
String sql = "update t_solr_job set job=?,company=?,address=?,salary=?,limit=?,time=? where id=?";
// 调用父类完成修改功能
return super.executeUpdate(sql, j, new String[] {"job","company","address","salary","limit","time","id"});
}
public int del(Job j) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
String sql = "delete from t_solr_job where id=?";
return super.executeUpdate(sql, j, new String[] {"id"});
}
}
5、创建tag包 分页拼接代码
package com.tangxinlian.tag;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.tangxinlian.util.PageBean;
public class PageTag extends BodyTagSupport{
private static final long serialVersionUID = -8012081268314346782L;
private PageBean pageBean;
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
@Override
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.print(toHTML());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doStartTag();
}
private String toHTML() {
StringBuilder sb = new StringBuilder();
// 上一次查询的from表单的html拼接
sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>");
// 查第几页的数据
sb.append("<input type='hidden' name='page'>");
// 重要设置拼接操作,将上一次请求参数携带到下一次
Map<String, String[]> parameterMap = pageBean.getParameterMap();
if(parameterMap.size()>0){
Set<Entry<String,String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
if(!"page".equals(entry.getKey())){
for (String val : entry.getValue()) {
sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+val+"'>");
}
}
}
}
sb.append("</form>");
// 默认展示前面4页,当前页,后面5页
int page = pageBean.getPage();
int max = pageBean.getMaxPage();
int before = page > 4 ? 4 : page-1;
int after = 10 - 1 - before;//5
after = max - page > after ? after : max-page;
// 用来控制上一页的点击按钮特效的
boolean startFlag = page == 1;
// 用来控制下一页的点击按钮特效的
boolean endFlag = page == max;
// 拼接分页条
sb.append("<ul class='pagination'>");
sb.append("<li class='page-item "+(startFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage(1)'>首页</a></li>");
sb.append("<li class='page-item "+(startFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getPrevPage()+")'><</a></li>");
// 代表了当前页的前4页
for (int i = before; i > 0 ; i--) {
sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page-i)+")'>"+(page-i)+"</a></li>");
}
sb.append("<li class='page-item active'><a class='page-link' href='javascript:gotoPage("+pageBean.getPage()+")'>"+pageBean.getPage()+"</a></li>");
// 代表了当前页的后5页
for (int i = 1; i <= after; i++) {
sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page+i)+")'>"+(page+i)+"</a></li>");
}
sb.append("<li class='page-item "+(endFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getNextPage()+")'>></a></li>");
sb.append("<li class='page-item "+(endFlag ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a></li>");
sb.append("<li class='page-item go-input'><b>到第</b><input class='page-link' type='text' id='skipPage' name='' /><b>页</b></li>");
sb.append("<li class='page-item go'><a class='page-link' href='javascript:skipPage()'>确定</a></li>");
sb.append("<li class='page-item'><b>共"+pageBean.getTotal()+"条</b></li>");
sb.append("</ul>");
// 拼接分页的js代码
sb.append("<script type='text/javascript'>");
sb.append("function gotoPage(page) {");
sb.append("document.getElementById('pageBeanForm').page.value = page;");
sb.append("document.getElementById('pageBeanForm').submit();");
sb.append("}");
sb.append("function skipPage() {");
sb.append("var page = document.getElementById('skipPage').value;");
sb.append("if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > "+max+") {");
sb.append("alert('请输入1~N的数字');");
sb.append("return;");
sb.append("}");
sb.append("gotoPage(page);");
sb.append("}");
sb.append("</script>");
return sb.toString();
}
}
把pageTag配置到zking.tld中
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>zking 1.1 core library</description>
<display-name>zking core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>z</short-name>
<uri>/zking</uri>
<tag>
<name>page</name>
<tag-class>com.tangxinlian.tag.PageTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>pageBean</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
6、创建framework包
1、 建模
1.1 ForwardModel
package com.tangxinlian.framework;
public class ForwardModel {
// <forward name="failed" path="/reg.jsp" redirect="false" />
private String name;
private String path;
private Boolean redirect;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Boolean isRedirect() {
return redirect;
}
public void setRedirect(Boolean redirect) {
this.redirect = redirect;
}
}
1.2 ActionModel
package com.tangxinlian.framework;
import java.util.HashMap;
import java.util.Map;
public class ActionModel {
// <action path="/regAction" type="test.RegAction">
private String path;
private String type;
private Map<String, ForwardModel> foMap = new HashMap<String, ForwardModel>();
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//两个行为
/**
* 将指定的forwardModel压入当前actionModel对象中
* <forward />放入<action></action>
* @param forwardModel
*/
public void push(ForwardModel forwardModel) {
foMap.put(forwardModel.getName(), forwardModel);
}
public ForwardModel pop(String name) {
return foMap.get(name);
}
}
1.3 ConfigModel
package com.tangxinlian.framework;
import java.util.HashMap;
import java.util.Map;
public class ConfigModel {
private Map<String, ActionModel> acMap = new HashMap<String, ActionModel>();
/**
* 将指定的actionModel压入当前configModel对象中
* <action />放入<config></config>
* @param actionModel
*/
public void push(ActionModel actionModel) {
acMap.put(actionModel.getPath(), actionModel);
}
public ActionModel pop(String path) {
return acMap.get(path);
}
}
工厂类
package com.tangxinlian.framework;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 23种设计模式值工厂模式
*
* 工厂模式解决的问题,将代码封装,提高代码的复用性
* 类比汉堡的获取方式(肯德基直接购买,原材料自己制作)
*
* 一般工厂类一定会有一个方法,就是生产指导模型对象的方法
* build
* nueInstance
*
* 拥抱变化
* 注意:
*在工厂类中会有两个以上的构建方法,一个默认框架李军的模型对象构建方法,
*还有一个是动态读取任意位置下的框架配置文件
*
* @author tangxinlian
*
* 2020年5月23日上午8:38:22
*/
public class ConfigModelFactory {
/**
* 通过资源文件构建对应的模型对象
* @param path 具体的资源文件路径
* @return
* @throws Exception
*/
public static ConfigModel build(String path) throws Exception {
// path=/config.xml
InputStream in = ConfigModelFactory.class.getResourceAsStream(path);
SAXReader reader = new SAXReader();
// /config.xml里的内容
Document doc = reader.read(in);
// 接下来就做一件事情---》把内容填充到configModel对象中(doc.asXML-->configModel)
ConfigModel configModel = new ConfigModel();
ActionModel actionModel = null;
ForwardModel forwardModel = null;
List<Element> actionEles = doc.selectNodes("/config/action");
for (Element actionEle : actionEles) {
actionModel = new ActionModel();
actionModel.setPath(actionEle.attributeValue("path"));
actionModel.setType(actionEle.attributeValue("type"));
// 给actionModel中放入ForwardModel对象
// 拿到forward标签内容
List<Element> forwardEles = actionEle.selectNodes("forward");
for (Element forwardEle : forwardEles) {
forwardModel = new ForwardModel();
forwardModel.setName(forwardEle.attributeValue("name"));
forwardModel.setPath(forwardEle.attributeValue("path"));
// redirect属性是boolean类型
// 需求:只有config.xml中redirect属性填写了false,它才代表转发
// forwardEle.attributeValue("redirect")获取到config中的redirect属性值
forwardModel.setRedirect(!"false".equals(forwardEle.attributeValue("redirect")));
actionModel.push(forwardModel);
}
configModel.push(actionModel);
}
return configModel;
}
/**
* 默认框架李军的模型对象构建方法
* @return
* @throws Exception
*/
public static ConfigModel build() throws Exception {
return build("/mvc.xml");
}
public static void main(String[] args) throws Exception {
ConfigModel model = ConfigModelFactory.build();
// ActionModel actionModel = model.pop("/regAction");
// System.out.println(actionModel.getType());
// 需求:获取/loginAction下的success结果码对应的页面/main.jsp
ActionModel actionModel = model.pop("/loginAction");
System.out.println(actionModel.getType());
ForwardModel forwardModel = actionModel.pop("success");
System.out.println(forwardModel.getPath());
}
}
2、
Action类
package com.tangxinlian.framework;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException ;
}
ModelDriven类
package com.tangxinlian.framework;
public interface ModelDriven<T> {
T getModel();
}
ActionSupport类
package com.tangxinlian.framework;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 处理if分支问题,动态调用当前类的其他方法add/del/edit
* @author tangxinlian
*
* 2020年6月6日下午11:49:49
*/
public class ActionSupport implements Action{
@Override
public String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String methodName = req.getParameter("methodName");
// this 指的是BookAction
Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
m.setAccessible(true);
// 相当于动态调用del(req,resp);
return (String)m.invoke(this, req,resp);
}
}
DispatcherServlet类
package com.tangxinlian.framework;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
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 org.apache.commons.beanutils.BeanUtils;
@WebServlet(name="dispatcherServlet",urlPatterns="*.action")
public class DispatcherServlet extends HttpServlet{
private static final long serialVersionUID = -8983673038312806186L;
private ConfigModel configModel;
@Override
public void init() throws ServletException {
try {
configModel = ConfigModelFactory.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@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 {
// http://localhost:8080/book.action?methodName=list
String uri = req.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));// /book
ActionModel actionModel = configModel.pop(path);
if(actionModel == null) {
throw new RuntimeException(path+" action 标签没有配置");
}
try {
// 实例化处理网络请求URL的类
// action 就相当于BookAction
Action action = (Action) Class.forName(actionModel.getType()).newInstance();
// 动态封装参数
if(action instanceof ModelDriven) {
ModelDriven md = (ModelDriven) action;
// 将前端jsp参数传递到后端的所有值封装到业务模型
BeanUtils.populate(md.getModel(), req.getParameterMap());
}
// 动态调用方法
String code = action.execute(req, resp);
ForwardModel forwardModel = actionModel.pop(code);
// /reg.jsp
String jspPath = forwardModel.getPath();
if(forwardModel.isRedirect()) {
resp.sendRedirect(req.getServletContext()+jspPath);
}else {
req.getRequestDispatcher(jspPath).forward(req, resp);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
7、创建web包
package com.tangxinlian.web;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tangxinlian.dao.JobDao;
import com.tangxinlian.entity.Job;
import com.tangxinlian.framework.ActionSupport;
import com.tangxinlian.framework.ModelDriven;
import com.tangxinlian.util.PageBean;
@WebServlet(name="jobAction",urlPatterns="/jobAction")
public class JobAction extends ActionSupport implements ModelDriven<Job>{
private JobDao jobDao = new JobDao();
private Job j = new Job();
@Override
public Job getModel() {
// TODO Auto-generated method stub
return j;
}
// 查询
public String list(HttpServletRequest req,HttpServletResponse resp) {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
try {
// 默认查询出第一页的数据
List<Job> list = jobDao.list(j, pageBean);
// 将查询的结果展示到对应jobList.jsp
req.setAttribute("jobs", list);
// 分页标签中使用
req.setAttribute("pageBean", pageBean);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
// blogList.jsp
return "list";
}
// 跳转新增
public String toAdd(HttpServletRequest req,HttpServletResponse resp) {
// jobAdd.jsp
return "toAdd";
}
// 新增
public String add(HttpServletRequest req,HttpServletResponse resp) {
try {
this.jobDao.add(j);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// /blog.action?methodName=list
return "toList";
}
// 跳转修改
public String toEdit(HttpServletRequest req,HttpServletResponse resp) {
// 查询当前要编辑的消息
try {
Job jb = this.jobDao.list(j, null).get(0);
req.setAttribute("b", jb);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// blogEdit.jsp
return "toEdit";
}
// 修改
public String edit(HttpServletRequest req,HttpServletResponse resp) {
try {
this.jobDao.edit(j);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// /blog.action?methodName=list
return "toList";
}
// 删除
public String del(HttpServletRequest req,HttpServletResponse resp) {
try {
this.jobDao.del(j);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// /blog.action?methodName=list
return "toList";
}
}
8、创建于src同一级别的conf 包
把JobAction配置到mvc.xml中
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/job" type="com.tangxinlian.web.JobAction">
<forward name="list" path="/jobList.jsp" redirect="false" />
<forward name="toAdd" path="/jobAdd.jsp" redirect="" />
<forward name="toEdit" path="/jobEdit.jsp" redirect="false" />
<forward name="toList" path="/job.action?methodName=list" redirect="" />
</action>
</config>
9、jsp页面
查询页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib prefix="z" uri="/zking" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<title>招聘列表</title>
<style type="text/css">
.page-item input {
padding: 0;
width: 40px;
height: 100%;
text-align: center;
margin: 0 6px;
}
.page-item input,
.page-item b {
line-height: 38px;
float: left;
font-weight: 400;
}
.page-item.go-input {
margin: 0 10px;
}
</style>
</head>
<body>
<form class="form-inline" action="${pageContext.request.contextPath }/job.action?methodName=list" method="post">
<div class="form-group mb-2">
<input type="text" class="form-control-plaintext" name="job" placeholder="请输入招聘职位">
</div>
<button type="submit" class="btn btn-primary mb-2">查询</button>
<!--
href="/bookAdd.jsp" 相对路径,相对的是tomcat 工作根目录
href="bookAdd.jsp" 相对于请求
href="${pageContext.request.contextPath }/bookAdd.jsp" 带上项目名的绝对路径
href="${pageContext.request.contextPath }/book.action?methodName=toAdd" 通过后台转发到前台的jsp页面
-->
<a href="${pageContext.request.contextPath }/jobAdd.jsp" class="btn btn-primary mb-2 ml-4">新增</a>
</form>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">职位</th>
<th scope="col">公司</th>
<th scope="col">工作地址</th>
<th scope="col">薪资</th>
<th scope="col">学历要求</th>
<th scope="col">爬取时间</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${jobs }" var="b">
<tr>
<td>${b.job }</td>
<td>${b.company }</td>
<td>${b.address }</td>
<td>${b.salary }</td>
<td>${b.limit }</td>
<td>${b.time }</td>
<td>
<a href="${pageContext.request.contextPath }/job.action?methodName=del&id=${b.id }" class="btn btn-sm btn-danger mb-2 ml-4">删除</a>
<a href="${pageContext.request.contextPath }/job.action?methodName=toEdit&id=${b.id }" class="btn btn-sm btn-success mb-2 ml-4">修改</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<z:page pageBean="${pageBean }"></z:page>
</body>
</html>
增加页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<title>招聘新增页面</title>
</head>
<body>
新增页面
<form action="${pageContext.request.contextPath }/job.action?methodName=add" method="post">
<div class="form-group row">
<label for="bid" class="col-sm-2 col-form-label">职位</label>
<div class="col-sm-10">
<input type="job" class="form-control" id="job" name="job">
</div>
</div>
<div class="form-group row">
<label for="company" class="col-sm-2 col-form-label">公司</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="company" name="company">
</div>
</div>
<div class="form-group row">
<label for="address" class="col-sm-2 col-form-label">工作地址</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="address" name="address">
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-2 col-form-label">薪资</label>
<div class="col-sm-10">
<input type="job" class="form-control" id="salary" name="salary">
</div>
</div>
<div class="form-group row">
<label for="limit" class="col-sm-2 col-form-label">学历要求</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="limit" name="limit">
</div>
</div>
<div class="form-group row">
<label for="time" class="col-sm-2 col-form-label">爬取时间</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="time" name="time">
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<input type="submit" class="form-control bg-success" value="提交">
</div>
</div>
</form>
</body>
</html>
修改页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<title>招聘修改页面</title>
</head>
<body>
修改页面
<form action="${pageContext.request.contextPath }/job.action?methodName=edit" method="post">
<input type="hidden" value="${b.id }" name="id">
<div class="form-group row">
<label for="bid" class="col-sm-2 col-form-label">职位</label>
<div class="col-sm-10">
<input type="job" class="form-control" id="job" name="job" value="${b.job }">
</div>
</div>
<div class="form-group row">
<label for="company" class="col-sm-2 col-form-label">公司</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="company" name="company" value="${b.company }">
</div>
</div>
<div class="form-group row">
<label for="address" class="col-sm-2 col-form-label">工作地址</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="address" name="address" value="${b.address }">
</div>
</div>
<div class="form-group row">
<label for="salary" class="col-sm-2 col-form-label">薪资</label>
<div class="col-sm-10">
<input type="job" class="form-control" id="salary" name="salary" value="${b.salary }">
</div>
</div>
<div class="form-group row">
<label for="limit" class="col-sm-2 col-form-label">学历要求</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="limit" name="limit" value="${b.limit }">
</div>
</div>
<div class="form-group row">
<label for="time" class="col-sm-2 col-form-label">爬取时间</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="time" name="time" value="${b.time }">
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<input type="submit" class="form-control bg-success" value="修改">
</div>
</div>
</form>
</body>
</html>