【Struts】- Struts1.3 工作流程
阿新 • • 發佈:2019-03-04
MVC: 模型檢視控制器設計模式
- M:Model 模型:主要作用域業務邏輯的實際處理
- V:View 檢視:主要用於資料的展示
- C:Controller 控制器:主要作為檢視和模型之間的邏輯控制,充當排程者的角色,不負責具體的業務邏輯處理
常見的MVC框架:struts 、springmvc
struts1.3配置檔案
Web容器配置struts1.3:只需要宣告struts1.3的攔截ActionServlet,如果struts-config.xml檔案未放在預設的位置,則需要手動配置檔案路徑
struts1.3工作流程:客戶端訪問Web伺服器,ActionServlet攔截所有的web請求並將請i去引數封裝進表單,作為呼叫內部的execute方法的形式引數,execute方法內部呼叫model處理頁面資料,然後通過struts-config.xml檔案檢視結果和跳轉路徑,直接頁面跳轉
基礎案例:頁面登陸驗證
struts總控配置檔案:struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <!-- 配置表單: form-beans 可以存放多個表單 name:表示表單名字(建議小寫) type:用於指明表單類的全路徑(無java字尾) --> <form-beans> <form-bean name="username" type="com.zhiwei.form.UserForm"></form-bean> </form-beans> <!-- 配置處理對應表單的Action name:和對應的表單要一致相關聯 type:表示該action的全路徑(包名+類名) path:表示訪問Action的資源名: http://localhost:8080/Web工程名稱/path scope:表示表單例項的訪問範圍在request裡面,也可以表示生命週期和request一個級別, 將表單例項放置request作用域裡面:預設session forward:配置跳轉關係:Action完成表單處理會給ActionServlet反饋一個結果及跳轉介面 --> <action-mappings> <action path="/login" name="username" scope="request" type="com.zhiwei.action.LoginAction"> <forward name="success" path="/WEB-INF/success.jsp"></forward> <forward name="error" path="/WEB-INF/error.jsp"></forward> </action> </action-mappings> </struts-config>
web容器配置:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置Struts1.3的攔截Servlet,Struts2攔截Servlet發生改變
ActionServlet:預設配置檔案位置,如果一致省略不寫
protected String config = "/WEB-INF/struts-config.xml";
-->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<!-- <init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 統一專案的編碼形式 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.zhiwei.filter.EncodingFilter</filter-class>
<init-param>
<param-name>pageCoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
</web-app>
表單:UserForm
package com.zhiwei.form;
//建立表單,供actionservlet使用
import org.apache.struts.action.ActionForm;
@SuppressWarnings("serial")
public class UserForm extends ActionForm {
private String username;
private String passwd;
//注意這裡的get和set方法中的方法名必須與JSP裡面的空間名相同,不然在執行過程中ActionAervlet會無法檢測(反射機制)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
控制器Controller:LoginAction
package com.zhiwei.action;
/**struts使用中文時會出現亂碼(過濾器),原因是在呼叫action時ActionServlet已經將資料儲存在表單中
Action ActionServlet都是單態的(在整個程式執行過程中始終保持是同一個物件服務),
任何傳送給actionservlet的請求在伺服器不關閉的情況下總是使用同一個action例項對業務邏輯進行處理
*/
import javax.servlet.http.HttpServletRequest;
import com.zhiwei.model.*;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.zhiwei.form.UserForm;
/**
* Action:主要處理頁面傳遞過來的引數,並封裝進表單,統一呼叫其他的功能類控制業務邏輯處理,
* 並更具處理的結果,對頁面進行相應的跳轉,Action需要在struts-config中進行action-form,result--forword配置
* execute:Action預設的執行方法,類似Servlet的service方法
* @author Yang Zhiwei
*/
public class LoginAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)
throws Exception {
UserForm uf=(UserForm)form; //轉換頁面請求表單引數
if(UserBeanBO.checkUser(uf)){
request.setAttribute("username", uf.getUsername());
/**
* 原始碼分析:預設轉發,而不是重定向
* public ActionForward(String path) {
this(path, false);
}
*/
return mapping.findForward("success"); //配置結果跳轉
}else{
request.setAttribute("Message", "輸入密碼不正確......");
return mapping.findForward("error");
}
}
}
Model層:
package com.zhiwei.model;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.zhiwei.form.UserForm;
public class UserBeanBO {
//定義資料庫基本引數
private static Connection ct=null;
private static PreparedStatement ps=null;
private static ResultSet rs=null;
private static int count=0;
private static int defaultSize=50;
//類似快取作用,緩解資料庫頻繁的IO操作(實際對於使用者個人私密資訊都會通過MD5等手段加密的)
private static List<Map<String,String>> userInfos=new ArrayList<Map<String,String>>(defaultSize);;
/**
* 核實使用者名稱和密碼
* 注意:預防SQL注入漏洞
* @param userName
* @param userPasswd
* @return
*/
public static boolean checkUser(UserForm uf){
System.out.println(Thread.currentThread().getName()+"--->開始時間:"+System.currentTimeMillis());
String userName=uf.getUsername();
String password=uf.getPasswd();
//快取預處理
if(userInfos.size()>0){
for(Map<String,String> user:userInfos){
if(user.containsKey(userName) && user.get(userName).equals(password)){
System.err.println(Thread.currentThread().getName()+"-->結束時間:"+System.currentTimeMillis());
return true;
}
}
}
boolean mark=false;
try{
ct=getDBLink();
ps=ct.prepareStatement("select *from student where stuname='"+userName+"' limit 1;");
rs=ps.executeQuery();
if(rs.next()){
String passwd=rs.getString(3);
if(passwd.equals(uf.getPasswd())){
//快取重新整理次數:實際操作更復雜不會全部清除,通過某種快取策略處理
if(userInfos.size()>=defaultSize){
userInfos.clear();
System.out.println("快取全部重新整理次數:"+count++);
}
Map<String,String> user=new HashMap<String,String>();
user.put(uf.getUsername(),password);
userInfos.add(user);
mark=true;
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
Close();
}
System.out.println(Thread.currentThread().getName()+"-->結束時間:"+System.currentTimeMillis());
return mark;
}
/**
* 關閉資料庫資源
*/
public static void Close(){
try {
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
if(ct!=null){
ct.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取資料庫連線:保證多執行緒的安全,使用同步鎖或者執行緒池
* @return
*/
public static synchronized Connection getDBLink(){
try{
Class.forName("com.mysql.jdbc.Driver"); //JVM載入JDBC記憶體
ct=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","squirrel","xiaoyang"); //獲取DB連線
}catch(Exception e){
e.printStackTrace();
}
return ct;
}
}
View層: login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<!--
Struts開發步驟:
1:新建web專案並引入struts開發包
2:新建jsp介面和ActionForm和Action類
3:新建struts-config配置檔案並進行ActionForms和Action配置
4:配置web.xml:引入ActionServlet
-->
<body style="text-align: center;">
<!-- 將請求交給對應的Action處理 :在struts-config中對映成path路徑:即login代表loginAction.java-->
<form action="${pageContext.request.contextPath}/login.do" method="post">
u:<input type="text" name="username"/><br>
p:<input type="password" name="passwd"/><br>
<input type="submit" value="submit"/>
</form>
</body>
</html>
success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<!-- EL表示式:param.username:request.getAttribute("username"); -->
Welcome <font color="red">${param.username }</font> logining this page!<br>
<a href="${pageContext.request.contextPath }">重新登陸</a>
</body>
</html>
error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<font color="red">${Message }</font><br>
Fail to this page!<br>
<a href="${pageContext.request.contextPath }">重新登陸</a>
</body>
</html>
測試SQL:
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`StuName` varchar(100) NOT NULL,
`StuPasswd` varchar(100) NOT NULL,
`StuScore` int(11) DEFAULT NULL,
`StuSex` char(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
insert into student values(1,'squirrel','xiaoyang',100,'M');
insert into student values(2,'zhangsan','zhangsan',85,'F');
insert into student values(3,'lisi','lisi',95,'M');
insert into student values(4,'wangwu','wangwu',75,'F');
insert into student values(5,'maliu','maliu',68,'M');
insert into student values(6,'tianqi','tianqi',80,'F');
insert into student values(7,'wangba','wangba',83,'M');
Jmeter效能測試結果(200併發)
注意: 資料庫連線的IO操作比較消耗資源,為了安全起見最好使用執行緒同步控制,如果想進一步提高效能需要適應執行緒池管理,後臺mysql資料庫開啟快取等優化措施
補充:
-
struts1.3和struts2很多東西都是不一樣的,但是本質的思想一致,struts1.3概念比較少,入門比較簡單
-
ActionServlet可使用DispatchAction可實現一個servlet擁有多個服務方法,ActionServlet預設方法