2019.6.22开始入门
就在这里写笔记吧~
一、SSH三大框架
Struts
spring
Hibernate
我们从Struts开始
https://www.bilibili.com/video/av14543156/?p=42
我是跟着这个老师学的。老师讲的很好
1)Struts
一、概念
Structs负责WEB层: ActionFormBean接收网页中表单提交的数据,通过Action进行处理,从Forward到对应在网页
Struts1目前已经很少再用,个人感觉springMVC在易用性上要优于Struts2.Struts2和springMVC在性能方面是不分伯仲。
这里我选择学习struts2,于是b站找了个视频看
1)JSP+Servlet
这个方法不好的地方就是功能越多创建的servlet越多
2)Struts流程
二、实例入门
打开myeclipse建一个Dynamic web project
-> module version选定为2.5
->导入jar包
->src中new一个package再new一个action
HelloActiond代码
package cn.tony.action;
public class HelloAction {
/*
* Servlet
* 1、每次访问Servlet时候,都会执行service方法
* 2、写类继承HttpServlet,重写类里面的方法,在web.xml中配置访问路径
*
* Action
* 1、访问action时,默认执行执行名称execute方法
* 2、创建Structs核心配置文件
*/
public String execute(){
return "ok";
}
}
->配置action访问路径
(1)创建一个struts2核心配置文件(名称位置是固定的)
位置:src下面
名称:struts.xml
(2)引入dtd约束
在strut.xml中加入这段代码
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
action配置代码
<struct>
<package name="hellodemo" extends="structs-defauly" namespace="/">
<!-- name:访问名称 -->
<action name="hello" class="cn.tony.action.HelloAction">
<!-- 配置方法的返回值到页面 -->
<result name="ok">/hello.jsp</result>
</action>
</package>
</struct>
此时去访问会报404的错误,说明还是不能访问到的。为什么呢?缺少了上文流程图中的过滤器还没有配置
->配置struts2过滤器(这步容易忘)
将以下代码添加到web.xml内
<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>
然后我们启动tomcat并在浏览器里面输入:http://localhost:8080/struts2_day01/hello
就可以成功跳转啦
效果图:
反射:得到类的字节码文件从而得到里面所有内容
蓝色箭头所指是实现反射的代码
执行过程流程图:
为了更好的理解,我们来做下面这一步
查看源代码 //了解即可
从过滤器的类开始org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
按住Ctrl点击这个类即可打开源代码
- 过滤器在服务器服务器启动时创建,创建时执行里面的init方法,在init方法中加载配置文件(自己创建的和strut2自带的)struts.xml和web.xml需注意
Struts2配置
1、名称位置固定
2、配置文件中主要有三个标签package、action、result。
- Package标签
1、类似于代码包,区别不同的action,要配置action,必须要先写package标签,在package标签里面才能配置action。
2、package标签里面属性
1)name属性
-name属性值和功能本身没有关系
-在一个配置文件中可以写多个package标签,但是name属性值不能相同。
-用于区别不同的package。
2)extends="struts-default"
-属性值是固定的struts-default
-只有写了这个之后,里面的类才能具有action的功能(类似于servlet里面一个普通的类继承httpservlet’之后它才是一个servlet,它才具备servlet的功能)
3)namespace属性
-namespaces属性值要和action的name属性值构成访问路径
<package name="hellodemo" extends="struts-default" namespace="/">
<!-- name:访问名称 -->
<action name="hello" class="cn.tony.action.HelloAction">
这里的“/”和“hello”就构成了访问路径“/hello”(这里有两点。一是namespace="/"可以省略,默认就是“/”。二是在浏览器里面输入的action的name的时候最好加上“.action”,为的是一些非主流浏览器可以识别出来)
-
Action标签
1、action标签作用:配置action访问路径
2、action标签属性
1)name属性
-namespaces属性值要和action的name属性值构成访问路径
-在一个package标签里面写多个action标签,但是action标签的name属性值是不能重复的。
2)class属性
-action全路径:包名加上类名
3)method属性
-比如说在action里面默认执行的方法是execute方法,但是在action里面可以写其他方法。所以这里通过method属性进行配置实现其他方法的执行。 -
Result标签
-根据你action的方法返回值,配置到不同的路径(不一定是别的页面)里面
-result标签属性
1)name属性
-和方法返回值一样
<!-- 配置方法的返回值到页面 -->
<result name="ok">/index.jsp</result>
2)type属性
-配置如何到路径中(请求转发或重定向)
-type属性默认值做请求转发操作(地址栏不变,页面内容改变)
Strut2常量配置
1、常用方式*
-在struts.xml中进行配置
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
2、不常用方式(了解)
-src下面创建struts.properties,进行修改
-在web.xml内配置
常用常量:
1、struts.i18n.encoding=UTF-8
1)表单提交数据到action里面,在action可以获取表单提交数据
2)表单提交数据到中文,有乱码问题,解决
-Post提交直接设置编码
-get提交做编码转换
3)如果在action获取表单通过post方式提交中文,中文乱码问题帮解决了,不需要自己处理问题
分模块开发
1、单独写配置文件,把配置文件引入核心配置文件中
在struts.xml中写入
<!-- 引入hello.xml -->
<include file="cn/tony/action/hello.xml"></include>
action的编写方式
方式一:创建普通类,这个类不继承任何类,不实现任何接口
public class HelloAction {
方式二:创建类,实现接口action
/* 实现接口
* @author TonyWang
*/
public class UserAction implements Action{
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return null;
}
}
方式三:创建类,继承ActionSupport(一般使用)
/*
* 继承类
* @author TonyWang
*/
public class PersonAction extends ActionSupport{
}
class ActionSupport implements Action
访问action的方法(重点)
1、有三种方式实现
第一种:使用action标签中的method属性,在这个属性里面写执行的action方法
第二种:使用通配符的方式实现
在的name属性使用*代表任意字符,method中的{1}代表name属性中的出现的第一个*所代替的字符
第三种:动态访问实现(不用)
2、错误
1)若action方法中有返回值,在配置文件中没有配置,出现错误
404-No result defined…
2)action里面的方法有返回值,若有返回值类型必须是String
3)action里面的方法没有返回值时候,在result标签不需要配置
-把方法写成void
-返回一个“none”/NONE(建议写成这两个,有继承使可以用NONE)
结果页面配置
全局结果页面
1、result标签配置action方法的返回值到不同的路径里面
2、创建两个action,执行默认的execute方法,让两个action的方法都返回success,返回success之后,配置到同一个页面里面。
(1)如果多个action,方法里面的返回值相同,到页面也是相同的,这个时候可以使用全局结果页面配置
<package name="hellodemo" extends="struts-default" namespace="/">
<action name="person" class="cn.tony.action.PersonAction">
<result name="success">/index.jsp</result>
</action>
<action name="user" class="cn.tony.action.UserAction">
<result name="success">/index.jsp</result>
</action>
</package>
(2)在package标签里面配置
<global-results>
<result name="success">/index.jsp</result>
</global-results>
局部结果页面
1、配置了全局页面,也配置了局部页面,以局部页面为准
Result标签的type属性
1)配置如何到路径中(请求转发或重定向)
2)type属性默认值做请求转发操作//dispatcher(地址栏不变,页面内容改变)
第二个值是做重定向操作,值是redirect(地址栏会变)
上面两种情况针对于到页面的跳转
配置到action里面
-chain //转发到action,一般不用,缓存问题
-redirectAction //重定向到action
Action获取表单提交数据**
1)知识引入
之前web阶段,提交表单到servlet里面,在servlet里面使用request对象里面的方法获得,getParameter,getParameterMap
2)提交表单中到action,但是action没有request对象,不能直接使用
3)action获取表单提交数据主要有三种方式
1、使用ActionContext类
2、使用ServletActionContext类
3、使用接口注入方式(基本不用)
下面详细说明这三种方法,
1、使用ActionContext类
Map<String,Object>getParameters() //返回一个包含所有HttpServletRequest参数信息
(1)因为这个方法不是静态的方法,需要创建ActionContext类的对象
(2)这个ActionContext类对象不是被new出来的
static ActionContext getContext()//获取当前线程的ActionContext对象
具体演示
注意那个Map要导入java.util包里面的,否则会报错
Form1DemoAction代码
public class Form1DemoAction extends ActionSupport {
@Override
public String execute() throws Exception{
//第一种方式:使用ActionContext对象获取
//1、获取ActionContext对象
ActionContext context=ActionContext.getContext();
//2、使用方法得到表单数据
//key是表单输入项name属性值,value是输入的值
Map<String,Object> map=context.getParameters();
Set<String> keys=map.keySet();
for(String key:keys){
//根据key得到value
Object[] obj=(Object[])map.get(key);
System.out.println(Arrays.toString(obj));
}
return NONE;
}
}
struts.xml代码
<package name="demo2" extends="struts-default" namespace="/">
<action name="form1" class="cn.tony.form.Form1DemoAction"></action>
</package>
form1.jsp代码
<form action="${pageContext.request.contextPath}/form1.action" method="post">
username:<input type="text" name="username">
<br/>
password:<input type="text" name="password">
<br/>
address:<input type="text" name="address">
<br/>
<input type="submit" value="提交">
</form>
2、使用ServletActionContext类
API
(1)调用类里面的静态方法,得到request对象
Form2DemoAction代码
public String execute() throws Exception{
//第二种方式:使用ServletActionContext类获取
//1、使用ServletActionContext类获取requert对象
HttpServletRequest request=ServletActionContext.getRequest();
//2、调用request里面的方法得到结果
String username = request.getParameter("username");
String password = request.getParameter("password");
String address = request.getParameter("address");
System.out.println(username+":"+password+":"+address);
return NONE;
}
struts.xml代码
<package name="demo2" extends="struts-default" namespace="/">
<action name="form1" class="cn.tony.form.Form1DemoAction"></action>
<action name="form2" class="cn.tony.form.Form2DemoAction"></action>
</package>
form2.jsp代码
<form action="${pageContext.request.contextPath}/form2.action" method="post">
username:<input type="text" name="username">
<br/>
password:<input type="text" name="password">
<br/>
address:<input type="text" name="address">
<br/>
<input type="submit" value="post">
</form>
3、使用接口注入,一般不用,就不看啦
在Action操作域对象
1、request、session、servletContext
public class Form3DemoAction extends ActionSupport {
@Override
public String execute() throws Exception{
//操作三个域对象
//request域
HttpServletRequest request=ServletActionContext.getRequest();
request.setAttribute("req","reqValue");
//session域
HttpSession session=request.getSession();
session.setAttribute("sess","sessValue");
//ServletContext域
ServletContext context=ServletActionContext.getServletContext();
context.setAttribute("contextname", "contextValue");
return NONE;
}
}
Strut2封装获取表单数据方式
Old School
原始方式,麻烦,但事实上是最几把叼的。
有的时候做框架的时候有些功能实现不了,就用原始方式去写
public class Form4DemoAction extends ActionSupport {
@Override
public String execute() throws Exception{
//获取表单数据
HttpServletRequest request=ServletActionContext.getRequest();
String username =request.getParameter("username");
String password=request.getParameter("password");
String address =request.getParameter("address");
//封装到实体类的一个对象里面去
User user =new User();
user.setUsername(username);
user.setPassword(password);
user.setAddress(address);
//System.out.println(user.getUsername());
return NONE;
}
}
New School
属性封装
直接把表单提交属性封装到action 的属性里面
实现步骤:
1、在action成员变量位置定义变量。变量名称要和表单输入项的name属性值一样
2、生成变量的set方法(set和get方法都写出来)
data1.jsp
<form action="${pageContext.request.contextPath}/data1.action" method="post">
username:<input type="text" name="username">
<br/>
password:<input type="text" name="password">
<br/>
address:<input type="text" name="address">
<br/>
<input type="submit" value="post">
</form>
DataDemo1Action.java
//1定义变量
//变量的名称要和表单输入项name属性值一样
private String username;
private String password;
private String address;
//2生成变量的set和get方法
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
模型驱动封装(important)
1、使用模型驱动方式,可以直接把表单数据封装到实体类里面
2、实现步骤
1)action实现接口ModelDriven
2)实现接口里面的方法getModel方法
-把创建对象返回
3)在action里面创建实体类的对象
前提要求:表单输入项name属性值和实体类属性名称一致
public class DataDemo2Action extends ActionSupport implements ModelDriven<User>{
//创建对象
//前提要求:表单输入项name属性值和实体类属性名称一致
private User user=new User();
public User getModel(){
//返回创建的user对象
return user;
}
@Override
public String execute() throws Exception{
return NONE;
}
}
3、使用模型驱动和属性封装注意问题:
1)在一个action中 ,获取表单数据可以属性封装,使用模型驱动封装,但是不能同时使用属性封装和模型驱动封装获取同一个表单数据
如果同时使用,只会执行模型驱动
表达式封装(sometimes算在属性封装里面,会用即可)
1、实现过程
1)使用表达式封装可以把表达数据封装到实体类对象里面
第一步 在action里面声明实体类
第二步 生成实体类变量的set和get方法
第三步 在表单输入项
data3.jsp
<form action="${pageContext.request.contextPath}/data3.action" method="post">
username:<input type="text" name="user.username">
<br/>
password:<input type="text" name="user.password">
<br/>
address:<input type="text" name="user.address">
<br/>
<input type="submit" value="post">
</form>
DataDemo3Action.java
必须提供get方法!
//1声明实体类
private User user;
//2生成实体类变量的set和get方法
public User getUser(){
return user;
}
public void setUser(User user){
this.user=user;
}
比较表达式封装和模型驱动封装
1、相同点:使用表达式封装和模型驱动封装都可以把数据封装到实体类对象里面
2、不同点:
1)一个action里面使用模型驱动只能把数据封装到一个实体类对象里面
implements ModelDriven<User>
2)使用表达式封装可以把数据封装到不同的实体类的对象里面
data3.jsp
<form action="${pageContext.request.contextPath}/data3.action" method="post">
<!-- 前三个属性封装到user对象里面 -->
username:<input type="text" name="user.username">
<br/>
password:<input type="text" name="user.password">
<br/>
address:<input type="text" name="user.address">
<br/>
<!-- 这个属性封装到book对象里面 -->
bname:<input type="text" name="book.bname">
<br/>
<input type="submit" value="post">
</form>
DataDemo3Action.java
//1声明实体类
private User user;
private Book book;
//2生成实体类变量的set和get方法
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public User getUser(){
return user;
}
public void setUser(User user){
this.user=user;
}
Strut2获取数据封装到集合中(会用)
1)封装到list集合
1、在action里面声明list
2、生成list变量的set和get
3、在表单输入项里面写表达式
ListAction.java
//1声明list变量
private List<User> list;
//2生成它的get和set方法
public List<User> getlist(){
return list;
}
public void setlist(List<User> list){
this.list=list;
}
list.jsp
<form action="${pageContext.request.contextPath}/list.action" method="post">
<!-- list[0]表示list集合中第一个user对象 -->
username:<input type="text" name="list[0].username">
<br/>
password:<input type="text" name="list[0].password">
<br/>
address:<input type="text" name="list[0].address">
<br/><br/>
username:<input type="text" name="list[1].username">
<br/>
password:<input type="text" name="list[1].password">
<br/>
address:<input type="text" name="list[1].address">
<br/>
<input type="submit" value="post">
</form>
list.jsp
<form action="${pageContext.request.contextPath}/list.action" method="post">
<!-- list[0]表示list集合中第一个user对象 -->
username:<input type="text" name="list[0].username">
<br/>
password:<input type="text" name="list[0].password">
<br/>
address:<input type="text" name="list[0].address">
<br/><br/>
username:<input type="text" name="list[1].username">
<br/>
password:<input type="text" name="list[1].password">
<br/>
address:<input type="text" name="list[1].address">
<br/>
<input type="submit" value="post">
</form>
struct.xml
<action name="list" class="cn.tony.data.ListAction"></action>
2)封装到map集合
1、声明一个map集合
2、生成get和set方法
MapAction.java
//1声明map集合
private Map<String.User> map;
//2生成map的get和set方法
public Map<String.User> getMap() {
return map;
}
public void setMap(Map<String.User> map) {
this.map = map;
}
3、在表单输入项的name属性值里面写表达式
map.jsp
<form action="${pageContext.request.contextPath}/map.action" method="post">
<!-- 设置key值map['key值'] -->
username:<input type="text" name="map['one'].username">
<br/>
password:<input type="text" name="map['one'].password">
<br/>
address:<input type="text" name="map['one'].address">
<br/><br/>
username:<input type="text" name="map['two'].username">
<br/>
password:<input type="text" name="map['two'].password">
<br/>
address:<input type="text" name="map['two'].address">
<br/>
<input type="submit" value="post">
</form>
struts.xml
<action name="map" class="cn.tony.data.MapAction"></action>
OGNL概述
之前用的表达式封装就用到过ognl
1、之前WEB阶段el表达式实在jsp中获取域对象里面的值
2、OGNL是一种表达式,这个表达式功能更加强大
1)在struts2里面用它操作值栈数据(主要功能)
2)在struts2操作一般呵呵struts2标签一起操作值栈
3、OGNL不是struts2的一部分,是单独的项目,经常和struts2一起使用
1)使用OGNL时需要导入jar包,struts2提供jar包
值栈概述
ValueStack是Struts的一个借口,字面意义为值栈,OgnlValueStack是ValueStack的一个实现类,客户端发起一个请求struts2架构会创建一个action’对象实例,同时也创建一个OgnlValueStack值栈实例,OgnlValueStack会贯穿真个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式读取值栈中的对象属性值
**
获取值栈对象
1 获取值栈对象有多种方式
1)常用方式:使用ActionContext类里面的方法得到值栈对象
值栈的结构主要有root和context俩部分
root结构:
是list集合
一般操作都是root里面的数据
context结构:
是map集合
action对象里面有值栈对象
值栈对象里面有action引用
向值栈放数据
栈-先入后出
1、获取值栈对象,调用值栈对象里面的set方法
在list中生成一个Map集合,将其放到了栈顶
2、获取值栈对象,调用值栈对象里面的push方法
调用了push之后栈中情况是这样子的
3、在action定义变量,生成变量的get方法
拦截器概述
java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。