struts入门笔记总结
Servlet与struts的区别
启动
servlet:无
struts:配置filter
创建
servlet:继承HttpServlet,实现doget,dopost,
添加注解,或者配置web.xml
struts:继承ActionSupport,写一个带有String返回值且抛出一个异常的函数
配置struts.xml,struts.xml是在src目录下
创建Action举例 UserAction.java
package com.sikiedu.web;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport implements ModelDriven<User>{
public User user=new User();
public String execute() throws Exception {
System.err.println("我已经运行");
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
配置举例
<?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>
<!-- name配置包名 -->
<package name="MyPackage" namespace="/" extends="struts-default">
<action name="LoginAction" class="com.sikiedu.web.UserAction" method="execute">
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
</package>
</struts>
封装参数
servlet:导入包BeanUtils,根据name属性自动封装
struts:实现ModelDriven接口,实现getModel方法
转发与重定向
Servlet
转发
request.getRequestDispatcher("/login.jsp").forward(request, response);;
重定向
response.sendRedirect(request.getContextPath()+"/index.html");
struts
转发:package—action—result默认为转发
<!-- name配置包名 -->
<package name="MyPackage" namespace="/" extends="struts-default">
<action name="LoginAction" class="com.sikiedu.web.UserAction" method="execute">
<result name="success" >/index.html</result><!-- 默认此处为转发-->
<result name="error">/login.jsp</result>
</action>
</package>
重定向 package—action—result中的type=“redirect”
<package name="MyPackage" namespace="/" extends="struts-default">
<action name="LoginAction" class="com.sikiedu.web.UserAction" method="execute">
<result name="success" type="redirect">/index.html</result><!--重定向 -->
<result name="error">/login.jsp</result>
</action>
</package>
struts创建Action的三种方式
继承ActionSupport并实现ModelDriven的接口然后在struts.xml中配置action
package com.sikiedu.web;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport implements ModelDriven<User>{
public User user=new User();
public String execute() throws Exception {
System.err.println("我已经运行");
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
<struts>
<!-- name配置包名 -->
<package name="MyPackage" namespace="/" extends="struts-default">
<action name="LoginAction" class="com.sikiedu.web.UserAction" method="execute">
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
</package>
</struts>
不继承父类也不实现任何接口,创建一个XXXAction类并构建一个execute方法,然后在struts.xml中配置
package com.sikiedu.web;
public class DefaultAction {
public String execute(){
System.out.println("这是一个普通的action");
return null;
}
}
<package name="MyPackage" namespace="/" extends="struts-default">
<action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
</package>
创建一个XXXAction只实现Action接口,然后在struts.xml中配置
package com.sikiedu.web;
import com.opensymphony.xwork2.Action;
public class ImplAction implements Action {
@Override
public String execute() throws Exception {
System.out.println("这是实现了Action接口的Action");
return null;
}
}
<action name="LoginImplAction" class="com.sikiedu.web.ImplAction" method="execute"></action>
总结
实现Action接口的方法比什么都不继承和实现的方法要好
继承ActionSupport并实现ModelDriven接口的方法要比只实现Action接口的方法更完善
如何创建struts.xml
核心配置
<struts>
<!-- name配置包名 -->
<!--namespace:给Action的访问路径定义一个命名空间 namespace="/user" 则需要访问http://localhost:8080/StrutsForum/user/LoginAction -->
<package name="MyPackage" namespace="/" extends="struts-default">
<!-- action:配置action类
name:决定了action访问的资源名称 相当于servlet:url-pattern
class:action的完整类名
method:制定调用action中的哪个方法来去处理请求-->
<action name="LoginAction" class="com.sikiedu.web.UserAction" method="execute">
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
<action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
<action name="LoginActionImpl" class="com.sikiedu.web.ImplAction" method="execute"></action>
</package>
</struts>
动态方法调用
struts.xml 根目录/LoginAction_方法名
<?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>
<!--struts2.5版本之后 动态方法需要声明下 -->
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="MyPackage" namespace="/" extends="struts-default">
<global-allowed-methods>login,register</global-allowed-methods>
<action name="LoginAction_*" class="com.sikiedu.web.UserAction" method="{1}">
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
</package>
</struts>
public String login() throws Exception {
System.err.println("login方法");
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
public String register() throws Exception{
System.out.println("register方法");
return null;
}
结果集的处理
1.转发
2.重定向
3.转发到Action
struts.xml
<action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
<action name="LoginActionImpl" class="com.sikiedu.web.ImplAction" method="execute">
<!-- 转发到LoginActionDefault -->
<result name="defaultAction" type="chain">LoginActionDefault</result>
</action>
ImplAction.java
public class ImplAction implements Action {
@Override
public String execute() throws Exception {
System.out.println("这是实现了Action接口的Action");
return "defaultAction";
}
}
DefaultAction.java
public class DefaultAction {
public String execute(){
System.out.println("这是一个普通的action");
return null;
}
}
输入 根目录/LoginActionImpl 控制台输出顺序 这是实现了Action接口的Action—>这是一个普通的action
跳转是由result来完成 而此时的路径还是根目录/LoginActionImp 转发路径是不会更改的
4.重定向到Action
ImplAction.java
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class ImplAction implements Action {
@Override
public String execute() throws Exception {
System.out.println("这是实现了Action接口的Action");
return "defaultAction";
}
public String login() {
//得到原生的request域 这里设置的名字和密码都是错误的
// ServletActionContext.getRequest().setAttribute("username", "123");
// ServletActionContext.getRequest().setAttribute("password", "123");
//使用的是ActionContext
ActionContext.getContext().put("username", "123");
ActionContext.getContext().put("password", "123");
return "toLogin";
}
}
struts.xml 浏览器输入 根目录/LoginActionImpl_login 即为调用LoginActionImpl的login方法
然后在LoginActionImpl的login方法中接收到toLogin的参数正好调用result name=“toLogin” type="redirectAction"的结果集,在这个结果集中
又指定了重定向到LoginAction_Login方法上,并传出两个参数
<struts>
<!--struts2.5版本之后 动态方法需要声明下 -->
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="MyPackage" namespace="/" extends="struts-default">
<!-- regex:.* 可以指代所有方法 -->
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="LoginAction_*" class="com.sikiedu.web.UserAction" method="{1}">
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
<action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
<action name="LoginActionImpl_*" class="com.sikiedu.web.ImplAction" method="{1}">
<!-- 转发到LoginActionDefault -->
<result name="defaultAction" type="chain">LoginActionDefault</result>
<!-- 重定向到Action(LoginAction_*) -->
<result name="toLogin" type="redirectAction">
<param name="actionName">LoginAction_login</param><!-- 这个是指定重定向action的名字 -->
<param name="username">${username}</param>
<param name="password">${password}</param>
</result>
</action>
</package>
</struts>
UserAction.java LoginAction_login方法
public String login() throws Exception {
System.err.println("login方法");
System.err.println(user.getUsername());
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
最终页面链接显示 根目录/LoginAction_login.action?username=123&password=123
页面显示 用户名或密码错误 控制台打印 login方法 123
log4j的配置以及解决中文乱码
lib下需要加入log4j-api-2.12.1.jar和log4j-core-2.11.0.jar并buildPath,然后在src下创建log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
<RollingFile name="RollingFile" fileName="logs/strutslog1.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d{MM-dd-yyyy} %p %c{1.} [%t] -%M-%L- %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
<DefaultRolloverStrategy fileIndex="max" max="2"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.opensymphony.xwork2" level="WAN"/>
<Logger name="org.apache.struts2" level="WAN"/>
<Root level="warn">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
解决中文乱码,如下所示
<?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>StrutsForum</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.class</filter-class>
<init-param><!-- 解决中文乱码 -->
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
参数传递
接收参数
第一种
在XxxAction(此Action要继承ActionSupport并且实现ModelDriven<传入对象>接口)中New一个domain包下的对象,并在getModel方法中返回你New的那个对象
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport implements ModelDriven<User>{
public User user=new User();//一定要New出来,并且不能加get和set方法
public String login() throws Exception {
System.out.println("login方法");
System.out.println(user.getUsername());
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
public String register() throws Exception{
System.out.println("register方法");
return null;
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;//这里要返回你创建的那个对象
}
}
第二种方法 属性驱动
此Action只继承ActionSupport但并不实现ModelDriven<对象>接口,你需要把使用的属性和对象创建出来并把属性加入对象中
这种方法需要在此类中添加属性的get和set方法
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport {
public String username;
public String password;
public String login() throws Exception {
System.out.println("login方法");
System.out.println(username+":"+password);
User user=new User();
user.setUsername(username);
user.setPassword(password);
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String register() throws Exception{
System.out.println("register方法");
return null;
}
}
第三种
此Action只继承ActionSupport但并不实现ModelDriven<对象>接口,需要声明一个对象并添加get和set方法,而且在login.jsp中的登陆表单中的input标签中的name="username"变成name=“user.username”,password与这个一样
<form action="${pageContext.request.contextPath}/LoginAction_login" method="post">
<div class="register-box">
<label for="username" class="username_label"> 用 户 名 <input
maxlength="20" name="user.username" type="text" placeholder="您的用户名和登录名" />
</label> <!--本来是name="username" 更改了name属性-->
<div class="tips"></div>
</div>
<div class="register-box">
<label for="username" class="other_label"> 设 置 密 码 <input
maxlength="20" type="password" name="user.password"
placeholder="建议至少使用两种字符组合" /> <!--本来是name="password" 更改了name属性-
</label>
<div class="tips" style="color:red">${error }</div>
</div>
<div class="arguement">
<input type="checkbox" id="xieyi" /> 阅读并同意 <a
href="javascript:void(0)">《你问我答用户注册协议》</a> <a href="register.html">没有账号,立即注册</a>
<div class="tips"></div>
</div>
<div class="submit_btn">
<button type="submit" id="submit_btn">立 即 登录</button>
</div>
</form>
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport {
public User user; //注意 声明的这个对象需要添加get和set方法
public String login() throws Exception {
System.out.println("login方法");
System.out.println(user.getUsername()+":"+user.getPassword());
UserService userService=new UserService();
boolean success=userService.findUser(user);
if(success) {
return "success";
}else {
ServletActionContext.getRequest().setAttribute("error", "用户名或密码错误");
return "error";
}
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String register() throws Exception{
System.out.println("register方法");
return null;
}
}
传递参数
ActionContext是一个Map集合 你想获取的参数都在ActionContext中,ActionContext域比原生的Request和Response域更加强大
public String login() {
//得到原生的request域 这里设置的名字和密码都是错误的
// ServletActionContext.getRequest().setAttribute("username", "123");
// ServletActionContext.getRequest().setAttribute("password", "123");
//ActionConext 与request 生命周期是一样的 但是这两个是两个域
//使用的是ActionContext的put 其实是直接在request域的调用setAttr
ActionContext.getContext().put("username", "123");
ActionContext.getContext().put("password", "123");
//获取Session
Map<String,Object> session=ActionContext.getContext().getSession();
session.put(key, value);
//获取Application
Map<String,Object> application=ActionContext.getContext().getApplication();
application.put(key, value);
//获得原生的request
HttpServletRequest request=ServletActionContext.getRequest();
//获得 原生的response
HttpServletResponse response=ServletActionContext.getResponse();
return "toLogin";
}
接受传递过来的参数 这个两段代码是重定向到某一个Action里的方法内添加的
System.out.println("session域:::::"+ActionContext.getContext().getSession().get("mysession"));
System.out.println("application域::::"+ActionContext.getContext().getApplication().get("myapplication"));
ognl表达式
ognl其实就相当于jstl+el 导入标签 <%@taglib uri="/struts-tags" prefix=“s”%>
<div class="tab">
<s:iterator value="pasteList" var="paste">
<div class="dvques">
<div class="quesCount">
<div class="count">
<s:property value="#paste.ansnum" /><!-- 如果要访问的数据是包装类型,我们要加# -->
</div>
<div class="ques">回答数</div>
</div>
<div class="quesContent">
<div class="quesTitle">
<s:property value="offer" />
<image src="images/bean.jpg" class="bean"> <span
class="spanques"> <s:property value="#paste.title" />
</span>
</div>
<div class="qContent">
<s:property value="#paste.content" />
</div>
<div class="tags">
<span class="tag">excel</span><span class="tag">程序</span>
</div>
<div class="quesUser">
<image src="images/0.gif" class="imguser" />
<div class="userName">
<s:if test="ansnum%2 == 0">
张大值
</s:if>
<s:else>
XXX
</s:else>
<div class="liulan">浏览(9) 30分钟前</div>
</div>
</div>
</div>
</div>
</s:iterator>
</div>
valueStack分析三种获得表单数据原理
像当request session application三个域中都有name属性,<s:property value="#name"/>会先从request中取,然后session,再application
action的原理
interceptor是拦截器,拦截器其实是个stack
result的原理
<action name="LoginActionImpl_*" class="com.sikiedu.web.ImplAction" method="{1}">
<!-- 转发到LoginActionDefault -->
<result name="defaultAction" type="chain">
<param name="actionName">LoginActionDefault</param>
</result>
<!-- 重定向到Action(LoginAction_*) -->
<result name="toLogin" type="redirectAction">
<param name="actionName">LoginAction_login</param><!-- 这个是指定重定向action的名字 -->
<param name="username">${username}</param>
<param name="password">${password}</param>
</result>
</action>
拦截器
创建拦截器的两种方式
每次访问有拦截器的Action就会调用一次拦截器,拦截器只能控制访问Action,不能控制访问jsp
第一种 继承MethodFilterInterceptor类
package com.sikiedu.web.intercept;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
//推荐这一种方法
public class MyIntercept extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//获取session
Map<String,Object> session=ActionContext.getContext().getSession();
//判断session中是否有user数据
Object object=session.get("user");
if(object!=null) {
//有 放行
return invocation.invoke();
}else {
//没有,重定向到login.jsp
return "toLogin";
}
}
第二种 实现Interceptor接口
package com.sikiedu.web.intercept;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class Intercept implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//放行
return invocation.invoke();
}
}
struts.xml中拦截器的配置 配置全局结果集用global-results标签注意使用顺序
<?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>
<!--struts2.5版本之后 动态方法需要声明下 -->
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="MyPackage" namespace="/" extends="struts-default">
<interceptors>
<!--注册拦截器 -->
<interceptor name="myIntercept" class="com.sikiedu.web.intercept.MyIntercept"></interceptor>
<!-- 注册拦截器的栈 -->
<interceptor-stack name="myStack">
<!-- 引入自己创建的拦截器 -->
<interceptor-ref name="myIntercept"></interceptor-ref>
<!-- 引入struts给你写的拦截器(20个左右)-->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 指定包中的默认拦截器栈 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>
<!-- 配置全局结果集 相当于在每一个包下的action下都写了一个,
注意顺序 default-class-ref?, global-results?, global-allowed-methods?-->
<global-results>
<result name="toLogin" type="redirect">/login.jsp</result>
</global-results>
<!-- regex:.* 可以指代所有方法 -->
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="LoginAction_*" class="com.sikiedu.web.UserAction" method="{1}">
<!-- 设置默认为转发 -->
<result name="success" type="redirect">/index.html</result>
<result name="error">/login.jsp</result>
</action>
<action name="LoginActionDefault" class="com.sikiedu.web.DefaultAction" method="execute"></action>
<action name="LoginActionImpl_*" class="com.sikiedu.web.ImplAction" method="{1}">
<!-- 转发到LoginActionDefault -->
<result name="defaultAction" type="chain">LoginActionDefault</result>
<!-- 重定向到Action(LoginAction_*) -->
<result name="toLogin" type="redirectAction">
<param name="actionName">LoginAction_login</param><!-- 这个是指定重定向action的名字 -->
<param name="username">${username}</param>
<param name="password">${password}</param>
</result>
</action>
</package>
</struts>
总结-一个struts小案例
bug
本人学习struts时,一直出现下面错误,上网搜索后没有得到正确的解决结果
处理方法是web.xml文件中配置struts的filter-class标签中引用filter的类名不要加.class后缀就可以了
就如org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter这样子去掉.class后缀即可
严重: 启动过滤器异常
java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.class
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1360)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1182)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:546)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:527)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:262)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4546)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5191)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
这些是我导的jar包和目录工程
package包及class
com.sikiedu.dao
PasteDao.java
package com.sikiedu.dao;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.sikiedu.domain.Paste;
import com.yl.lain.utils.C3p0DataSourceUtils;
public class PasteDao {
public List<Paste> findAllPaste() throws SQLException {
QueryRunner runner=new QueryRunner(C3p0DataSourceUtils.getDataSource());
String sql="select * from paste";
return runner.query(sql, new BeanListHandler<Paste>(Paste.class));
}
}
UserDao.java
package com.sikiedu.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.sikiedu.domain.User;
import com.yl.lain.utils.C3p0DataSourceUtils;
public class UserDao {
public User findUser(User user) throws SQLException {
QueryRunner runner=new QueryRunner(C3p0DataSourceUtils.getDataSource());
String sql="select * from user where username=? and password=?";
return runner.query(sql,new BeanHandler<User>(User.class),user.getUsername(),user.getPassword());
}
}
com.sikiedu.domain
Paste.java
package com.sikiedu.domain;
public class Paste {
private String id;
private Integer ansnum;
private Integer offer;
private String title;
private String content;
//这里是省略了get和set方法以及有参构造方法
}
User.java
package com.sikiedu.domain;
public class User {
private String username;
private String password;
//这里是省略了get和set方法以及有参构造方法
}
com.sikiedu.service
PasteService.java
package com.sikiedu.service;
import java.sql.SQLException;
import java.util.List;
import com.sikiedu.dao.PasteDao;
import com.sikiedu.domain.Paste;
public class PasteService {
public List<Paste> findAllPaste() throws SQLException {
PasteDao pasteDao =new PasteDao();
return pasteDao.findAllPaste();
}
}
UserService.java
package com.sikiedu.service;
import java.sql.SQLException;
import com.sikiedu.dao.UserDao;
import com.sikiedu.domain.User;
public class UserService {
public boolean findUser(User user) throws SQLException {
UserDao userDao=new UserDao();
User temp=userDao.findUser(user);
return temp==null?false:true;
}
}
com.sikiedu.web
PasteAction.java
package com.sikiedu.web;
import java.util.List;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.sikiedu.domain.Paste;
import com.sikiedu.service.PasteService;
public class PasteAction extends ActionSupport {
public String getAllPaste() throws Exception {
PasteService pasteService=new PasteService();
List<Paste> pasteList=pasteService.findAllPaste();
ActionContext.getContext().put("pasteList",pasteList );
return "index";
}
}
UserAction.java
package com.sikiedu.web;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sikiedu.domain.User;
import com.sikiedu.service.UserService;
public class UserAction extends ActionSupport implements ModelDriven<User> {
public User user=new User();
public String login() throws Exception {
//封装User
//调用UserService中的判断用户是否存在的方法
UserService userService=new UserService();
boolean isSuccess=userService.findUser(user);
//拿到返回值
if(isSuccess) {
//成功 在session域中放置user对象
ActionContext.getContext().getSession().put("user", user);
return "getAllPaste";
}else {
//失败 添加错误信息 转发到login.jsp
ActionContext.getContext().put("error", "用户名或密码错误");
return "login";
}
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
com.sikiedu.web.intercept
UserIntercept.java
package com.sikiedu.web.intercept;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
//创建拦截器 如果用户没有登陆就在login.jsp页面
public class UserIntercept extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//获取session
Map<String,Object> session=ActionContext.getContext().getSession();
//判断session中是否有user数据
Object object=session.get("user");
if(object!=null) {
//有 放行
return invocation.invoke();
}else {
//没有,重定向到login.jsp
return "toLogin";
}
}
}
src下的c3p0-config.xml和struts.xml
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/struts?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8</property>
<property name="user">login</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
struts.xml
<?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>
<!-- 动态结果集 -->
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="fourm" namespace="/" extends="struts-default">
<interceptors>
<!--注册拦截器 -->
<interceptor name="UserIntercept" class="com.sikiedu.web.intercept.UserIntercept"></interceptor>
<!-- 注册拦截器的栈 -->
<interceptor-stack name="myStack">
<!-- 引入自己创建的拦截器 -->
<interceptor-ref name="UserIntercept">
<!-- 不让拦截器拦截login方法 -->
<param name="excludeMethods">login</param>
</interceptor-ref>
<!-- 引入struts自带的拦截器-->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 指定包中的默认拦截器栈 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>
<!-- 在UserIntercept中没有的话会返回toLogin,但是在每个Action中写一个太麻烦了所以定义一个全局结果集 -->
<global-results>
<!-- 重定向 -->
<result name="toLogin" type="redirect">/login.jsp</result>
</global-results>
<global-allowed-methods>regex:.*</global-allowed-methods> <!-- 动态方法调用 -->
<action name="UserAction_*" class="com.sikiedu.web.UserAction" method="{1}">
<!-- 转发到Action -->
<!--<result name="getAllPaste" type="chain">PasteAction_getAllPaste</result> -->
<!-- 重定向到Action -->
<result name="getAllPaste" type="redirectAction">PasteAction_getAllPaste</result>
<!-- 默认转发 -->
<result name="login">/login.jsp</result>
</action>
<action name="PasteAction_*" class="com.sikiedu.web.PasteAction" method="{1}">
<result name="index">/index.jsp</result>
</action>
</package>
</struts>
/ForumProject/WebContent/WEB-INF/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>ForumProject</display-name>
<filter>
<filter-name>Struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class><!--注意这里千万不能加.class后缀,会报过滤器异常错误-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
ForumProject/WebContent/下的jsp文件
index.jsp 注意ognl表达式的使用 <s:property value=" "/>
<div class="tabContent">
<div class="dvtags">
<a class="curenttag">待解决</a><span class="line"></span><a>高分</a><span
class="line"></span><a>新回答</a><span class="line"></span><a>已解决</a>
</div>
<div class="tab">
<s:iterator value="pasteList" var="paste">
<div class="dvques">
<div class="quesCount">
<div class="count">
<s:property value="#paste.ansnum" /><!-- 如果要访问的数据是包装类型,我们要加# -->
</div>
<div class="ques">回答数</div>
</div>
<div class="quesContent">
<div class="quesTitle">
<s:property value="#paste.offer" />
<image src="images/bean.jpg" class="bean"> <span
class="spanques"> <s:property value="#paste.title" />
</span>
</div>
<div class="qContent">
<s:property value="#paste.content" /> <!-- ognl内置标签 -->
</div>
<div class="tags">
<span class="tag">excel</span><span class="tag">程序</span>
</div>
<div class="quesUser">
<image src="images/0.gif" class="imguser" />
<div class="userName">
<s:if test="ansnum%2 == 0">
张大值
</s:if>
<s:else>
XXX
</s:else>
<div class="liulan">浏览(9) 30分钟前</div>
</div>
</div>
</div>
</div>
</s:iterator>
</div>
<div class="tab hidden">2</div>
<div class="tab hidden">3</div>
<div class="tab hidden">4</div>
</div>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/head.css" />
<link rel="stylesheet" type="text/css" href="css/login.css" />
</head>
<body>
<div class="dvhead">
<div class="dvlogo">
<a href="index.html">你问我答</a>
</div>
<div class="dvsearch">10秒钟注册账号,找到你的同学</div>
<div class="dvreg">
已有账号,立即 <a href="login.html">登录</a>
</div>
</div>
<section class="sec">
<form action="${pageContext.request.contextPath}/UserAction_login" method="post">
<div class="register-box">
<label for="username" class="username_label"> 用 户 名 <input
maxlength="20" name="username" type="text" placeholder="您的用户名和登录名" />
</label>
<div class="tips"></div>
</div>
<div class="register-box">
<label for="username" class="other_label"> 设 置 密 码 <input
maxlength="20" type="password" name="password"
placeholder="建议至少使用两种字符组合" />
</label>
<div class="tips" style="color:red">${error }</div>
</div>
<div class="arguement">
<input type="checkbox" id="xieyi" /> 阅读并同意 <a
href="javascript:void(0)">《你问我答用户注册协议》</a> <a href="register.html">没有账号,立即注册</a>
<div class="tips" style="color:red"> <s:property value="#error"/> </div>
</div>
<div class="submit_btn">
<button type="submit" id="submit_btn">立 即 登录</button>
</div>
</form>
</section>
<script src="js/index.js" type="text/javascript" charset="utf-8"></script>
</body>