快速Struts2完整版本
1:创建struts2项目
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5</version>
</dependency>
()
2:在web.xml中配置核心的过虑器
<filter>
<filter-name>s2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>s2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在s2.3.x版本中
配置的过虑器: org.apache.struts2.dispatcher.ng.StrutsPreparedAndExecutionFilter
在s2.5版本中配置的:
org.apache.struts2.dispatcher.StrutsPreparedAndExecutionFilter
Struts2的执行流程:
通过上面的问题:
1:StrutsPreparedAndExecution里面用的是 ThreadLocal模式维护当前线程的对象,同时对requst进行包装,即包装模式。
2:ActionInvocation是迭代器模式。actionInvocation.invoke()是指执行一下拦截器,如果没有则直接执行目标资源。
3:添加struts2的配置文件
4:添加一个登录的action
以下包含三个问题:
1:如何开发一个action
2:如何来接收参数:属性,模型。
3:如何访问域对象。
4:可以在execute中来返回多个字符串。根据不同的字符串,返回不同的地址
接收用户名+密码,如果用户成功,就去显示工作平台:
package cn.s2.login;
import org.apache.commons.lang3.StringUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import cn.s2.domain.User;
public class LoginAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
// 如果用户和密码密码有顺序正好相反则登录成功
String pwd = StringUtils.reverse(user.getPwd());
if (user.getName().equals(pwd)) {
//如果登录成功,则应该将用户的信息保存到Session
ActionContext.getContext().getSession().put("user",user);
return SUCCESS;
} else {
ActionContext.getContext().getSession().put("error", "用户名或密码错误");
return INPUT;
}
}
}
配置:
对于OGNL来说:
如果直接写入值:<s:if test=”name”/> 相当于是从Stack取值。
如果以#开始,则是找取上下文中的值 <s:if test=”#session.name”> 相当于从map.get(session).getAttribute(name)
<form action="<s:url value='/login.action'/>" method="post">
<s:if test="#session.error!=null">
<s:property value="#session.error"/>
</s:if>
Name:<input type="text" name="name" value="${name}"><br>
Pwd:<input type="text" name="pwd"><br>
<input type="submit">
</form>
5:退出
使用同一个Action即可
public String logout() {
ActionContext.getContext().getSession().remove("user");
return INPUT;
}
配置动态的方法调用:
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="s2" extends="struts-default" strict-method-invocation="false">
<action name="login" class="cn.s2.login.LoginAction">
<result>/WEB-INF/views/index.jsp</result>
<result name="input">/index.jsp</result>
</action>
</package>
6:在登录成功以后,要求可以显示所有学生名单
显示的学生名单功能,应该是一个Servlet开发的
所使用的技术:jquery-databales -
要求的数据是:[
{},{},{},{}
]
在struts2里面如何返回json:
实现的方式:
1:可以返回一个一个统一的页面上去,如
<global-results>
<result name=”json”>/WEB-INF/views/pubs/json.jsp</result> 在json.jsp中:${json}
</global-results>
在action中必须要:
Public String queryStuds(){
List<Stud> list =service.query();
String json = JSONArray.toJsonString(list);
ActionContext.getContext().put(“json”,json);
Return “json”;
}
2:自己开发Result从栈顶来获取数据
3:使用json插件,自动从栈顶获取数据
<!-- http://mvnrepository.com/artifact/org.apache.struts/struts2-json-plugin -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.5</version>
</dependency>
public class StudAction extends ActionSupport {
@Override
public String execute() throws Exception {
Random r = new Random();
int ran = r.nextInt(300);
List<Stud> list = new ArrayList<>();
for (int i = 0; i < ran; i++) {
list.add(new Stud(UUID.randomUUID().toString().replace("-", "").substring(0, 10), r.nextInt(100),
"189" + r.nextInt(1000), UUID.randomUUID().toString().replace("-", "")));
}
///
ActionContext.getContext().getValueStack().push(list);
return SUCCESS;
}
}
<action name="stud" class="cn.s2.stud.StudAction">
<result type="json"/>
</action>
7:问题
不安全
没有登录也可以查看所有学生信息:
解决方案:
使用拦截器拦截所有安全的Action
package cn.s2.interceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import cn.s2.domain.User;
public class LoginInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 判断用户是否登录
User user = (User) ActionContext.getContext().getSession().get("user");
if (user == null) {
ActionContext.getContext().put("error", "请先登录!");
return "input";
} else {
return invocation.invoke();
}
}
}
<interceptors>
<interceptor name="loginInterceptor" class="cn.s2.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="secuDefaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginInterceptor"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="secuDefaultStack"></default-interceptor-ref>
8: 验证码
可以使用自定义的reuslt来实现:
public class ImgResult implements Result {
@Override
public void execute(ActionInvocation invocation) throws Exception {
<!-- 配置自定义的result -->
<result-types>
<result-type name="img" class="cn.s2.results.ImgResult"></result-type>
</result-types>
<!-- 开发一个action自动返回这个result -->
<action name="image">
<result name="img"></result>
</action>
<!-- 配置自定义的result -->
<result-types>
<result-type name="img" class="cn.s2.results.ImgResult">
<param name="width">90</param>
<param name="num">6</param>
</result-type>
</result-types>
<!-- 开发一个action自动返回这个result -->
<action name="image">
<result type="img">
<param name="width">120</param>
<param name="num">8</param>
</result>
</action>