(溫故知新) Struts2 簡易練習(查找資料) normal
原始碼下載:http://goo.gl/k8WCf9
【開發環境】
Tomcat 7
MySQL
【開發工具】
Intellij IDEA 14
【使用FrameWork】
Struts2
jQuery
【主要畫面】
需求:
1. 按“查詢”秀出結果在下方
2. 需要使用annotation
3. JSP需要使用struts2 tag ex: <s:property value="#myUser.name"/>
4. 查詢時需要檢查在session中是否存在屬性為LOGIN的字串,若是沒有則丟出
錯誤訊息(請使用com.opensymphony.xwork2.interceptor.Interceptor方式實作)
* 請在Struts.xml中Action設定上使用Wildcard Method Selection
【使用到的 MySQL 資料】
-- MySQL 語法
CREATE TABLE IF NOT EXISTS `USER_PROFILE` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`USER_ID` varchar(11) NOT NULL,
`USER_NAME` varchar(10) NOT NULL,
`USER_SEX` varchar(10) NOT NULL,
`USER_PHONE` varchar(10) NOT NULL,
`USER_ADDRESS` varchar(10) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
--INSERT INTO `USER_PROFILE` (`USER_ID`, `USER_NAME`, `USER_SEX`,`USER_PHONE`,`USER_ADDRESS`) VALUES
('2013000001', '張三', 'M','0911120111','台北市士林區'),
('2013000002', '李四', 'M','0911120112','新北市土城區'),
('2013000003', '王五', 'M','0911120113','新北市三重區'),
('2013000004', '陳二', 'F','0911120114','台北市信義區'),
('2013000005', '孫九', 'F','0911120115','台北市中山區');
SELECT * FROM `user_profile`;
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>STRUTS2_normal_1</display-name>
<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>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Index.jsp
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script>
$(function(){
$("#ck_male").click(function(){
$("#ck_female").prop("checked",false);
}) ;
$("#ck_female").click(function(){
$("#ck_male").prop("checked",false);
}) ;
});
</script>
</head>
<body>
<h2>Struts2_normal_1</h2>
<!-- 加入警告訊息 -->
<div style="color: red;"><s:actionerror /></div>
<s:form action="queryMethods">
<s:textfield name="user_profile.userName" label="使用者姓名"/>
<s:textfield name="user_profile.userPhone" label="使用者電話"/>
<s:checkbox id="ck_male" name="user_profile.male" label="男"/>
<s:checkbox id="ck_female" name="user_profile.female" label="女"/>
<s:submit value="查詢" />
</s:form>
<br>
<s:if test="null!=list&&!list.isEmpty()">
<hr>
<s:iterator value="list">
<table class="table1">
<tr>
<td>編號</td>
<td>姓名</td>
<td>性別</td>
<td>電話</td>
<td>地址</td>
</tr>
<tr>
<td><s:property value="userId" /></td>
<td><s:property value="userName" /></td>
<td><s:property value="userSex" /></td>
<td><s:property value="userPhone" /></td>
<td><s:property value="userAddress" /></td>
</tr>
</table>
</s:iterator>
</s:if>
<s:else>
<hr>
查無資料
</s:else>
<hr>
<a href="Login">登入</a>
<a href="Logout">登出</a>
</body>
</html>
上面的部分簡單的使用 jQuery 建立 checkbox 檢核機制,當選男的,就會消除女的,反之亦然,另外在整張form 的部份,使用的 struts2 的 s tag,並建立對應的 model 與頁面使用,最後設計兩個連結並導向 Login / Logout 兩個 action,用以模擬登入登出的狀態,在action,將檢核資訊帶入 Session 中。
Model 部分:
USER_PROFILE.java 對應到資料庫的 Table,當中擺入兩個boolean屬性male/female,用以判斷使用者所選的是男性或女性。
package test.Models;
/**
* Created by Hsu on 2015/4/16.
*/
public class USER_PROFILE {
private int id;
private String userId;
private String userName;
private String userSex;
private String userPhone;
private String userAddress;
private boolean male;
private boolean female;
public boolean isMale() {
return male;
}
public void setMale(boolean male) {
if(male){
this.userSex = "M";
}
this.male = male;
}
public boolean isFemale() {
return female;
}
public void setFemale(boolean female) {
if(female){
this.userSex = "F";
}
this.female = female;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
}
與資料庫連線的部份 使用 BasicDataSource 來取代傳統的 JDBC 連線:
package test.utils;
import org.apache.commons.dbcp.BasicDataSource;
import javax.sql.DataSource;
/**
* Created by Hsu on 2015/4/16.
*/
public class DataSourceHolder {
private BasicDataSource ds = new BasicDataSource();
private DataSourceHolder(){
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=big5");
ds.setUsername("test");
ds.setPassword("test");
}
private static class SingletonHolder{
private static DataSourceHolder instance = new DataSourceHolder();
}
public static DataSourceHolder getInstance(){
return SingletonHolder.instance;
}
public DataSource getDataSources(){
return ds;
}
}
要取得 Connection 實體 只要使用
DataSourceHolder.getInstance().getDataSources().getConnection();
即可獲得
接著建立 Dao 的部份
package test.Dao;
import org.apache.log4j.Logger;
import test.Models.USER_PROFILE;
import test.utils.DataSourceHolder;
import test.utils.StringUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Hsu on 2015/4/16.
*/
public class UserProfileDao {
Logger logger = Logger.getLogger(this.getClass());
public List<USER_PROFILE> queryByCondition(USER_PROFILE user_profile){
List<USER_PROFILE> list = new ArrayList<USER_PROFILE>();
Connection conn = null;
try{
conn = DataSourceHolder.getInstance().getDataSources().getConnection();
final String sql = "select * from user_profile where 1=1 " +
this.generateWhere(user_profile) + " order by user_id ";
PreparedStatement ps = conn.prepareStatement(sql);
this.preparePS(user_profile, ps);
ResultSet rs = ps.executeQuery();
while (rs.next()){
USER_PROFILE resultUserProfile = this.rs2Model(rs);
list.add(resultUserProfile);
}
rs.close();
ps.close();
}catch (SQLException sex){
logger.error(sex.getMessage(),sex);
sex.printStackTrace();
}catch (Exception ex){
logger.error(ex.getMessage(),ex);
ex.printStackTrace();
}finally {
try{
conn.close();
}catch (SQLException sex){
logger.error(sex.getMessage(),sex);
sex.printStackTrace();
}
}
return list;
}
private String generateWhere(USER_PROFILE user_profile){
StringBuffer sb = new StringBuffer();
// 姓名查詢
if(!"".equals(StringUtil.NulltoString(user_profile.getUserName()))){
sb.append(" and user_name like ? ");
}
// 電話查詢
if(!"".equals(StringUtil.NulltoString(user_profile.getUserPhone()))){
sb.append(" and user_phone = ? ");
}
// 性別查詢
if(!"".equals(StringUtil.NulltoString(user_profile.getUserSex()))){
sb.append(" and user_sex = ? ");
}
return (sb.length()>0?sb.toString():"");
}
private void preparePS(USER_PROFILE user_profile, PreparedStatement ps) throws SQLException{
int count = 1;
if(!"".equals(StringUtil.NulltoString(user_profile.getUserName()))){
ps.setString(count++, "%" + user_profile.getUserName() + "%");
}
if(!"".equals(StringUtil.NulltoString(user_profile.getUserPhone()))){
ps.setString(count++, user_profile.getUserPhone());
}
if(!"".equals(StringUtil.NulltoString(user_profile.getUserSex()))){
ps.setString(count++, user_profile.getUserSex());
}
}
private USER_PROFILE rs2Model(ResultSet rs) throws Exception{
USER_PROFILE user_profile = new USER_PROFILE();
user_profile.setId(rs.getInt("id"));
user_profile.setUserId(rs.getString("user_Id"));
user_profile.setUserName(rs.getString("user_name"));
user_profile.setUserPhone(rs.getString("user_phone"));
user_profile.setUserSex(rs.getString("user_sex"));
user_profile.setUserAddress(rs.getString("user_address"));
return user_profile;
}
}
裡面只單純提供了資料查找的功能,若有需要其他如 新增、移除、修改的部份,可另行加入對應的method。
Struts.xml 配置檔部分:
下面我們配置了 authorizationInterceptor 這個 Interceptor,好用來做驗證登入登出的訊息。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.locale" value="zh_TW" />
<!-- 定義系統預設編碼集 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 允許使用OGNL -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<!-- 允許 使用 DynamicMethodInvocation -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<!-- 使用struts2 ui -->
<!-- <constant name="struts.ui.theme" value="simple" /> -->
<constant name="struts.ui.theme" value="xhtml" />
<package name="crud" extends="struts-default">
<interceptors>
<interceptor name="authorizationInterceptor" class="test.Interceptors.AuthorizationInterceptor" />
<interceptor-stack name="myStack">
<interceptor-ref name="authorizationInterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<!-- <default-interceptor-ref name="myStack" /> -->
<global-results>
<result name="toList">/index.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
<action name="*Methods" method="{1}"
class="test.Actions.MainAction">
<interceptor-ref name="myStack" />
<result name="success">/index.jsp</result>
</action>
<action name="Login" class="test.Actions.Login">
<result name="success">/index.jsp</result>
</action>
<action name="Logout" class="test.Actions.Logout">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
而接著是最重要的 Action 部分:
package test.Actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.SessionAware;
import test.Dao.UserProfileDao;
import test.Models.USER_PROFILE;
import java.util.List;
import java.util.Map;
/**
* Created by Hsu on 2015/4/16.
*/
public class MainAction extends ActionSupport implements SessionAware {
private static final long serialVersionUID = -1651659160635719619L;
private List<USER_PROFILE> list;
private USER_PROFILE user_profile;
private Map<String, Object> session;
public String query() throws Exception{
System.out.println("query Method");
UserProfileDao dao = new UserProfileDao();
list = dao.queryByCondition(user_profile);
//session.clear();
return "toList";
}
public List<USER_PROFILE> getList() {
return list;
}
public void setList(List<USER_PROFILE> list) {
this.list = list;
}
public USER_PROFILE getUser_profile() {
return user_profile;
}
public void setUser_profile(USER_PROFILE user_profile) {
this.user_profile = user_profile;
}
@Override
public void setSession(Map<String, Object> session) {
System.out.println("Get Session OK...");
this.session = session;
}
@Override
public String execute() throws Exception {
System.out.println("execute Method");
return SUCCESS;
}
}
裡面最主要的 Method 就是 query(),也就是我們在 Struts.xml 中所配置的 Action其對應的方法。
private List<USER_PROFILE> list;
private USER_PROFILE user_profile;
上面所列的兩個屬性,則是用於對照到 index.jsp 所用到的資料,如:
<s:if test="null!=list&&!list.isEmpty()">
<hr>
<s:iterator value="list">
及
<s:textfield name="user_profile.userName" label="使用者姓名"/>
上面的原始碼中,我 implements SessionAware 這個類別,主要就是要用來取得 Session 的資料。
因為依照題意,我們需要取得Session 的相關資訊,且要在 interceptor 中做判斷,底下就是interceptor 的實作。
package test.Interceptors;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import java.util.Map;
/**
* Created by Hsu on 2015/4/21.
* Ref: http://www.mkyong.com/struts2/struts-2-creating-own-interceptor/
*/
public class AuthorizationInterceptor extends AbstractInterceptor
{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("intercept enter");
Map session = invocation.getInvocationContext().getSession();
String userParam = (String)session.get("USER");
if(null != userParam){
System.out.println("userParam:" + userParam);
if(!"LOGIN".equals(userParam)){
System.out.println("return Action.ERROR");
return Action.ERROR;
}
System.out.println("invocation.invoke()");
return invocation.invoke();
}else{
System.out.println("userParam:" + userParam);
System.out.println("return Action.ERROR");
return Action.ERROR;
}
}
}
上面其中的
Map session = invocation.getInvocationContext().getSession();
就是用來取得 Session 的資料用,下面接著就是判斷,若含有 LOGIN 的字串Action 就繼續進行,若無則導致錯誤頁面。
而因為我們要虛擬登入/登出動作,故多增加了 Login及Logout 兩個 action
package test.Actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;
/**
* Created by Hsu on 2015/4/21.
*/
public class Login extends ActionSupport implements SessionAware {
Map<String, Object> session;
@Override
public String execute() throws Exception {
// 虛擬登入
System.out.println("User Login!!!!");
session.put("USER","LOGIN");
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
package test.Actions;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;
/**
* Created by Hsu on 2015/4/21.
*/
public class Logout extends ActionSupport implements SessionAware {
Map<String, Object> session;
@Override
public String execute() throws Exception {
// 虛擬登出
System.out.println("Session Clear!!!!");
session.clear();
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
上面兩個action,主要是將資料放進 session跟清除 session 中的資料用,當然也可以整合在MainAction 中,用method的方式去實作。
【程式執行畫面】
未點選登入時直接點選查詢
沒有留言 :
張貼留言