- 框架
半成品(提前准备好的有 base,dao,entity framework,tag,util类如图)
工具包,和分页包
- com.wxm.base;
- BeanDao
package com.wxm.base;
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.wxm.entity.Book;
import com.wxm.util.DBAccess;
import com.wxm.util.PageBean;
/**
* 通用分页查询(带条件查询)
* <T>代表你要对那个实体类对应分页查询
* @author 2019071003
*
*/
public class BeanDao<T> {
/**
*
* @param sql 由于不同的表查询语句不一样,所以靠子类写好来传递
* @param cls 需要返回不同的对象集合 查询的对象
* @param bean 可能要分页
* @return
* @throws Exception
*/
public List<T> executeQuery (String sql,Class cls,PageBean bean) throws Exception{
List<T> list = new ArrayList<>();
Connection con = DBAccess.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
//决定是否分页:
if(bean != null && bean.isPagination()) {//判读条件
//分页
/**
* 1.分页是与分页助手类pagebean中的total有关,需要查询数据库得到total赋值给bean
* 2.查询出符合条件的某一页的数据
*/
String countsql = getCountsql(sql);
ps = con.prepareStatement(countsql);
rs = ps.executeQuery();
/**
* -- 符合条件的记录数
select count(1) from (select * from t_mvc_book where bname like '%斗破%') t;
*/
if(rs.next()){
bean.setTotal(rs.getObject(1).toString());//查询多少条数据
}
/**
* --分页的查询语句
select * from t_mvc_book where bname like '%斗破%' limit 起始下标(第几页),变量(每页显示几条)
*/
String pagesql = getPagesql(sql, bean);
ps = con.prepareStatement(pagesql);
rs = ps.executeQuery();
}else {
//不分页
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
}
T t = null;
while (rs.next()) {
/**
* 1. 实例化一个你要查询的对象 (比如book)
* 2. 通过对象的属性名去游标中取出属性值(通过反射来完成)
* 2.1 获取到类对象中的属性
* 2.2 给属性赋值
* 3. 已经赋值好的实例对象放入到list集合当中
*/
t = (T) cls.newInstance();//反射获取对象开始
Field [] fields = cls.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);//打开权限
// 对象 对象的属性名
f.set(t, rs.getObject(f.getName()));
}
list.add(t);
}
return list;
}
/**
*
* @param sql
* @param bean 获取查询的起始下标和变量
* @return
*/
private String getPagesql(String sql , PageBean bean) {
// TODO 分页查询语句
return sql + " limit " +bean.getStartIndex()+","+bean.getRows();
}
private String getCountsql(String sql) {
// TODO 用来查询对应条件有多少条数据
return "select count(1) from ("+sql+") t";
}
/**
*
* @param sql 决定增删改一种
* @param attrs 决定?的位置 new String[]{bname","price","bid"}
* @param t 要操作的实体类
* @return
* @throws SQLException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public int executeUpdate(String sql, String[] attrs ,T t) throws SQLException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
Connection con = DBAccess.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
for (int i = 1; i <= attrs.length; i++) {
//
System.out.println("attrs[i-1]="+attrs[i-1]);
Field field = t.getClass().getDeclaredField(attrs[i-1]);
field.setAccessible(true);
System.out.println("t.getClass().getDeclaredField="+t.getClass().getDeclaredField("bname"));
pst.setObject(i, field.get(t));
}
int num = pst.executeUpdate();
DBAccess.close(con, pst, null);
return num;
}
}
- com.wxm.dao;
- BookDao
package com.wxm.dao;
import java.sql.SQLException;
import java.util.List;
import com.wxm.base.BeanDao;
import com.wxm.entity.Book;
import com.wxm.util.PageBean;
import com.wxm.util.StringUtils;
/**
* 目的:做一个通用的分页的查询方法
* 1.利用三层架构知识简单写一个普通查询方法
* 2.将原有的查询方法进行反射优化,转变一个可以被所有实体类Dao层所继承的通用查询
* 3.考虑分页
* 3.1算总记录数
* 3.2查询出当前页的结果集
* @author 2019071003
*
*/
public class BookDao extends BeanDao<Book>{
public List<Book> list(Book book,PageBean pageBean) throws Exception{
String sql="select * from t_mvc_book where true";
String bname=book.getBname();
int bid=(int) book.getBid();
if(StringUtils.isNotBlank(bname)) {
sql+=" and bname like '%"+bname+"%'";
}
if(bid!=0) {
sql+=" and bid ="+bid;
}
return super.executeQuery(sql, Book.class, pageBean);
}
/**
* 新增
* @param book
* @return
* @throws SQLException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws SecurityException
* @throws NoSuchFieldException
*/
public int add(Book book) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, SQLException {
String sql="insert into t_mvc_book value(?,?,?)";
return super.executeUpdate(sql, new String[] {"bid","bname","price"}, book);
}
/**
* 删除
* @param book
* @return
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws SQLException
*/
public int del(Book book) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, SQLException {
String sql="delete from t_mvc_book where bid=?";
return super.executeUpdate(sql, new String[] {"bid"}, book);
}
/**
* 修改
* @param book
* @return
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws SQLException
*/
public int edit(Book book) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, SQLException {
String sql="update t_mvc_book set bname =?,price=? where bid=?";
return super.executeUpdate(sql, new String[] {"bname","price","bid"}, book);
}
}
- com.wxm.entity;
- Book
package com.wxm.entity;
public class Book {
private long bid;
private String bname;
private float price;
public Book() {
super();
}
public Book(long bid, String bname, float price) {
super();
this.bid = bid;
this.bname = bname;
this.price = price;
}
public long getBid() {
return bid;
}
public void setBid(long bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
}
}
- com.wxm.framework;
- ActionModel
package com.wxm.framework;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author Administrator
*
*/
public class ActionModel implements Serializable{
private static final long serialVersionUID = 6145949994701469663L;
private Map<String, ForwardModel> forwardModels = new HashMap<String, ForwardModel>();
private String path;
private String type;
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;
}
public void put(ForwardModel forwardModel){
forwardModels.put(forwardModel.getName(), forwardModel);
}
public ForwardModel get(String name){
return forwardModels.get(name);
}
}
- com.wxm.framework;
- ActionSupport
package com.wxm.framework;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.wxm.web.*;
/**
* 增加版的子控制器
* 原来的子控制器只能处理有关用户请求
* 有时候,用户请求是多个,但是都是操作同一张表,那么原有的子控制器代码编写繁琐
* 增强版 将一组相关的操作放到一个Action中
* @author 2019071003
*
*/
public class ActionSupport implements Action{
public String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 传前台的什么方法,它(后台)就调用什么方法---动态方法调用(反射知识)
String methodName=req.getParameter("methodName");
System.out.println("methodName"+methodName);
String code=null;
//获取当前子控制器类的实例
// this.在这里是指CalAction它的一个类实例
try {
Method m = this.getClass().getDeclaredMethod(methodName,
HttpServletRequest.class,HttpServletResponse.class);//获取类对象
m.setAccessible(true);//设置权限
//动态调用add方法
//它也有返回值,是返回码
code=(String) m.invoke(this, req,resp);
} catch (Exception e) {
e.printStackTrace();
}
return code;
}
}
- ConfigModel
package com.wxm.framework;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 鐢ㄦ潵鎻忚堪config鏍囩
* @author Administrator
*
*/
public class ConfigModel implements Serializable{
private static final long serialVersionUID = -2334963138078250952L;
private Map<String, ActionModel> actionModels = new HashMap<String, ActionModel>();
public void put(ActionModel actionModel){
actionModels.put(actionModel.getPath(), actionModel);
}
public ActionModel get(String name){
return actionModels.get(name);
}
}
- ConfigModelFactory
package com.wxm.framework;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ConfigModelFactory {
private ConfigModelFactory() {
}
private static ConfigModel configModel = null;
public static ConfigModel newInstance() throws Exception {
return newInstance("mvc.xml");
}
/**
* 宸ュ巶妯″紡鍒涘缓config寤烘ā瀵硅薄
*
* @param patzzh
* @return
* @throws Exception
*/
public static ConfigModel newInstance(String path) throws Exception {
if (null != configModel) {
return configModel;
}
ConfigModel configModel = new ConfigModel();
InputStream is = ConfigModelFactory.class.getResourceAsStream(path);
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(is);
List<Element> actionEleList = doc.selectNodes("/config/action");
ActionModel actionModel = null;
ForwardModel forwardModel = null;
for (Element actionEle : actionEleList) {
actionModel = new ActionModel();
actionModel.setPath(actionEle.attributeValue("path"));
System.out.println("path:"+actionModel.getPath());
actionModel.setType(actionEle.attributeValue("type"));
System.out.println("Type:"+actionModel.getType());
List<Element> forwordEleList = actionEle.selectNodes("forward");
for (Element forwordEle : forwordEleList) {
forwardModel = new ForwardModel();
forwardModel.setName(forwordEle.attributeValue("name"));
forwardModel.setPath(forwordEle.attributeValue("path"));
forwardModel.setRedirect(forwordEle.attributeValue("redirect"));
System.out.println("forwardModel.getName()"+forwardModel.getName());
actionModel.put(forwardModel);
}
configModel.put(actionModel);
}
return configModel;
}
public static void main(String[] args) {
try {
ConfigModel configModel = ConfigModelFactory.newInstance();
ActionModel actionModel = configModel.get("/loginAction");
ForwardModel forwardModel = actionModel.get("failed");
} catch (Exception e) {
e.printStackTrace();
}
}
}
- ForwardModel
package com.wxm.framework;
import java.io.Serializable;
/**
* 鐢ㄦ潵鎻忚堪forward鏍囩
* @author Administrator
*
*/
public class ForwardModel implements Serializable {
private static final long serialVersionUID = -8587690587750366756L;
private String name;
private String path;
private String 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 String getRedirect() {
return redirect;
}
public void setRedirect(String redirect) {
this.redirect = redirect;
}
}
- ModelDrivern
package com.wxm.framework;
/**
* 模型驱动接口
* 作用 是将jsp所有传递过来的参数以及参数值都自动封装到浏览器所要操作的实体类中
* @author 2019071003
*
* @param <T>
*/
public interface ModelDrivern<T> {
T getModel();
}
打jar包
mvc一定要和ConfigModelFactory同级目录
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/book" type="com.wxm.web.BookAction">
<forward name="list" path="/bookList.jsp" redirect="false" />
<forward name="edit" path="/bookEdit.jsp" redirect="false" />
<forward name="toList" path="/book.action?methodName=list" />
</action>
</config>
- PageTag
package com.wxm.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.wxm.util.PageBean;
public class PageTag extends BodyTagSupport{
private static final long serialVersionUID = 1768059941408824100L;
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 SKIP_BODY;
}
private String toHTML() {
// 可变的字符串容器
StringBuilder sb=new StringBuilder();
// 拼接下一次所分页请求所提交的分页 表单
sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>");
sb.append("<input type='hidden' name='page'>");
Map<String, String[]> paMap = pageBean.getPaMap();
if(paMap != null && paMap.size()>0) {
Set<Entry<String,String[]>> entrySet = paMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
for(String value : entry.getValue()) {
if(!"page".equals(entry.getKey()))
sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+value+"' >");
}
}
}
sb.append("</form>");
// 拼接分页条
sb.append("<div style='text-align: right; font-size: 12px;'>");
sb.append("每页"+pageBean.getRows()+"条,共"+pageBean.getTotal()+"条,第"+pageBean.getPage()+"页,共"+pageBean.getMaxPage()+"页 <a href='javascript:gotoPage(1)'>首页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getNextPage()+")'>下一页</a> <a");
sb.append(" href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a> <input type='text'");
sb.append(" id='skipPage'");
sb.append(" style='text-align: center; font-size: 12px; width: 50px;'> <a");
sb.append(" href='javascript:skipPage()'>Go</a>");
sb.append("</div>");
//拼接分页的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("function skipPage() {");
sb.append("var page = document.getElementById('skipPage').value;");
sb.append("if(!page || isNaN(page) || parseInt(page)<1 || parseInt(page) > "+pageBean.getMaxPage()+"){");
sb.append("alert('请输入1~N的数字');");
sb.append("return;}");
sb.append("gotoPage(page);}");
sb.append("</script>");
return sb.toString();
}
}
- 数据库连接
package com.wxm.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("数据库连接(关闭)成功");
}
}
#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://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
user=root//账户名 url /test指数据库名
pwd=123//密码
- EncodingFiter
package com.wxm.util;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 中文乱码处理
*
*/
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();
}
}
}
- 分页工具PageBean
package com.wxm.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
/**
*分页工具
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
//保留上一次 的请求地址
private String url="";
//保留上一次请求所携带的参数
private Map<String, String[]> paMap=new HashMap<>();
/**
* pageBean初始化的方法
* @param req
*/
public void setRequest(HttpServletRequest req) {
//改变它第几页的数据
this.setPage(req.getParameter("page"));
//改变它每页展示的数据
// System.out.println(req.getParameter("rows"));
if(req.getParameter("rows")!=null) {
this.setRows(Integer.parseInt(req.getParameter("rows")));
}else {
this.setRows(10);
}
//控制页面是否分页
this.setPagination(req.getParameter("pagination"));
this.setUrl(req.getRequestURL().toString());//上一次的地址
this.setPaMap(req.getParameterMap());//上一次查询的参数
}
private void setPagination(String parameter) {
// 当你填false就不分页
if("false".equals(pagination)) {
this.setPagination(false);
}
}
public void setPage(String page) {
// 如果不为空的时候
if(StringUtils.isNotBlank(page)) {
this.setPage(Integer.valueOf(page));
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String[]> getPaMap() {
return paMap;
}
public void setPaMap(Map<String, String[]> paMap) {
this.paMap = paMap;
}
private boolean pagination = true;// 是否分页
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;
}
/**
*获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
/**
* 最大页码
* @return
*/
public int getMaxPage() {
return this.total%this.rows==0? this.total/this.rows:this.total/this.rows+1;
}
/**
* 获取下一页
* @return
*/
public int getNextPage() {
return this.page<this.getMaxPage()?this.page+1:this.page;
}
public int getPreviousPage() {
return this.page>1?this.page-1:this.page;
}
}
StringUtils 字符处理
package com.wxm.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);
}
}
- 使用自定义mvc框架完成CRUD操作
统计之前所有的知识点有
- 可以去我的博客里通过案例学习
package com.wxm.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器:
* 作用:具体处理用户请求的类(实现了Action接口)
* @author 2019071003
*
*/
public interface Action {
String execute(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException;
}
- BookAction
package com.wxm.web;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.xml.internal.ws.client.dispatch.DispatchImpl;
import com.wxm.dao.BookDao;
import com.wxm.entity.Book;
import com.wxm.framework.ModelDrivern;
import com.wxm.util.PageBean;
public class BookAction extends ActionSupport implements ModelDrivern<Book>{
private Book book = new Book();
private BookDao bookDao = new BookDao();
/**
* 分页查询
* @param req
* @param resp
* @return
* @throws Exception
*/
public String list(HttpServletRequest req,HttpServletResponse resp) throws Exception {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
try {
List<Book> list = this.bookDao.list(book, pageBean);
req.setAttribute("bookList", list);
req.setAttribute("pageBean", pageBean);
} catch (InstantiationException | IllegalAccessException | SQLException e) {
e.printStackTrace();
}
return "list";
}
/**
* 跳转到增加或者修改页面
* @param req
* @param resp
* @return
* @throws Exception
*/
public String preSave(HttpServletRequest req,HttpServletResponse resp) throws Exception {
// bid的类型是int类型,而int类型的默认值是0,如果jsp未传递bid的参数值,那么bid=0
if(book.getBid() == 0) {
System.out.println("增加逻辑...");
}else {
try {
// 修改数据回显逻辑
//查单个
Book b = this.bookDao.list(book, null).get(0);
req.setAttribute("book", b);
} catch (InstantiationException | IllegalAccessException | SQLException e) {
e.printStackTrace();
}
}
// 新增页面与修改页面是同一个jsp
return "edit";
}
/**
* 新增
* @param req
* @param resp
* @return
*/
public String add(HttpServletRequest req,HttpServletResponse resp) {
try {
this.bookDao.add(book);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
| SQLException e) {
e.printStackTrace();
}
//新增完了需要刷新页面
return "toList";
}
/**
* 修改
* @param req
* @param resp
* @return
*/
public String edit(HttpServletRequest req,HttpServletResponse resp) {
try {
this.bookDao.edit(book);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
| SQLException e) {
e.printStackTrace();
}
return "toList";
}
/**
* 删除
* @param req
* @param resp
* @return
*/
public String del(HttpServletRequest req,HttpServletResponse resp) {
try {
this.bookDao.del(book);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
| SQLException e) {
e.printStackTrace();
}
return "toList";
}
@Override
public Book getModel() {
return book;
}
}
强调
- DispatcherServlet 中心控制器
package com.wxm.web;
/**
* 中央控制器
* 作用:
* 接受用户请求,通过用户请求的url寻找制定的子控制器去处理业务
*
*
* 1,对存放子控制器action容器的增强
* ?原来为了完成业务需求,需要不断修改框架的代码,这样设计是不合理的
* 处理方式:参照web.xml的实际方法,来完成中央的控制器管理子配置器的管理
*
*
* 2.处理结果码的跳转形式( req.getRequestDispatcher("/rs.jsp").forward(req, resp)/重定向;)
*
* 3.将一组操作放到一个子控制器去完成
*
*
* 4.处理jsp传递到后台的参数封装
*
* 5.解决框架配置文件重名冲突问题
* @author 2019071003
*
*/
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.wxm.framework.ActionModel;
import com.wxm.framework.ConfigModel;
import com.wxm.framework.ConfigModelFactory;
import com.wxm.framework.ForwardModel;
import com.wxm.framework.ModelDrivern;
public class DispatcherServlet extends HttpServlet{
private static final long serialVersionUID = 2304962805570259027L;
private ConfigModel configModel=null;
public void init() {
/**
* 用来配置子控制器
*/
// 1.将Action的信息配置到xml(反射实例化)
// 解决了在框架代码中去改动,以便于完成客户需求,这个是不合理的
//2.防止配置的xml同名问题
try {
String xmlPath = this.getInitParameter("xmlPath"); // 5.mvc 的默认地址
if(null == xmlPath || "" .equals(xmlPath)) {
xmlPath="mvc.xml";
}
System.out.println("xmlPath"+xmlPath);
configModel =ConfigModelFactory.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url=req.getRequestURI();
url=url.substring(url.lastIndexOf("/"),url.lastIndexOf("."));
System.out.println("url:"+url);
/* Action action = actionMap.get(url);*/
ActionModel actionModel = configModel.get(url);
try {
// 2 2如果客户没有配置 需要提示
if(actionModel == null) {
throw new RuntimeException("您还未配置子控制器来处理用户请求");
}
//1 类地址 进行实例化
Action action = (Action) Class.forName(actionModel.getType()).newInstance();
//4加强
if(action instanceof ModelDrivern) {
ModelDrivern modelDriver = (ModelDrivern) action;
Object model = modelDriver.getModel();
// 给 model 赋值了,那么意味这在调用add/del不在是空值
BeanUtils.populate(model, req.getParameterMap());
}
// 3加强
String code = action.execute(req, resp);
ForwardModel forwardModel = actionModel.get(code);
if("false".equals(forwardModel.getRedirect())) {
req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
}else {
// 2注意:默认会缺损项目名 req.getContextPath()
resp.sendRedirect(req.getContextPath()+ forwardModel.getPath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>pro_book</display-name>
<!-- 中文编码 -->
<filter>
<filter-name>encodingFiter</filter-name>
<filter-class>com.wxm.util.EncodingFiter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFiter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>com.wxm.web.DispatcherServlet</servlet-class>
<init-param>
<param-name>xmlPath</param-name>
<param-value>/mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
- 自定义标签库
<?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>wxm 1.1 core library</description>
<display-name>wxm core</display-name>
<tlib-version>1.1</tlib-version><!-- 标签库的版本号 -->
<short-name>c</short-name><!-- 标签库的简称 -->
<uri>/wxm</uri><!--你标签库引用的uri -->
<tag>
<!--填写的是标签库中的标签名 -->
<name>page</name>
<!--标签对应的后台助手类 -->
<tag-class>com.wxm.tag.PageTag</tag-class>
<!--标签类别 -->
<body-content>JSP</body-content>
<attribute>
<!-- 自定义标签中的属性 -->
<name>pageBean</name>
<!--属性值是否必填 -->
<required>true</required>
<!--是否支持El/ognl表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
- bookList. 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 uri="/wxm" prefix="m"%>
<!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">
<title>Insert title here</title>
</head>
<body>
<h2>小说目录</h2>
<br>
<form action="${pageContext.request.contextPath}/book.action?methodName=list"
method="post">
书名:<input type="text" name="bname"> <input type="submit"
value="确定">
<!-- <input type="hidden" name="pagination" value="false"> -->
<!-- 分页控制-->
<input type="hidden" name="rows" value="20">
</form>
<!-- /book.action?methodName=preSave转向后台 -->
<a href="${pageContext.request.contextPath}/book.action?methodName=preSave">增加</a>
<table border="1" width="100%">
<tr>
<td>编号</td>
<td>名称</td>
<td>价格</td>
<td>操作</td>
</tr>
<c:forEach items="${bookList }" var="b">
<tr>
<td>${b.bid }</td>
<td>${b.bname }</td>
<td>${b.price }</td>
<td>
<a href="${pageContext.request.contextPath}/book.action?methodName=preSave&&bid=${b.bid}">修改</a>
<a href="${pageContext.request.contextPath}/book.action?methodName=del&&bid=${b.bid}">删除</a>
</td>
</tr>
</c:forEach>
</table>
<m:page pageBean="${pageBean}"></m:page>
</body>
</html>
bookEdit.jsp
<%@ 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">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/book.action" method="post">
<input type="hidden" name="methodName" value="${book.bname ==null ? 'add' : 'edit' }">
书籍ID:<input type="text" name="bid" value="${book.bid }"><br>
书籍名称:<input type="text" name="bname" value="${book.bname }"><br>
书籍价格:<input type="text" name="price" value="${book.price }"><br>
<input type="submit">
</form>
</body>
</html>
最后效果
、
常见异常:url异常
表现为
- 转换异常
- null异常
这里是把自定义的bookAction转化为Action异常
解决方法:
1.首先看bookAction继承的类是否为Actionsupport( 增加版的子控制器)
2.第二种情况为导mvc.jar 看到导的jar是否对应
总结:都是不规范操作导致的
我这里主要是要写对应的访问的路径名
http://localhost:8080/pro_book/book.action?methodName=list
而不是bookList.jsp
- 显示页面不出结果
- (前提是没有代码明显报错情况下)
注意:
- 这个错误解决的思路大致为
url获取不到或者有错误
思路jsp ——>web.xml—(tld文件)—>action看传递url哪里出了问题