Struts
创建struts的一些问题:
1.创建完之后lib需要移动到WEB-INF下面
2.lib里面的jar需要全部重新替换
3.struts-default报错 找到project structure---facets 在struts里面点击铅笔 将struts-core-jar包勾选保存
4.控制台报错web版本不符合 替换为3.0版本
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <!--配置struts的过滤器--> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
struts执行流程
1.tomcat启动:加载应用web.xml文件
2.实例化并初始化过滤器()
3.加载struts.xml配置文件
4.客户端请求hello.action()
5.请求到达过滤器
6.截取请求的动作名称hello,并从struts.xml中找
7.找到后实例化动作类
8.调用对应的动作方法,方法有返回值
9. 根据返回值,找到name取值对应的结果视图
10.找到jsp页面
11.响应浏览器,展示结果
配置文件加载顺序
顺序 配置文件 所在位置
1. default.properties jar包中
2. struts-default.xml jar包中
3. struts-plgin.xml jar包中
4. struts.xml 应用中
5 struts.properties 应用中
6. web.xml 应用中
struts的后缀访问设置和开发模式设置
第一种方式:struts.xml配置文件 struts标签内添加一个 <constant name="struts.action.extension" value="php"></constant>
第二种方式:在src下创建struts.properties 添加 struts.action.extension=html 如果这样会覆盖struts.xml配置文件
第三种:web.xml里面配置 略
开发模式配置:struts.xml配置文件 struts标签内添加一个 <constant name="struts.devMode" value="true"></constant>
struts配置文件
package元素讲解:
<!--package表示包 name:包名在struts.xml文件不能有相同的包名,包名是唯一
extends:继承 固定struts_defalut
abstract:抽象包 被用于继承 一般在抽象包里不声明action
namespace:命名空间,访问路径,默认值是空字符串,可用于模块划分 要注意:命名空间需要加/斜杠
-->
<!--action:动作 name:相当于Servlet的映射路径
class:处理请求的类,相当于servlet类
methond:处理请求的方法
-->
namespace:命名空间,访问路径,默认值是空字符串,可用于模块划分 要注意:命名空间需要加/斜杠
<package name="p1" extends="struts-default" namespace="/n4">
action元素讲解:
访问网址:http://localhost:8080/structsdemo_war_exploded/user/login1 更改login1
第一种方式:
struts.xml文件
<package name="p2" extends="struts-default" namespace="/user"> <action name="login" class="main.java.action.LoginAction1" method="login"> <result name="success">/loginsuccess.jsp</result> </action> </package>
LoginAction1文件
package main.java.action; public class LoginAction1 { public String login() throws Exception { return "success"; } }
第二种方式:
struts.xml文件
<package name="p2" extends="struts-default" namespace="/user"> <action name="login2" class="main.java.action.LoginAction2"> <result name="success">/loginsuccess.jsp</result> </action> </package>
LoginAction2文件
package main.java.action; import com.opensymphony.xwork2.Action; public class LoginAction2 implements Action { @Override public String execute() throws Exception { return "success"; } }
第三种方式:(推荐使用)
struts.xml文件
<package name="p2" extends="struts-default" namespace="/user">
<action name="login3" class="main.java.action.LoginAction3">
<result name="success">/loginsuccess.jsp</result>
</action>
</package>
LoginAction3文件
package main.java.action;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction3 extends ActionSupport {
public String login(){
return SUCCESS;
}
}
修改默认动作类 在package标签内
<!-- 配置默认动作类 -->
<default-class-ref class="main.java.action.LoginAction2"></default-class-ref>
动作访问通配符 * 需要加上红色部分才可以正常运行
<!-- 通配符* -->
<package name="p1" extends="struts-default" namespace="/n1" strict-method-invocation="false">
<action name="*" class="main.java.action.UserAction" method="{1}">
<result name="success">/{1}.jsp</result>
</action>
</package>
<!-- 两个*通配符 -->
<package name="p4" extends="struts-default" namespace="/student" strict-method-invocation="false">
<action name="*_*" class="main.java.action.StudentAction" method="{1}{2}">
<result name="success">/{1}{2}.jsp</result>
</action>
</package>
动态方法的调用(不经常用)
struts标签内配置
<!-- 配置动态方法的调用属性为true -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
版本问题 2.3之后需要加上红色部分 中间是方法名称
<package name="p5" extends="struts-default">
<action name="student" class="main.java.action.StudentAction">
<result name="success">/success.jsp</result>
<allowed-methods>addStudent,findStudent,deleteStudent</allowed-methods>
</action>
</package>
result元素转发和重定向:
<package name="p5" extends="struts-default" namespace="/n1">
<action name="student" class="main.java.action.StudentAction">
<result name="success" type="redirect">/success.jsp</result>
</action>
</package>
chain和redirectAction的使用
同一个package包内
<package name="p5" extends="struts-default" namespace="/n1">
<action name="action1" class="main.java.action.StudentAction">
<result name="success" type="redirectAction">action2</result>
</action>
<action name="action2" class="main.java.action.StudentAction">
<result name="success">/success2.jsp</result>
</action>
</package>
不同package
<package name="p5" extends="struts-default" namespace="/n1">
<action name="action1" class="main.java.action.StudentAction">
<result name="success" type="chain">
//依赖注入
<param name="namespace">/n2</param>
<param name="actionName">action2</param>
</result>
</action>
</package>
<package name="p5" extends="struts-default" namespace="/n2">
<action name="action2" class="main.java.action.StudentAction">
<result name="success">/success2.jsp</result>
</action>
</package>
自定义验证码:
struts.xml
<package name="p1" extends="struts-default" namespace="/n2">
<!--声明结果类型-->
<result-types>
<result-type name="captcha" class="main.java.action.CAPTCHAResult"></result-type>
</result-types>
<action name="checkcode">
<result name="success" type="captcha">
<param name="width">120</param>
<param name="height">30</param>
</result>
</action>
</package>
CAPTCHAResult
package main.java.action;
import cn.dsna.util.images.ValidateCode;
import com.opensymphony.xwork2.ActionInvocation;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import javax.servlet.http.HttpServletResponse;
public class CAPTCHAResult extends StrutsResultSupport {
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
protected void doExecute(String s, ActionInvocation actionInvocation) throws Exception {
//生成验证码
//1.创建一个验证码对象
ValidateCode code = new ValidateCode(width,height,4,6);
//2.获取response对象
HttpServletResponse response = ServletActionContext.getResponse();
//3.把图片返回给客户端
code.write(response.getOutputStream());
}
}
Action接收请求参数的方式
第一种通过request对象:
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> <!--配置一个常量--> <!--1.配置访问的后缀名--> <!--<constant name="struts.action.extension" value="php"></constant>--> <!--2.配置开发者模式--> <constant name="struts.devMode" value="true"></constant> <!-- 配置动态方法的调用属性为true --> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> <package name="p1" extends="struts-default"> <action name="login" class="main.java.action.LoginAction" method="login"> <result name="success">/login.jsp</result> </action> </package> </struts>
action.java
package main.java.action; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.ServletActionContext; import javax.servlet.http.HttpServletRequest; public class LoginAction extends ActionSupport { public String login(){ HttpServletRequest request = ServletActionContext.getRequest(); String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username); System.out.println(password); return NONE; } }
jsp
<%-- Created by IntelliJ IDEA. User: Wait、 Date: 2019/7/30 Time: 11:08 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="${pageContext.request.contextPath}/login.action"> 用户名<input type="text" name="username"><br> 密码<input type="password" name="password"><br> <input type="submit" name="登录"><br> </form> </body> </html>
第二种通过set注入:
struts.xml和第一种相同
action.java
package main.java.action; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.ServletActionContext; import javax.servlet.http.HttpServletRequest; public class LoginAction extends ActionSupport { private String username; private String password; public void setUsername(String username) { System.out.println("setUsername"); this.username = username; } public void setPassword(String password) { System.out.println("setPassword"); this.password = password; } public String login(){ System.out.println(username); System.out.println(password); return NONE; } }
jsp和第一种相同
第三种set模型属性:
struts.xml和第一种相同
action.java
package main.java.action; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.ServletActionContext; import javax.servlet.http.HttpServletRequest; public class LoginAction extends ActionSupport { private User user; public User getUser() { System.out.println("getUser"); return user; } public void setUser(User user) { System.out.println("setUser"); this.user = user; } public String login(){ System.out.println(user); return NONE; } }
User模型
package main.java.action; 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 + '\'' + '}'; } }
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="${pageContext.request.contextPath}/login.action"> 用户名<input type="text" name="user.username"><br> 密码<input type="password" name="user.password"><br> <input type="submit" name="登录"><br> </form> </body> </html>
第四种通过模型驱动,在action里实现一个模型驱动:(最常用)
struts.xml和第一种相同
action.java
实现步骤:1.在action里面实现一个模型驱动接口
2.提供一个模型属性,并且一定要赋值
package main.java.action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import org.apache.struts2.ServletActionContext; import org.omg.CORBA.PRIVATE_MEMBER; import org.omg.PortableInterceptor.ORBIdHelper; import javax.servlet.http.HttpServletRequest; public class LoginAction extends ActionSupport implements ModelDriven<User> { private User user = new User(); public String login(){ System.out.println(user); return NONE; } @Override public User getModel() { return user; } }
User模型和第三种方法相同
jsp和第一种方法相同
用户注册案例:
使用druid数据库技术
druid.properties
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/struts2_day3?characterEncoding=utf-8 #数据库用户名 username=root #数据库密码 password=123456 #初始化连接数 initialSize=5 #最大连接数 maxActive=10 #最大等待时间 maxWait=3000 minIdle=3
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> <!--配置一个常量--> <!--1.配置访问的后缀名--> <!--<constant name="struts.action.extension" value="php"></constant>--> <!--2.配置开发者模式--> <constant name="struts.devMode" value="true"></constant> <!-- 配置动态方法的调用属性为true --> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> <package name="p2" extends="struts-default"> <action name="register" class="main.action.UserAction" method="register"></action> </package> </struts>
domain
package main.domain; import java.util.Date; public class User { private String username; private String password; private Date birthday; private String hobby; private Boolean married; 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } public Boolean getMarried() { return married; } public void setMarried(Boolean married) { this.married = married; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", birthday=" + birthday + ", hobby='" + hobby + '\'' + ", married=" + married + '}'; } }
dao
接口 package main.dao; import main.domain.User; public interface UserDao { public int addUser(User user); }
实现 package main.dao.Impl; import main.dao.UserDao; import main.domain.User; import main.utils.JDBCUtils; import org.springframework.jdbc.core.JdbcTemplate; public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource()); @Override public int addUser(User user) { String sql = "insert into user values(?,?,?,?,?)"; return jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), user.getBirthday(), user.getHobby(), user.getMarried()); } }
service
接口 package main.service; import main.domain.User; public interface UserService { public void register(User user); } 实现 package main.service.Impl; import main.dao.Impl.UserDaoImpl; import main.dao.UserDao; import main.domain.User; import main.service.UserService; public class UserServiceImpl implements UserService { UserDao userDao = new UserDaoImpl(); @Override public void register(User user) { userDao.addUser(user); } }
action
package main.action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import main.domain.User; import main.service.Impl.UserServiceImpl; import main.service.UserService; public class UserAction extends ActionSupport implements ModelDriven<User> { private User user = new User(); @Override public User getModel() { return user; } public String register(){ UserService us = new UserServiceImpl(); us.register(user); System.out.println(user); return NONE; } }
jsp页面
<%-- Created by IntelliJ IDEA. User: Wait、 Date: 2019/8/3 Time: 12:03 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=utf-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="${pageContext.request.contextPath}/user/register.action" method="post"> 用户名<input type="text" name="username"><br> 密码<input type="password" name="password"><br> 生日<input type="text" name="birthday"><br> 爱好<input type="checkbox" name="hobby" value="写代码">写代码 <input type="checkbox" name="hobby" value="泡妞">泡妞 <input type="checkbox" name="hobby" value="买房">买房<br> 是否已婚<input type="radio" name="married" value="true">已婚 <input type="radio" name="married" value="false">未婚 <br> <input type="submit" value="注册"> </form> </body> </html>
自定义日期转换器
User-conversion.properties代码(此文件需要和模型放在一起,且文件名使用固定格式)
birthday=main.web.convert.MyDateConverter
MyDateConverter.java文件
package main.web.convert;
import org.apache.struts2.util.StrutsTypeConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
//需要继承这个类 String[] strings, Class aClass 第一个是表单传过来的数组值 第二个是转换文件的路径
public class MyDateConverter extends StrutsTypeConverter { //把字符串转成对象类型
@Override public Object convertFromString(Map map, String[] strings, Class aClass) { if (strings != null && strings.length > 0){ //取数据 String dateStr = strings[0]; if ("".equals(dateStr)){//空的字符串不转换 return null; } //转换 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); //格式在此定义 try { return sdf.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); throw new RuntimeException(e);//转换异常 } } return null; } //把对象类型转成字符串类型 @Override public String convertToString(Map map, Object o) { return null; } }
全部类型转换器
错误的回显
struts标签的使用(form)
错误处理和中文显示(properties文件和模型写在一起)
<%@ page contentType="text/html;charset=utf-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="S" uri="/struts-tags" %> //使用struts标签需要导入
<html>
<head>
<title>Title</title>
<s:head></s:head>
</head>
<body>
<%--
Struts的Form标签
struts表单特点
1.action不需要写项目名,会自动加
2.会给表单里面的内容放在table中,并加上样式
3.struts的表单项必须要有name属性
--%>
<%--
requiredLabel:代表必填项目
requiredPosition:必填*号位置
showPassword:回显时,密码还在
--%>
<s:form action="/user/register.action">
<s:textfield name="username" label="用户名" requiredLabel="true" requiredPosition="left"></s:textfield>
<s:password name="password" label="密码" showPassword="true"></s:password>
<s:textfield name="birthday" label="生日"></s:textfield>
<%-- list使用的OGNL表达式--%>
<s:checkboxlist list="#{'写代码':'写代码','泡妞':'泡妞','买房':'买房'}" label="爱好" name="hobby"></s:checkboxlist>
<s:radio list="#{'true':'已婚','false':'未婚'}" name="married" label="是否已婚"></s:radio>
<s:submit value="注册"></s:submit>
</s:form>
<hr>
HTML原始标签
<form action="${pageContext.request.contextPath}/user/register.action" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
生日:<input type="text" name="birthday"><br>
爱好:<input type="checkbox" name="hobby" value="写代码">写代码
<input type="checkbox" name="hobby" value="泡妞">泡妞
<input type="checkbox" name="hobby" value="买房">买房<br>
是否已婚<input type="radio" name="married" value="true">已婚
<input type="radio" name="married" value="false">未婚 <br>
<input type="submit" value="注册">
</form>
</body>
</html>
服务端Action验证action
package main.web.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import main.domain.User;
import main.service.Impl.UserServiceImpl;
import main.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.interceptor.validation.SkipValidation;
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
// struts自带的表单字段的验证
// 第一种:重写validate方法,如果数据不对,可以往FieldError添加字段信息错误信息
// 注意:
// 1.表单一定要用struts的标签 s:form/s:textfield
// 2.addFieldError里的key,是表单的name值
// 3.validate对于Action来说是全局的,也就是说action的所有方法都会生效
// 4.在不需要验证的action方法上,可以声明一个注解跳过Validation的执行 @SkipValidation
// @Override
// public void validate() {
// //判断用户名是否为空
// if (StringUtils.isEmpty(user.getUsername())){
// addFieldError("username","用户名不能为空");
// }
//
// //判断密码是否为空
// if (StringUtils.isEmpty(user.getPassword())){
// addFieldError("password","密码不能为空");
// }
//
// }
// 第二种:写一个方法 格式 validate+方法名(第一个字母大写)
// 注意:1.
// 只针对方法有效,它是一个局部的字段校验 下面就是第二种方法
public void validateRegister() {
//判断用户名是否为空
if (StringUtils.isEmpty(user.getUsername())){
addFieldError("username","用户名不能为空");
}
//判断密码是否为空
if (StringUtils.isEmpty(user.getPassword())){
addFieldError("password","密码不能为空");
}
}
//加一个注解跳过Validation的执行 @SkipValidation
public String register(){
System.out.println("register方法");
UserService us = new UserServiceImpl();
// us.register(user);
System.out.println(user);
return NONE;
}
}
xml声明式验证
全局声明方式:
局部声明方式:需要将UserAction的方法写在xml文件名中 UserAction-register-validation.xml
验证器综合案例