第一次用上Struts2框架做Web开发的体验……
Posted 程序设计实验室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第一次用上Struts2框架做Web开发的体验……相关的知识,希望对你有一定的参考价值。
SliiyStruts2
又名 sb-struts2,因为 struts 真的太难用了(也许在很多年前是很好用的,但是现在看来,被其他框架秒成渣)
前言
想不到我还是得和这 struts 框架打交道啊,从一开始学 web 的时候就十分抵制这类古老,使用反人类的框架,不过为了帮女朋友做个学校的作业,还是得搞一下,然而,半小时就写好的业务代码,因为我不熟悉这个框架和 Java 的这套体系,调试了半天才成功 run 起来……(心好累)
开始
首先使用 idea 创建 struts2 项目,但是坑来了,idea 创建的少了一个包,请自行去 maven 仓库下载,具体是少了这个包
javassist-3.26.0-GA.jar
接着就可以开始写代码了……
关于 Struts2 框架的学习参考:
-
Struts2 入门这一篇就够了 [1]
这篇写得很好,很详细,里面还有例子,跟着做就可以自己实现一个简单的 struts 框架了……
配置
先写一个最简单的 IndexAction,这里主要是做数据库的初始化工作,代码如下:
package cn.deali.action;
import cn.deali.utils.Database;
import com.opensymphony.xwork2.ActionSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IndexAction extends ActionSupport {
private final static Logger logger = LoggerFactory.getLogger(IndexAction.class);
@Override
public String execute() throws Exception {
System.out.println("Index Action");
logger.info("Index Action");
// 初始化数据库
if (Database.init()) {
Database.eraseData = false;
return SUCCESS;
} else
return ERROR;
}
}
写完了 Action 之后还要给一个配套的 jsp 页面,这叫做 MVC 设计模式,前后端分离(伪)……
<%--
Created by IntelliJ IDEA.
User: DealiAxy
Date: 2019/11/17
Time: 10:23
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户管理系统</title>
</head>
<body>
<h1>用户管理系统</h1>
<a href="Login.action">登录</a>
<a href="SignIn.action">注册</a>
<a href="User.action">修改密码</a>
</body>
</html>
之后就可以配置 struts2 了,就像这样……
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="cn.deali.action" namespace="/" extends="struts-default">
<default-action-ref name="Index"/>
<action name="Index" class="cn.deali.action.IndexAction" method="execute">
<result name="success">main.jsp</result>
<result name="error">error.jsp</result>
</action>
</package>
</struts>
其中的<default-action-ref name="Index"/>
是我后来学到的,默认 action,一开始我以为和其他框架一样,定义一个“/”路由就可以了,结果自己坑了自己,调试了半天都不行。
参考资料:
-
struts2 设置默认首页 [2]
日志记录
一开始用的是 log4j,感觉有点坑啊,然后想起来之前用过 slf4j,虽然两个不是同个概念的,不过slf4j+slf4j-simple
,是真的好用,方便,(ps:需要性能更好的可以用 logback,hhh),log4j 配置真的麻烦,而且嵌入到 tomcat 服务器,反正我这只是做个作业,不用搞太麻烦。
而且 slf4j 的输出模板也很好用,至少不会像 log4j 那么麻烦要拼接字符串了。
关于日志记录的操作参考:
-
Log4j.properties 配置详解加示例 - 简约人生的博客 - CSDN 博客 [3]
-
log4j 配置[4]
-
SLF4J 使用和与 Log4J 对比[5]
-
使用 SLF4J 和 Logback[6]
-
Java 日志框架:slf4j 作用及其实现原理[7]
关于我自己的 Log4J 的配置我这也放上来吧,虽然最后没用上。
# 配置根Logger:设定日志记录的最低级别,
log4j.rootLogger=DEBUG, stdout, logfile,ERROR
log4j.category.org.springframework=ERROR
log4j.category.org.apache=INFO
log4j.logger.org.hibernate=ERROR
# 输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 指定日志信息的最低输出级别,默认为DEBUG
log4j.appender.stdout.Threshold=ERROR
# 表示所有消息都会被立即输出,设为false则不输出,默认值是true
log4j.appender.stdout.ImmediateFlush=true
# 可以灵活自定义布局模式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 默认值是System.out。
log4j.appender.stdout.Target=System.out
# 设定以怎样的格式显示消息
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
数据库
数据库又是喜闻乐见的 SQLite 了,反正每次我都是用这个,hhh……
关于 Java 使用 SQLite,可以参考:
-
在 Java 中使用 Sqlite 数据库 [8]
附上我的SQLiteHelper
实用类代码:
package cn.deali.utils.sqlite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* sqlite帮助类,直接创建该类示例,并调用相应的接口即可对sqlite数据库进行操作
* <p>
* 本类基于 sqlite jdbc v56
*
* @author haoqipeng
*/
public class SQLiteHelper {
private final static Logger logger = LoggerFactory.getLogger(SQLiteHelper.class);
private Connection connection;
private Statement statement;
private ResultSet resultSet;
private String dbFilePath;
/**
* 构造函数
*
* @param dbFilePath sqlite db 文件路径
* @throws ClassNotFoundException
* @throws SQLException
*/
public SQLiteHelper(String dbFilePath) throws ClassNotFoundException, SQLException {
this.dbFilePath = dbFilePath;
connection = getConnection(dbFilePath);
}
/**
* 获取数据库连接
*
* @param dbFilePath db文件路径
* @return 数据库连接
* @throws ClassNotFoundException
* @throws SQLException
*/
public Connection getConnection(String dbFilePath) throws ClassNotFoundException, SQLException {
Connection conn = null;
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:" + dbFilePath);
return conn;
}
/**
* 执行sql查询
*
* @param sql sql select 语句
* @param rse 结果集处理类对象
* @return 查询结果
* @throws SQLException
* @throws ClassNotFoundException
*/
public <T> T executeQuery(String sql, ResultSetExtractor<T> rse) throws SQLException, ClassNotFoundException {
try {
resultSet = getStatement().executeQuery(sql);
T rs = rse.extractData(resultSet);
return rs;
} finally {
destroyed();
}
}
/**
* 执行select查询,返回结果列表
*
* @param sql sql select 语句
* @param rm 结果集的行数据处理类对象
* @return
* @throws SQLException
* @throws ClassNotFoundException
*/
public <T> List<T> executeQuery(String sql, RowMapper<T> rm) throws SQLException, ClassNotFoundException {
List<T> rsList = new ArrayList<T>();
try {
resultSet = getStatement().executeQuery(sql);
while (resultSet.next()) {
rsList.add(rm.mapRow(resultSet, resultSet.getRow()));
}
} finally {
destroyed();
}
return rsList;
}
/**
* 执行数据库更新sql语句
*
* @param sql
* @return 更新行数
* @throws SQLException
* @throws ClassNotFoundException
*/
public int executeUpdate(String sql) throws SQLException, ClassNotFoundException {
try {
int c = getStatement().executeUpdate(sql);
return c;
} finally {
destroyed();
}
}
/**
* 执行多个sql更新语句
*
* @param sqls
* @throws SQLException
* @throws ClassNotFoundException
*/
public void executeUpdate(String... sqls) throws SQLException, ClassNotFoundException {
try {
for (String sql : sqls) {
getStatement().executeUpdate(sql);
}
} finally {
destroyed();
}
}
/**
* 执行数据库更新 sql List
*
* @param sqls sql列表
* @throws SQLException
* @throws ClassNotFoundException
*/
public void executeUpdate(List<String> sqls) throws SQLException, ClassNotFoundException {
try {
for (String sql : sqls) {
getStatement().executeUpdate(sql);
}
} finally {
destroyed();
}
}
private Connection getConnection() throws ClassNotFoundException, SQLException {
if (null == connection) connection = getConnection(dbFilePath);
return connection;
}
private Statement getStatement() throws SQLException, ClassNotFoundException {
if (null == statement) statement = getConnection().createStatement();
return statement;
}
/**
* 数据库资源关闭和释放
*/
public void destroyed() {
try {
if (null != connection) {
connection.close();
connection = null;
}
if (null != statement) {
statement.close();
statement = null;
}
if (null != resultSet) {
resultSet.close();
resultSet = null;
}
} catch (SQLException e) {
logger.error("Sqlite数据库关闭时异常", e);
}
}
}
public interface ResultSetExtractor<T> {
public abstract T extractData(ResultSet rs);
}
public interface RowMapper<T> {
public abstract T mapRow(ResultSet rs, int index) throws SQLException;
}
还有我的数据库工厂类,哈哈:
package cn.deali.utils;
import cn.deali.utils.sqlite.SQLiteHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Database {
private final static Logger logger = LoggerFactory.getLogger(Database.class);
private static SQLiteHelper db;
public static boolean eraseData = false;
public static SQLiteHelper getInstance() {
if (db != null)
return db;
try {
db = new SQLiteHelper("test.db");
return db;
} catch (Exception ex) {
logger.error(ex.getMessage());
return null;
}
}
public static boolean init() {
logger.info("初始化数据库!");
db = getInstance();
try {
if (eraseData) {
db.executeUpdate("drop table if exists user;");
db.executeUpdate("create table user(username varchar(20), password varchar(20));");
logger.info("创建数据表");
}
return true;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
return false;
}
}
}
坑
首先是 tomcat 服务器在 Windows 上有控制台输出乱码的问题,很烦,解决的话可以参考:
-
解决 Tomcat 控制台输出信息乱码 [9] -
Tomcat 乱码问题 catalina.bat 设置为 UTF-8 控制台出现乱码 [10]
完整代码
欢迎交流
-
微信公众号:画星星高手 -
打代码直播间: https://live.bilibili.com/11883038 [11] -
知乎: https://www.zhihu.com/people/dealiaxy [12] -
简书: https://www.jianshu.com/u/965b95853b9f [13]
参考资料
Struts2入门这一篇就够了: https://juejin.im/post/5aa3349ff265da23884caa6a#heading-17
[2]struts2设置默认首页: https://blog.csdn.net/zhangpan19910604/article/details/46672519
[3]Log4j.properties配置详解加示例 - 简约人生的博客 - CSDN博客 : https://blog.csdn.net/jianyuerensheng/article/details/50420747
[4]log4j 配置: https://github.com/digoal/blog/blob/master/201701/20170126_01.md
[5]SLF4J使用和与Log4J对比: https://www.jianshu.com/p/32e2a7254c03
[6]使用SLF4J和Logback: https://www.liaoxuefeng.com/wiki/1252599548343744/1264739155914176
[7]Java日志框架:slf4j作用及其实现原理: https://www.cnblogs.com/xrq730/p/8619156.html
[8]在Java中使用Sqlite数据库: https://www.cnblogs.com/haoqipeng/p/sqlite-use-in-java.html
[9]解决Tomcat控制台输出信息乱码: https://blog.csdn.net/qq_35436635/article/details/86575943
[10]Tomcat乱码问题 catalina.bat设置为UTF-8 控制台出现乱码: https://blog.csdn.net/zhaoxny/article/details/79926333
[11]https://live.bilibili.com/11883038: https://live.bilibili.com/11883038
[12]https://www.zhihu.com/people/dealiaxy: https://www.zhihu.com/people/dealiaxy
[13]https://www.jianshu.com/u/965b95853b9f: https://www.jianshu.com/u/965b95853b9f
以上是关于第一次用上Struts2框架做Web开发的体验……的主要内容,如果未能解决你的问题,请参考以下文章