首页 > 其他分享 >Struts2学习总结

Struts2学习总结

时间:2022-11-24 18:06:56浏览次数:45  
标签:总结 username return String 学习 Struts2 user password public


struts2其实主要充当MVC模式的View层,主要是为了代替Servlet获取请求参数那些繁琐的操作。它提供的功能主要有如下2点:

1.通过属性绑定和模型绑定来简化传统servlet需要使用request对象来getParameter。
2.运用了AOP的设计思想,使用拦截器来扩展功能
3.提供了一个json库来处理异步请求
4.文件上传

下面就来说一下这两个功能的实现方式和遇到的坑,这里要特别注意的是,需要清楚自己的struts2版本,因为版本的差异会导致配置的细微差别,因为这个原因我也踩了很多坑,这里我的struts版本是2.5.8


一、传统的接收表单参数并获取(这里将会具体介绍struts2的配置

1.首先在 ​​web.xml​​ 中加入过滤器配置,这里也是根据struts2的具体版本来配置,可以在官网下载完整版,看一下apps里面的源代码,拷贝过来即可。

<!-- struts2 filter -->
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- END SNIPPET: filter -->

2.在项目的 ​​src​​​ 目录下新建一个 ​​struts.xml​​ 文件,DOCTYPE头信息也可以拷贝下载回来的项目的代码,一下是配置文件的基本结构。

<?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>

</struts>

3.然后可以在这个文件中进行具体路由action的配置,也可以使用include命令把配置文件分出去,代码如下(要注意的是这里的file路径写的是src之后的路径,一开始不用带斜杠)

<include file="com/xiaoxiaohei/action/hello.xml"></include>

4.配置package。在这里,name属性是自定义的,唯一就好,extends固定为struts-default(后面说道json的时候才需要改),namespace以斜杠开始后面可以跟上一些自定义的名称:

<package name="demo2" extends="struts-default" namespace="/">
</package>

5.配置package列面的action,这就是具体的路由配置了,具体是一个url(name)指向一个类(class)里面的一个方法(method),如果没定义method,默认是execute方法(这里也要注意的是,不如果引入额外的包,可能导致默认调用的方法是index),代码如下:

<action name="data3" class="com.xiaoxiaohei.form.DataDemo3Action" ></action>

为了减少代码,也可以使用通配符进行配置。不过这里有个坑,我使用的2.5.8版本需要先在(package标签外面struts标签内部加上如下代码):

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

然后在package里面加上如下代码:

<!-- 必须写action在前面 -->
<global-allowed-methods>regex:.*</global-allowed-methods>

才可以进行通配符的配置:

<action name="customer_*" class="com.xiaoxiaohei.interceptor.CustomerAction" method="{1}">
</action>

在action的里面,可以设置result标签,根据返回值来重定向到页面:

<result name="success">success.jsp</result>

6.配置好之后先上一个简单的表单页面:

<%@ page language="java" contentType="text/html; charset=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>

<h1>login</h1>

<form action="${pageContext.request.contextPath}/customer_login.action" method="post" enctype="multipart/form-data">
username:<input name="username" type="text" > <br>
password:<input name="password" type="text" > <br>
ok:<input type="submit">
</form>

</body>
</html>

在页面中向服务器传username和password参数。

7.后台数据的获取:

首先需要创建一个action类来继承ActionSupport,然后实现execute方法,模板如下。

public class Form1DemoAction extends ActionSupport {
@Override
public String execute() {
return NONE;
}
}

a.第一种获取参数的方法:实现ServletRequestAware接口

public class Form1DemoAction extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;

@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("start");
//1.get ActionContext
ActionContext context = ActionContext.getContext();
//2.get params
Map<String,Parameter> map = context.getParameters();

Set<String> keys = map.keySet();
for(String key : keys) {
Parameter obj = map.get(key);

System.out.println(key + "=" + Arrays.toString(obj.getMultipleValues()));
}

return NONE;
}

@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.request = request;
}
}

b.第二种方法:使用ServletActionContext对象类获取servlet的request对象:

public class Form2DemoAction extends ActionSupport {
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("req", "reqValue");

HttpSession session = request.getSession();
session.setAttribute("sess", "sessionValue");

ServletContext context = ServletActionContext.getServletContext();
context.setAttribute("context", "contextValue");

String username = request.getParameter("username");
String password = request.getParameter("password");
String address = request.getParameter("address");



System.out.println(username + ":" + password + ":" + address);

return NONE;
}
}

c.使用属性驱动的方式进行封装(在action中定义字段和相应的get set方法):

public class DataDemo1Action extends ActionSupport {
private String username;
private String password;
private String address;


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 getAddress() {
return address;
}


public void setAddress(String address) {
this.address = address;
}


@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(username + "---" + password + "---" + address);

ActionContext context = ServletActionContext.getContext();
Map<String, Parameter> map = context.getParameters();

System.out.println("username=" + map.get("username"));

return NONE;
}

}

c.模型驱动(一般使用这个方法)。继承ModelDriven类

public class DataDemo2Action extends ActionSupport implements ModelDriven<User> {
private User user = new User();


@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(this.user);
return NONE;
}

@Override
public User getModel() {
// TODO Auto-generated method stub
return this.user;
}
}

d.属性驱动也可以封装对象,不过jsp页面的name需要作出相应的修改,如下代码就是要改成user.username和user.password

<form action="${pageContext.request.contextPath}/data3.action" method="post">
username:<input name="user.username" type="text" > <br>
password:<input name="user.password" type="text" > <br>
ok:<input type="submit">
</form>
public class DataDemo3Action extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private User user;



public User getUser() {
return user;
}



public void setUser(User user) {
this.user = user;
}



@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(user);
return NONE;
}

}

上面用到的Java bean如下

public class User {
private String username;
private String password;
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;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}



}

二、拦截器,拦截器简单的说就是用来在action之前来做一些公共的操作(比如说action的访问权限等)。

1.首先定义一个拦截器类,继承MethodFilterInterceptor,在这里可以做一些操作,比如说获取session做一些校验等:

public class LoginInterceptor extends MethodFilterInterceptor {

@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
HttpServletRequest request = ServletActionContext.getRequest();
Object obj = request.getSession().getAttribute("user");
Object username = request.getSession().getAttribute("username");
System.out.println(obj);
System.out.println(username);

if(obj != null && obj instanceof User && ((User)obj).getUsername().equals("admin")) {
return invocation.invoke();
}

return "failed";
}

}

2.在struts.xml中配置与具体action的关联,先在interceptors中声明,然后在action中使用,注意:如果还需使用系统内部提供的拦截器,那么需要加上一条name=”defaultStack”的拦截器配置

<package name="demo2" extends="struts-default" namespace="/">

<!-- 必须写在action前面 -->
<interceptors>
<interceptor name="loginInterceptor" class="com.xiaoxiaohei.interceptor.LoginInterceptor"></interceptor>
</interceptors>

<!-- 必须写action在前面 -->
<global-allowed-methods>regex:.*</global-allowed-methods>

<action name="customer_*" class="com.xiaoxiaohei.interceptor.CustomerAction" method="{1}">
<interceptor-ref name="loginInterceptor">
<param name="excludeMethods">login</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>

<result name="login" type="json">
<param name="root">map</param>
</result>
<result name="failed">failed.jsp</result>
<result name="success">success.jsp</result>

</action>
</package>

三、返回json对象

1.首先引入必要的两个包:

struts2-json-plugin-2.5.8.jar
json-lib-2.3-jdk15.jar

2.把package的extends改成json-default

<package name="demo2" extends="json-default" namespace="/">

在result中定义一个param指定返回的字段(如果不指定,默认返回ModelDriven的Java bean):

<result name="login" type="json">
<param name="root">map</param>
</result>

然后在相应的action类中定义一个成员变量和上面配置的变量名一样就好,就上面的配置,我就需要定义个名为map的变量,声明get/set方法:

private Map<String, Object> map = new HashMap<>();

public String login() throws Exception {
System.out.println(user);
map.put("abc", "aaaaa");

return "login";
}

四、这里再补充说一下文件上传,就贴上代码就好,只需要注意action类的那几个file相关的变量名是固定的就好,input[type=file]标签的name名字要和action类的File对象的变量名保持一致

<%@ page language="java" contentType="text/html; charset=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>

<h1>login</h1>

<form action="${pageContext.request.contextPath}/customer_login.action" method="post" enctype="multipart/form-data">
username:<input name="username" type="text" > <br>
password:<input name="password" type="text" > <br>
file:<input type="file" name="file">
ok:<input type="submit">
</form>

</body>
</html>
public class CustomerAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();

private File file;
private String fileFileName;
private String fileContentType;

private Map<String, Object> map = new HashMap<>();





public Map<String, Object> getMap() {
return map;
}


public void setMap(Map<String, Object> map) {
this.map = map;
}


public File getFile() {
return file;
}


public void setFile(File file) {
this.file = file;
}


public String getFileFileName() {
return fileFileName;
}


public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
}


public String getFileContentType() {
return fileContentType;
}


public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
}


public User getUser() {
return user;
}


public void setUser(User user) {
this.user = user;
}


@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return NONE;
}


public String login() throws Exception {
System.out.println(user);

if ("admin".equals(user.getUsername())) {
//session
ServletActionContext.getRequest()
.getSession().setAttribute("user", user);
ServletActionContext.getRequest()
.getSession().setAttribute("username", user.getUsername());

map.put("abc", "aaaaa");

String root = ServletActionContext.getServletContext().getRealPath("/upload");
InputStream is = new FileInputStream(file);
OutputStream os = new FileOutputStream(new File(root, fileFileName));

System.out.println("fileFileName=" + fileFileName);

System.out.println("File:" + file.getName());
System.out.println("file:" + file.getPath());

byte[] buffer = new byte[500];
int length = 0;
while(-1 != (length=is.read(buffer, 0, buffer.length))) {
os.write(buffer, 0, length);
}
os.close();
is.close();

return "login";
} else {
ServletActionContext.getRequest()
.getSession().removeAttribute("user");
ServletActionContext.getRequest()
.getSession().removeAttribute("username");
return "failed";
}
}

public String loginSuccess() {
return "login";
}

@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}

}


标签:总结,username,return,String,学习,Struts2,user,password,public
From: https://blog.51cto.com/u_15890522/5884414

相关文章

  • C# 如何将Word、Excel、PPT转成PDF文件(使用Spire提供的组件)学习
    第一步:新建一个winform项目,下载Spire组件dll下载Spire.Doc、Spire.XLS、Spire.Presentation,路径:工具--NuGet包管理器--管理解决方案NuGet程序包1)Spire.Doc:word转成其它......
  • Hibernate学习总结
    Hibernate主要是在开发中对Dao(databaseaccessobject)层进行操作,因为他主要是操作数据库的,所以hibernate主要用于数据库的增删查改,下面就来一一介绍:1.配置hibernate,在src目......
  • K8S学习记录
    kubelet在启动之后会一直闪烁运行;systemctlstatuskubelet之后,会发现有时候runnning有时候退出,属于一直闪烁。(尚硅谷P34视频最后)systemctl命令 ctl表示controller。......
  • android学习布局管理器的一些心得——基础篇
    LinearLayout---线性布局   在LinearLayout中,如下方法是比较容易忘记的,而且这些方法是LinearLayout常用的方法:1.android:gravity(在代码编程实现中的方法为:setGravit......
  • android学习布局管理器的一些心得2——基础篇
    RelativeLayout-----相对布局1.RelativeLayout不是相对于单体的布局,每一个组件的布局都要依赖另外一个或多个组件,这个布局表示的是一个组件相对于另一个组件(或者是整个Rel......
  • 如何为机器学习进行数据标签、版本控制和管理
    一个丰富食物数据集的案例研究介绍几个月前,托洛卡和ClearML公司一起创建了此联合项目。我们的目标是向其他机器学习的从业者展示从收集数据到将数据输入机器学习模型之......
  • linux学习用到的命令
    创建快件方式ln创建目录的快件方式sudoln-s/root/myhack//root/Desktop以上指令是创建软链接到桌面。ln-s/mnt/hgfs/VMware_share//home/ICer/Vm_Share指令......
  • Vue学习笔记(2)
    31.父子组件通信1.父亲给儿子通信利用props2.儿子给父亲通信,先利用props让父亲给儿子传个函数,再让儿子再调用函数32.todolist案例总结组件化编码流程:(1).拆分静态组......
  • 【Win32 API学习】模拟键盘输入和鼠标输入
    在Windows大行其道的今天,windows界面程序受到广大用户的欢迎。对这些程序的操作不外乎两种,键盘输入控制和鼠标输入控制。有时,对于繁杂的,或重复性的输入操作,我们能否通过编......
  • 【go】go微服务框架kratos学习笔记十(熔断器)
    什么是熔断假设存在这样的调用链:服务A->服务B->服务C如果服Ccrash或者一些原因导致不可用,服B可能会阻塞很多线程/协程,如果短时间内大量积压,导致系统资源耗尽服B......