Struts视频笔记:
Struts是一个开源的web框架,框架提高了程序的规范的同时也约束了程序员的自由
为什么会有struts:
因为我们队mvc理解的不同,可能造成不同公司写程序的时候,规范不统一,这样不利于程序的维护和扩展,所以我们有必要用一个统一的规范来开发项目(struts)
Struts 的好处: 程序更加规范化,开发效率提高了,可读性增加了,程序的可维护性增加了
运行原理:
一个请求从浏览器发送给web服务器,http://localhost:8080/web应用/action,web服务器首先解析主机à然后解析web应用的名称à在解析出资源名à转发给总司令ActionServlet(该类由struts框架提供给我们的无需编写,只需配置)àActionServlet有一个文件struts-config.xml,该文件配置了表单actionForm(军火库),还配置了action,以及他们之间的对应关系,当ActionServlet拿到命令后它会查询struts-config.xml文件去填充数据,把用户的数据填充到表单里边,à下个动作就是去调用指定的action(小队长),action去从表单中读取数据,à调用某个model(士兵,如service)完成任务,à完成任务把结果返回给ActionServlet总司令(返回一个执行的结果),-->总司令又去查询struts-config.xml文件,决定跳转到哪个jsp页面,à返回一个执行结果(形成静态html文件)à直接返回给web服务器à服务器再把静态页面以http响应给浏览器
,登录小项目过程步骤: 新建web工程à导入struts包à编写login.jspà编写actionForm和actionà配置struts-config.xmlà编写ok.jsp和err.jsp à配置web.xml à测试
点击finish,自动创建web.xml和struts-config.xml。
Struts-config.xml中的<action>中的scope指的是actionform的生命周期范围 struts中<action>的scope默认是session
配置过滤器
public class MyFilter extends HttpServlet implements Filter {
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
arg0.setCharacterEncoding("gb2312");
arg1.setCharacterEncoding("gb2312");
arg2.doFilter(arg0, arg1);
}
配置web.xml
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.chao98.services.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上面这次比较浪费资源每次都要去实例化 但是下面这种过滤器不太彻底,往数据库里插入数据时还是会经常出现乱码
public class MyFilter extends HttpServlet implements Filter {
private String encoding;
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
// arg0.setCharacterEncoding("gb2312");
//arg1.setCharacterEncoding("gb2312");
arg0.setCharacterEncoding(encoding);
arg2.doFilter(arg0, arg1);
}
public void init(FilterConfig arg0) throws ServletException {
encoding=arg0.getInitParameter("encoding");
}
然后在web.xml中加入
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
配置struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<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>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
写一个关于安全性的过滤器,用于过滤一些用户注册使用的关键字
private String keywords[];
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
String username=arg0.getParameter("username");
System.out.println("this is safe filter !");
System.out.println(username);
if(username!=null){
for(String key:keywords){
if(key.equals(username)){
arg0.setAttribute("err", username+"被第二个管理安全的过滤器拦截了");
arg0.getRequestDispatcher("/WEB-INF/tishi.jsp").forward(arg0, arg1);
return ;
}
}
}
arg2.doFilter(arg0, arg1);
}
public void init(FilterConfig arg0) throws ServletException {
keywords=arg0.getInitParameter("keywords").split(";");
}
然后在web.xml配置过滤器还有设置要过滤的关键字
<init-param>
<param-name>keywords</param-name>
<param-value>xiaomao;xiaoxiao</param-value>
</init-param>
每个action是单态的,包括actionserver,对网站并发性有影响 若要证明的话在***action.java中声明一个静态变量,每次访问自加
什么是单态: 单态是指在整个运行过程中,始终是一个对象;
struts-config.xml默认放在WEB-INF目录下,也可以放到其他地方,只需要在web.xml中的
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
有多个struts-config.xml只需用","号隔开
java 中插入数据库的语句需要注意标点 st.executeUpdate("insert into user(username,password) values("+"'"+u.getUsername()+"'"+","+"'"+u.getPassword()+"'"+")");
jstl(jsp startand tag liblary) jsp标准标签库: 可以提高开发速度,代码简洁
升级jsp 页面 <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">替换8.5myeclipse:
D:\Program\Files\Myeclipse\Common\plugins\com.genuitec.eclipse.wizards_8.5.0.me201003052220.jar\templates\jsp\jsp.vtl的
6.5myeclipse:D:\ProgramFiles\MyEclipse6.5\myeclipse\eclipse\plugins\com.genuitec.eclipse.wizards_6.5.0.zmyeclipse650200806\templates\jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 这样比较符合现在的开发潮流
各个jstl标签
<c:out>:
<c:out value="hello world"></c:out>
<c:out value="${username}" default="没有值" escapeXml="false" ></c:out>等同于request.getAttribute("user").toString();
escapeXml表示是否安装html样式显示 默认是true:表示以文本显示
如何输出request,session,application, pageContext域对象的数据
<%
request.setAttribute("hello","request你好!");
session.setAttribute("hello","session你好!");
application.setAttribute("hello","application你好");
pageContext.setAttribute("hello","pageContext你们<a href='http://www.baidu.com'>百度</a>");
%>
这里有个优先级的问题,pageContext>request>session>application
<c:out value="${hello}" default="没有值" escapeXml="false" >
如果是在同一个页面,那么这段代码输出pageContext你们好百度
<%
User u=new User();
u.setUsername("admin");
u.setPassword("admin");
request.setAttribute("user",u);
%>
<c:out value="${user.username}"></c:out> | |<c:out value="${user.password}"></c:out>
相当于(User) request.setAttribute("user").getUsername();
<c:set>:
<c:set var="abc" value="中国,北京" scope="request"></c:set>
<c:out value="${abc}"/>
<c:remove var="abc"/> 移除 之后 中国北京将不再显示
<c:catch>:
<c:catch var="err">
<%int i=3/0; %>
</c:catch>
<c:out value="${err.message}"></c:out>
<c:if test="${2<30?true:false}">ok</c:if>
<c:if>:
<%
request.setAttribute("a","hello");
request.setAttribute("age","22"); %>
判断字符串:
<c:if test="${a=='hello'}">
hello
</c:if>
判断数值
<c:if test="${age>12 and age<30 or age==22}">
年龄大于12 小于30 ${age }
</c:if> <%
ArrayList<User> al=new ArrayList<User>();
User u1=new User();
u1.setUsername("陈超");
u1.setPassword("tiger");
User u2=new User();
u2.setUsername("system");
u2.setPassword("manager");
al.add(u1); al.add(u2);
request.setAttribute("alluser",al);
%>
<c:forEach items="${alluser}" var="u">
${u.username}
${u.password} <br/>
</c:forEach>
第一种迭代
<c:forEach var="i" begin="1" end="10">${i} </c:forEach>
<br/>
第二种迭代
<c:forEach var="i" begin="1" end="10" step="3">${i} </c:forEach><br />
用于分隔字符:<c:forTokens items="11;33;44;52;" delims=";" var="temp">${temp}</c:forTokens>
什么时候用$符,什么时候不用$
如果是从某个域对象中取出值,取的是一个变量就要用$ ,取的是一个固定的值就不要$
第一种:Window.open(); 这种方式比较慢
第二种:window.location.href=”/web应用名/goManager?pageNow=”+pageNow
<c:if test="${pageNow>1}">前一页:<a href=”/web应用名/goManager?pageNow=${pageNow-1}”></c:if>
当前页:<c:forEach><a href="/web应用名/gotoManage?pageNow=${i}">[${i }]</a></c:forEach>
<c:if test="${pageNow<pageCount}">后一页:<a href=”/web应用名/goManager?pageNow=${pageNow+1}”>
</c:if>
当前页${pageNow } /总页数 ${pageCount } 跳转到<input type="button" id="pageNow" name="pageNow" value="跳"/>
<%
Map map=new HashMap();
//map.put("aa","admin");
// map.put("bb","scott");
User u1=new User();
u1.setUsername("xiaoming");
u1.setPassword("xiaoming");
User u2=new User();
u2.setUsername("xiaoming");
u2.setPassword("xiaoming");
map.put("u1",u1);
map.put("u2",u2);
request.setAttribute("person",map);
%>
<c:forEach items="${person}" var="per">
key:${per.key }值 name: ${per.value.username }值 password:${per.value.password }<br/>
</c:forEach>
<%
Set set=new HashSet();
User u3=new User();
u3.setUsername("scott");
u3.setPassword("tiger");
set.add(u3);
request.setAttribute("setuser" ,set);
%>
<c:forEach items="${setuser}" var="myusers">
值 name: ${myusers.username }值 password:${myusers.password }<br/>
<c:if test="${!empty setuser}">有人</c:if></c:forEach>
重定向:<c:redirect url="http://www.hao123.cn"/>
import标签:
<c:import url="a.jsp">
<c:param name="name" value="admin"/>
</c:import>
Strtus标签:
<html:base ref="http://www.baidu.com"/><a href="#">goto</a>
如果没有给超链接设置则默认跳到百度(如上)
<html:image src="images/chadu.png"></html:image>这是一个图片按钮
<html:img src="images/chadu.png"/>这是真真正正的一i张图片
bean标签: 用于输出信息
<%
User u1=new User();
u1.setUsername("admin");
u1.setPassword("admin");
request.setAttribute("user",u1);
%>
<bean:write name="user" property="username"></bean:write>
另外还有两种创建bean的方法,但是用的不多
<bean:define id=""/></bean:define>
<jsp:useBean id="u2" class="com.chao98.forms.User"></jsp:useBean>
<jsp:setProperty name="u2" property="username" value="chenchao"/>
Logic 标签:
logic标签使用
<%
User u1=new User();
u1.setUsername("admin");
u1.setPassword("aa");
User u2=new User();
u2.setUsername("tiger");
u2.setPassword("ac");
User u3=new User();
u3.setUsername("scott");
u3.setPassword("ab");
ArrayList<User> al=new ArrayList<User>();
al.add(u1);
al.add(u2);
al.add(u3);
request.setAttribute("users",al);
%>
<logic:iterate id="user" name="users">
<bean:write name="user" property="username"/>
<bean:write name="user" property="password"/><br/>
</logic:iterate>
<logic:empty name="ee">
属性不存在
</logic:empty>
<logic:notEmpty name="users">
users属性存在
</logic:notEmpty>
<logic:iterate id="myusers" name="users">
<logic:greaterThan value="20" property="age" name="myusers">
年龄大于二十
</logic:greaterThan>
</logic:iterate>
标签的选择: 通常会选择el表达式$
op Struts 第23讲: 开发struts 的用户管理系统
Create table users (
Id int primary key,
Name varchar(20) not null,
Pwd varchar(30) not null,
Email varchar(30) not null,
Tel varchar(30) not null,
Grade int default 1 not null
)
如果中文不能加入的话 show variables like ‘%char%’;
Set character_set_client=gbk
注销退出登录
request.getSession().invalidate(); //会把所有的session都删除
return mapping.findForward("logout");
动态表单(dynimic form): 当我们表单个数和类型不确定的情况下,我们就可以使用动动态表单来解决
动态表单和普通表单的区别:
1普通表单actionForm 是首先你需要定义这样一个类,然后配置到struts-config中,
2,动态表单完全依赖反射机制创建,所以不要去定义表单类,直接在struts-config.xml中配置即可
<form-bean name=”userForm”
type=”org.apache.struts.action.DynaActionForm”>
<form-property name=”username” type=”java.lang.String/>
</form-bean>
文件的上传与下载
读取文件(inputStream) 写文件(outputStream);
案例项目:
1:
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/register.do" method="post">
name:<input type="text" name="username"/><br/>
photo:<input type="file" name="myphoto"/><br/>
<input type="submit" value="regist" />
</form>
2:
public class UserForm extends ActionForm {
private String username;
private FormFile myphoto;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public FormFile getMyphoto() {
return myphoto;
}
public void setMyphoto(FormFile myphoto) {
this.myphoto = myphoto;
}
3:
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
UserForm userForm=(UserForm)form;
String username=userForm.getUsername();//取出用户名字
FormFile formFile=userForm.getMyphoto();
// 通过FormFile 我们可以获取关于上次文件的各种信息
String fileName=formFile.getFileName();
int fileSize=formFile.getFileSize();
System.out.println("文件名称:"+fileName);
System.out.println("文件大小:"+fileSize);
InputStream is=null;
OutputStream os=null;
try {//取出输入流
is=formFile.getInputStream();
//得到输出流--文件
// 1 得到file文件夹上传到tomcat服务器后的绝对路径
String keepFilePath=this.getServlet().getServletContext().getRealPath("file");
System.out.println(keepFilePath);//打印路径
os=new FileOutputStream(keepFilePath+"\\"+fileName);//读取文件并写出到服务器file
int len=0;//缓存
byte []bytes=new byte[1024];
//循环处理
while((len=is.read(bytes))>0){
os.write(bytes,0,len);//读一点写一点
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
4: 在webroot下建立一个file文件夹
完善struts文件上传(上面这种如果上传文件名相同的文件的话就会被覆盖
首先了解uuid 的简单使用方法:
String uuids=(java.util.UUID.randomUUID()).toString();
面试题subString(int beginindex,int endindex);是如何截取的 : 获取字符串的一个子串,从beginindex包扩beginindex 取到endindex ,但是不包括endindex 如
String subString="helloworld!";
System.out.println(subString.substring(0,5));
//打出hello beginindex是从0开始的
优化后的代码为
public class RegisterAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
UserForm userForm=(UserForm)form;
String username=userForm.getUsername();//取出用户名字
FormFile formFile=userForm.getMyphoto();
// 通过FormFile 我们可以获取关于上次文件的各种信息
String fileName=formFile.getFileName();
String newFileName="";
int beginIndex=fileName.lastIndexOf(".");
String uuid=(java.util.UUID.randomUUID()).toString();
newFileName=uuid+fileName.substring(beginIndex, fileName.length());
int fileSize=formFile.getFileSize();
System.out.println("uuid:"+uuid);
System.out.println("文件名称:"+fileName);
System.out.println("新文件名称:"+newFileName);
System.out.println("文件大小:"+fileSize);
InputStream is=null;
OutputStream os=null;
try {//取出输入流
is=formFile.getInputStream();
//得到输出流--文件
// 1 得到file文件夹上传到tomcat服务器后的绝对路径
String keepFilePath=this.getServlet().getServletContext().getRealPath("file");
System.out.println(keepFilePath);//打印路径
os=new FileOutputStream(keepFilePath+"\\"+newFileName);//读取文件并写出到服务器file
int len=0;//缓存
byte []bytes=new byte[1024];
//循环处理
while((len=is.read(bytes))>0){
os.write(bytes,0,len);//读一点写一点
return mapping.findForward("loginok");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return mapping.findForward("loginerr");
}
}
注意事项:如果文件名是中文怎么办?
做一个过滤器
arg0.setCharacterEncoding("UTF-8");
arg1.setCharacterEncoding("UTF-8");
arg2.doFilter(arg0, arg1);
案例: 保存到数据库中
Create database userdb2;
Use userdb2;
Create table t_users
(username varchar(30) unique not null,
myphoto varchar(128) not null,##保存新的文件名
myphoto2 varchar(128) not null ##保存旧的文件名
);
Q:1272307737
文件下载
如果下载的文件时中文名那么我们需要在action中对其进行处理
String filterFilkename=java.net.URLEncoder.encode(u.getMyphoto(),"GB2312");
思考: 如何控制文件的大小?
如何控制文件上传类型?
可以从D:\Program Files\Tomcat 6.0\conf目录下的 web.xml中可以查看文件的类型
如何防止用户名重复?