其实学习框架,就是为了可以很好的很快的完成我们的需求,而学习struts2只是为了替代之前用的servlet这一层,框架使开发更加简单,所以作为一个小菜鸟,特别感谢那些超级无敌变态开发的框架供我们使用,当然说那些使超级无敌变态并不是说他们很变态,是他们的思想太强大了。
言归正传,这次使用的拦截器是struts2框架的核心之处,希望学习struts2框架的小伙伴重视起来哦。一起共勉。
1:第一步依旧是导包哦,使用别人的框架,第一步,就记住导入自己使用的核心包即可。
2:配置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>struts2_login20170307</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list> <!-- 引入struts2的核心过滤器 -->
<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>
3:第三步,想要登陆就必须设计号数据表,当然你首先要设计好数据库。字段如下所示:
4:设计好数据表之后就可以创建实体类User.java,源码如下所示:
package com.bie.po; import java.io.Serializable; /**
* @author BieHongLi
* @version 创建时间:2017年3月5日 上午9:40:09
*
*/
public class User implements Serializable{ private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String password;
private String email;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", password=" + password + ", email=" + email + ", phone=" + phone
+ "]";
} }
5:完成了实体类,就可以如以前学习的那样,写dao层,service层,当然servlet层被action层替换了。这里先写dao层吧,首先创建工具类BaseDao.java,源码如下所示:
package com.bie.dao; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle; /**
* @author BieHongLi
* @version 创建时间:2017年3月5日 上午9:32:14
* 数据交互层dao层
*/
public class BaseDao { private static String driver="com.mysql.jdbc.Driver";
private static String url="jdbc:mysql:///test";
private static String user="root";
private static String password="123456"; /***
* 连接数据库的方法
* @return
* @throws ClassNotFoundException
* @throws SQLException
*/
public static Connection getCon() throws ClassNotFoundException, SQLException{
Class.forName(driver);//加载数据库驱动
System.out.println("测试加载数据库成功");
Connection con=DriverManager.getConnection(url, user, password);
System.out.println("测试数据库链接成功");
return con;
} /***
* 关闭数据库的方法
* @param con
* @param ps
* @param rs
*/
public static void close(Connection con,PreparedStatement ps,ResultSet rs){
if(rs!=null){//关闭资源,避免出现异常
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} /***
* 同意增删改的方法
* @param sql
* @param arr
* @return
*/
public static boolean addUpdateDelete(String sql,Object[] arr){
Connection con=null;
PreparedStatement ps=null;
try {
con=BaseDao.getCon();//第一步 :连接数据库的操作
ps=con.prepareStatement(sql);//第二步:预编译
//第三步:设置值
if(arr!=null && arr.length!=0){
for(int i=0;i<arr.length;i++){
ps.setObject(i+1, arr[i]);
}
}
int count=ps.executeUpdate();//第四步:执行sql语句
if(count>0){
return true;
}else{
return false;
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
} public static void main(String[] args) {
try {
BaseDao.getCon();
System.out.println("测试数据库链接成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
6:建议再创建一个工具类,过滤编码的UTFFilter.java
package com.bie.dao; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest; /**
* @author BieHongLi
* @version 创建时间:2017年2月21日 上午11:08:49
*
*/
@WebFilter("/*")
public class UTFFilter implements Filter{ @Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain)throws IOException, ServletException {
//将servletRequest转发为HttpServletRequest
HttpServletRequest request=(HttpServletRequest)servletRequest;
request.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest, servletResponse);
} @Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub } }
7:接着写service层的接口和实现类;
package com.bie.dao; import java.util.List; import com.bie.po.User; /**
* @author BieHongLi
* @version 创建时间:2017年3月5日 上午9:39:21
*
*/
public interface UserDao { /***
* 登陆的方法
* @param user
* @return
*/
public User selectLogin(User user); /***
* 用户查询的方法
* @param sql
* @param arr
* @return
*/
public List<User> selectUser(String sql,Object[] arr);
}
package com.bie.dao.impl; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import com.bie.dao.BaseDao;
import com.bie.dao.UserDao;
import com.bie.po.User; /**
* @author BieHongLi
* @version 创建时间:2017年3月5日 上午9:39:35
*
*/
public class UserDaoImpl implements UserDao{ @Override
public User selectLogin(User user) {
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
con=BaseDao.getCon();//1:获取数据库的连接
//2:书写sql语句
String sql="select * from user where name=? and password=? ";
ps=con.prepareStatement(sql);//3:预编译
//4:设置值
ps.setString(1, user.getName());
ps.setString(2, user.getPassword());
rs=ps.executeQuery();//5:执行sql语句
User users;
if(rs.next()){
users=new User();
//从数据库中获取值设置到实体类的setter方法中
users.setId(rs.getInt("id"));
users.setName(rs.getString("name"));
users.setPassword(rs.getString("password"));
users.setEmail(rs.getString("email"));
users.setPhone(rs.getString("phone"));
//user.setIsAdmin(rs.getString("isAdmin")); //return user;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//关闭资源,避免出现异常
BaseDao.close(con, ps, rs);
}
return user;
} @Override
public List<User> selectUser(String sql, Object[] arr) {
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
con=BaseDao.getCon();//第一步连接数据库
ps=con.prepareStatement(sql);//第二步:预编译
if(arr!=null){
for(int i=0;i<arr.length;i++){
ps.setObject(i+1, arr[i]);
}
}
//第四步执行sql
rs=ps.executeQuery();
List<User> list=new ArrayList<User>();
while(rs.next()){
User user=new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setPhone(rs.getString("phone")); //System.out.println(user);//测试数据
list.add(user);
}
return list;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
//关闭资源,避免出现异常
BaseDao.close(con, ps, rs);
} return null;
} }
8:接着写service层的接口和实现类,接口UserService.java和实现类UserServiceImpl.java;
package com.bie.service; import java.util.List; import com.bie.po.User; /**
* @author BieHongLi
* @version 创建时间:2017年2月23日 下午1:58:59
*
*/
public interface UserService { /***
* 用户查询的信息
* @param user
* @return
*/
public List<User> selectUser(User user); /***
* 用户登陆的功能
* @param user
* @return
*/
public User login(User user);
}
package com.bie.service.impl; import java.util.ArrayList;
import java.util.List; import com.bie.dao.UserDao;
import com.bie.dao.impl.UserDaoImpl;
import com.bie.po.User;
import com.bie.service.UserService; /**
* @author BieHongLi
* @version 创建时间:2017年2月23日 下午1:59:36
*
*/
public class UserServiceImpl implements UserService{ private UserDao dao=new UserDaoImpl(); @Override
public List<User> selectUser(User user) {
//sql语句
//String sql="select * from user ";
StringBuilder sql=new StringBuilder("select * from user where 1=1 ");
List<Object> list=new ArrayList<Object>();
if(user!=null){
//按照姓名查询
if(user.getName()!=null && !user.getName().equals("")){
sql.append(" and name = ? ");
list.add(user.getName());
}
//按照email查询
if(user.getEmail()!=null && !user.getEmail().equals("")){
sql.append(" and email = ? ");
list.add(user.getEmail());
} }
return dao.selectUser(sql.toString(), list.toArray());
} @Override
public User login(User user) {
if(user!=null && user.getName()!=null && user.getPassword()!=null){
return dao.selectLogin(user);
}
return null;
} }
9:开始写登陆页面login.jsp页面和用户信息显示list.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="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>登陆的页面</title>
</head>
<body> <form action="${pageContext.request.contextPath }/user_login.action" method="post">
账号:<input type="text" name="user.name"/><br>
密码:<input type="password" name="user.password"/><br/>
<input type="submit" name="登陆"/> </form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>信息列表展示的页面</title>
</head>
<body> <table cellpadding="10" cellspacing="10" align="center">
<tr>
<th>编号</th>
<th>姓名</th>
<th>密码</th>
<th>邮件</th>
<th>电话</th>
</tr> <s:iterator var="user" value="#request.listUser" status="lu">
<tr>
<td>
<s:property value="#lu.count"/>
</td>
<td>
<s:property value="#user.name"/>
</td>
<td>
<s:property value="#user.password"/>
</td>
<td>
<s:property value="#user.email"/>
</td>
<td>
<s:property value="#user.phone"/>
</td>
</tr>
</s:iterator> </table> </body>
</html>
10:登陆页面点击登陆就到了struts.xml页面,struts.xml页面会到action页面,所以现在写struts.xml页面的源码;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"> <struts>
<!-- 配置包 -->
<package name="user" extends="struts-default">
<!-- 拦截器写到最上面 ,拦截器配置-->
<interceptors>
<interceptor name="loginCheck" class="com.bie.interceptor.UserCheckInterceptor"></interceptor>
<interceptor-stack name="myStack">
<!-- 默认的defaultStack -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 【执行拦截器】第一种写法,当前包下所有的action都执行myStack栈,如果只想一个执行,下面是第二种写法 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref> <!-- 全局配置,需要写到上面 -->
<global-results>
<result name="error">error.jsp</result>
</global-results> <action name="user_*" class="com.bie.action.UserAction" method="{1}">
<!--第二种写法,只是在这一个Action中执行myStack栈
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
-->
<!--
第三种写法:执行用户栈(与第二种写法一样,只在当前action中执行自定义栈)
<interceptor-ref name="loginCheck"></interceptor-ref>
--> <!-- 登陆失败跳转到登陆页面 -->
<result name="input">login.jsp</result> <!-- 登陆成功,跳转到显示信息页面,但是需要先过action -->
<result name="loginSuccess" type="redirectAction">user_list</result> <!-- 列表展示 -->
<result name="list">list.jsp</result>
</action>
</package>
</struts>
11:struts.xml页面的action会和UserAction.java的方法进行匹配,所以现在写UserAction.java,然后就可以完成登陆功能;
package com.bie.action; import java.util.List; import com.bie.po.User;
import com.bie.service.UserService;
import com.bie.service.impl.UserServiceImpl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport; /**
* @author BieHongLi
* @version 创建时间:2017年3月7日 上午10:31:34
*
*/
public class UserAction extends ActionSupport{ private static final long serialVersionUID = 1L;
//----------1:封装请求数据------------
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//-----------2:调用service方法------------
private UserService service=new UserServiceImpl(); //-----------3:登陆的action方法----------------------
public String login() throws Exception {
try {
User userInfo=service.login(user);
//判断,如果为空,返回失败input
if(userInfo==null){
//登录失败
return "input";
}
//如果登陆成功,数据保存到session中
ActionContext.getContext().getSession().put("userInfo", "userInfo"); return "loginSuccess";
} catch (Exception e) {
return "ERROR";
}
} //-----------4:列表,处理显示数据的方法-------------
public String list(){
try {
//查询全部
List<User> list=service.selectUser(user);
//保存到request中
ActionContext.getContext().getContextMap().put("listUser", list); return "list";
} catch (Exception e) {
return "ERROR";
}
} }
12:最后就再创建一个包interceptor包,这里面写过滤器,这是过滤器的核心,也是struts2的核心技术,所以需要重点掌握哦;源码如下所示:(注意:UserCheckInterceptor会和struts.xml的过滤器配置进行交互,最后完成拦截器的功能)
package com.bie.interceptor; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; /**
* @author BieHongLi
* @version 创建时间:2017年3月7日 下午1:28:00
* 拦截业务处理方法
*/
public class UserCheckInterceptor extends AbstractInterceptor{ private static final long serialVersionUID = 1L; //步骤:1:首先拿到当前执行的方法名,2:然后进行判断 ,只要当前方法名不是login,就需要进行验证
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//获取ActionContext对象
ActionContext ac=invocation.getInvocationContext();
//获取action对象的代理对象
ActionProxy proxy=invocation.getProxy();
//获取当前执行的方法名
String methodName=proxy.getMethod();
//判断是否登陆
if(!"login".equals(methodName)){
//先获取当前登陆的用户
Object obj=ac.getSession().get("userInfo");
if(obj == null){
//当前用户没有登陆
return "input";
}else{
//当前用户有登陆
return invocation.invoke();
}
}else{
//当前用户正在登陆
return invocation.invoke();
}
} }
演示效果如下所示:
革命尚未成功,拦截器我都学会了,努力!!!
13:Struts2的国际化:
第一,创建配置文件中文msg.properties文件,配置如下:
username=\u8D26\u53F7
password=\u5BC6\u7801
submit=\u63D0\u4EA4
title=\u6807\u9898
第二,创建配置文件英文msg_en_US.properties文件,配置如下所示:
username=UserName
password=Password
submit=OnSubmit
title=Title
然后找到default.properties搜索i18n:找到struts.custom.i18n.resources复制到配置文件上:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- 通过常量加载资源文件,value值当存在多个的时候使用都好隔开 -->
<constant name="struts.custom.i18n.resources" value="com.bie.lesson08.config.msg"></constant> <package name="adminPackage" extends="struts-default"> <!-- 拦截器配置 -->
<interceptors>
<interceptor name="loginCheck" class="com.bie.lesson08.utils.AdminInterceptor"></interceptor>
<interceptor-stack name="myStack">
<!-- 默认的拦截器配置 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
</interceptor-stack>
</interceptors> <!-- 执行拦截器 ,当前包下所有的action都执行mystack栈-->
<default-interceptor-ref name="myStack"></default-interceptor-ref> <!-- 错误放到全局的位置 -->
<global-results>
<result name="error">error.jsp</result>
</global-results> <action name="admin_*" class="com.bie.lesson08.action.AdminAction" method="{1}">
<!-- :第一步,登陆失败跳转的页面,登陆失败跳转到login.jsp -->
<result name="input">login.jsp</result> <!-- 登陆成功跳转的页面,登陆成功跳转到list.jsp,前提是查询出数据再跳转哦 -->
<!-- ,第二步,登陆成功重定向到这个查询数据的页面,之后再进行跳转到显示数据的页面 -->
<result name="success" type="redirectAction">admin_list</result> <!-- ,第三步,当查询出数据,跳转到显示数据的页面 -->
<result name="list">/WEB-INF/list.jsp</result> <!-- 登陆错误跳转的页面,登陆错误跳转的错误的页面,错误放到全局 -->
<!-- <result name="error">error.jsp</result> -->
</action> </package> </struts>
然后去jsp页面开始使用struts2的国际化,使用如<s:text name="title"></s:text>:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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">
<!-- struts的国际化,name是key值 -->
<title><s:text name="title"></s:text></title>
</head>
<body> <form action="${pageContext.request.contextPath }/admin_login.action" method="post">
账号:<input type="text" name="admin.adminName"/><br>
密码:<input type="password" name="admin.adminPassword"/><br/>
<input type="submit" name="登陆"/> </form> </body>
</html>