java审计框架基础
2022-8-19 16:17:49 Author: goddemon的小屋(查看原文) 阅读量:21 收藏

好像已经很久没发过文章了,水一篇吧,最近在回头恶补java web的一些东西还有研究链条和内存马的一些东西,有些东西还没整明白,怕误人子弟,所以暂时就不发了。

后面等学明白了在发吧,先发一篇java审计需要的一些基础知识点吧,也能算是开发吧(也是笔者基于javaweb学习过程中自己基于自己的理解的一些学习笔记,所以可能存在一些问题,若有问题,希望批评指教),也希望能给入坑审计java审计的人一些参考吧。而至于实战审计的一些文章,最近一段时间应该是不会打算发的,倒不是说没相关的素材,最近也确实审计了不少的系统,水了不少的cnvd证书和奖金。

但是从自己本身而言还是不是特别喜欢写相关的东西。

写基于系统本身的一些漏洞的代码审计吧,在某种角度而言其实就是路由+source+sink+trick,而基于这种漏洞本身而言,其实可能遇到的绕过技巧本身不会太多,最多也就是几个组合拳或者几个特性导致的一些问题。

而基于组件和链条相关的漏洞挖掘吧,能力仍有不足,所以基于这种角度还不如安心分享自己的一些知识笔记。

最后:虚心进步,慢慢成长。

java常用类库

java.applet 提供了创建applet需要的所有类
java.awt.* 提供了创建⽤户界⾯以及绘制和管理图形、图像的类
java.beans.* 提供了开发Java Beans需要的所有类
java.io 提供了通过数据流、对象序列以及⽂件系统实现的系统输⼊、输出
java.lang.* Java编程语⾔的基本类库
java.math.* 提供了简明的整数算术以及⼗进制算术的基本函数
java.rmi 提供了与远程⽅法调⽤相关的所有类
java.net 提供了⽤于实现⽹络通讯应⽤的所有类
java.security.* 提供了设计⽹络安全⽅案需要的⼀些类
java.sql 提供了访问和处理来⾃于Java标准数据源数据的类
java.test 包括以⼀种独⽴于⾃然语⾔的⽅式处理⽂本、⽇期、数字和消息的类和接⼝
java.util.* 包括集合类、时间处理模式、⽇期时间⼯具等各类常⽤⼯具包
javax.accessibility 定义了⽤户界⾯组件之间相互访问的⼀种机制
javax.naming.* 为命名服务提供了⼀系列类和接⼝
javax.swing.* 提供了⼀系列轻量级的⽤户界⾯组件,是⽬前Java⽤户界⾯常⽤的包
注:在使⽤Java时,除了java.lang外,其他的包都需要import语句引⼊之后才能使⽤

常用注解

格式:

@注解名称(属性=属性值)@suerping(value='aaa') 

概念:也叫元数据。即对一些说明含义做了一些简写操作。

意义:

①编写文档:利用注解生成文档。

②代码分析:利用注解对代码进行分析。

③编译检测:让编译器进行基础的编译检测。如@Override就是一个编译检查注解


1.基础路由以及函数相关的注解
@override  重写
@WebServlet("/hello") servlet中的配置路由的注解

2.spring引入相关注解
@Component:创建此类的对象,并放入到Spring容器中。即给一个对象起对象名
//@Component("xxxx"):创建此类的对象,取一个对象名,并放入到Spring容器中。
@Autowired:默认自动按照类型在Spring容器寻找对象,并注入到属性中。
//即在spring容器中寻找对象,然后注入到属性中,所以此时要注意:UserDao接口的实现类只能有一个。
@Value
//用于设置默认值,配置文件时使用
//如@Value("${jdbc.url}") 配置jdbc的路由
//@Value("#{T(java.lang.Math).PI}")或者配置springEL表达式

3.作用范围注解
@Scope(),设置bean的作用域。

案例使用:

1.给UserDao取对象名

@Repository("userDao")
public class UserDaoImpl implements UserDao{ }

2.使用@Qualifier通知@Autowired 注解,注入对象名为userDao的对象

@Autowired
@Qualifier("userDao")//即把属性userDao的注入到userDao的值中去
private UserDao userDao;
image.png

注意点:

①与@Component相同注解含义的注解

  1. @Service 业务层组件
  2. @Controller 控制层组件
  3. @Repository 数据层组件

四层

view(视图层)->controller层(控制值)-->server层(服务层)-->dao层(持久层)-->entity(实体层)

url获取以及转发实现代码(request作用域的实现)

URL获取

具体的几种方法
①request.getRequestURL();//获取除参数以外的所有路径
②request.getRequestURI();//获取除参数以及域名以外的所有路径
③request.getQueryString();/获取参数字符串
④request.getMethod();//获取请求方式
⑤request.getProtocol();//获取当前协议版本
以http://www.baidu.com/aa/ssss?name=ice为例
获取请求时的完整路径:Srting url= request.getRequestURL()+"";
结果  http://www.baidu.com/aa/ssss
获取请求时的部分路径:String uri=request.getRequestURI();
结果  /aa/ssss
获取请求时的参数字符串:String queryString=request.getQueryString();
结果  name=ice
获取请求方式:Srting method=request.getMethod();
结果  GET/POST/PUT/DELETE
获取当前协议版本:String protocol=request.getProtocol()
结果  HTTP/1.1
获取项目站点名:String webapp=request.getContextPath()
结果  /aa (这个看Tomcat的配置)

获取请求参数:request.getParmater("name")
获取请求同一参数的所有值(复选框传值):request.getParmaterValues("name")

转发跳转

request.getRequestDispatcher("/jsp/index.jsp").forward(request, response);
重定向
response.sendRedirect("//jsp/index.jsp");

Spring

基础

体系结构

①框架结构
image.png
  1. 核心容器(Core Container)
  2. AOP(Aspect Oriented Programming)
  3. 设备支持(Instrmentation)
  4. 数据访问及集成(Data Access/Integeration)
  5. Web报文发送(Messaging)
  6. Test测试
②结构详细解释
  • Spring Core 核心容器模块
    1. spring-core包和spring-beans包提供框架的基础部分,包括IOC和DI功能,BeanFactory是一个复杂的工厂模式的实现,无需编程就能实现单例,并允许开发人员将配置和特定的依赖从实际程序逻辑中解耦
    2. Context包建立在core和beans模块的基础之上,context继承了Beans模块的特性,并且增加了对国际化的支持,事件广播,资源加载和创建上下文等等
    3. spirng-expression包提供了强大的表达式语言
  • AOP模块

能够实现方法拦截器和切入点完全分离的代码。

  • 事务
  • 消息模块
  • 数据访问

提供了数据访问,事务,对象关系映射等功能的集成

  • web

即将要学习的Springmvc框架包含其中,两外还包括了spring5新增的支持响应式编程的Web开发框架

  • 测试

组合Junit或TestNG来实现单元测试和集成测试等功能

两大核心:

DI:依赖注入(Dependency Injection),作用:去除组件之间的依赖关系,实现解耦合。含义:所谓依赖注入,是指工程中需要的组件无须自己创建,而是依赖于外部环境注入。AOP:面向切面编程(filter以及代理问题即通过这个实现)

几个注意点

①BeanFactory与ApplicationContext
BeanFactory

BeanFactory是spring的核心接口,提供了IOC的配置机制,作用是实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。使用的代码特点:链接:https://blog.csdn.net/qq_43203949/article/details/124203569使用BeanFactory或者是其接口的特点即可

public interface BeanFactory {

    /**
     * factoryBean的前缀
     */

    String FACTORY_BEAN_PREFIX = "&";

    /*
     * 四个不同形式的getBean方法
     */

    Object getBean(String name) throws BeansException;

    <T> getBean(String name, Class<T> requiredType) throws BeansException;

    <T> getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;
 
 // 是否存在某个bean
    boolean containsBean(String name)
    
 // 是否为单实例,bean的作用域为Singleton
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
 // 是否为原型(多实例),bean的作用域为Prototype
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
 // 名称、类型是否匹配
    boolean isTypeMatch(String name, Class<?> targetType)
            throws NoSuchBeanDefinitionException
;
 // 通过Bean的名字获取该bean的类型
    Class<?> getType(String name) throws NoSuchBeanDefinitionException; 
 // 根据实例的名字获取实例的别名
    String[] getAliases(String name);

}

ApplicationContext

概念:应用上下文(org.springframework.context.ApplicationContext),继承自BeanFactory。作用:提供了更多面向应用的功能,比如国际化支持、框架事件体系,更易于创建实际应用。(实际应用一般是用它)

②IOC与DI
IOC:

概念:控制反转(Inversion of Control):它是一种控制权的转移。即组件与组件之间的依赖由主动变为被动。也就是说:应用程序本身不再负责组件的创建、维护等,而是将控制权移交出去。从这一点来说,几乎所有的框架都是IOC框架。

DI:(和IOC的关系是IOC思想的具体实现方法)

依赖注入(Dependency Injection):依赖其他容器(比如spring)来创建和维护所需要的组件,并将其注入到应用程序中。

DI(依赖注入)

注解方式配置

<!--开启注解扫描,设置需要扫描的包  -->
    <context:component-scan base-package="com.neusoft"/>

xml配置文件方式

依赖注入的几种方式
①set方法注入(即默认的方式就是set方法)
//1.)注入对象属性,这里的ref必须是利用bean标签设置好了的
<property  name="set方法后的方法名" ref="被注入的对象id"></property>
//2.)注入普通属性,这里的value可以是属性值也可以是类
//<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="属性名" value="属性值"></property>
//3.)注入list集合属性
 <proerty name="属性名">
   <list>
   <value>值1</value>
   <value>值2</value>
   <value>值3</value>
   </list>
 </proerty>
//4.)注入map集合属性
<proerty name="属性名">
<map>
<entry key="map集合的键" valueref="map集合的值"></entry>
<entry key="map集合的键" valueref="map集合的值"></entry>
<entry key="map集合的键" valueref="map集合的值"></entry>
</map>
</proerty>
//5.)注入properties集合属性
<property name="属性名">
<props>
<prop key="properties集合的键">值1</prop>
<prop key="properties集合的键">值2</prop>
<prop key="properties集合的键">值3</prop>
</props>
</property>

SET拓展注入:P命名空间和C命名空间 P命令空间注入C命名空间注入

②带参构造注入(构造器注入)
//1.)注入对象属性
 <constructor name="属性名" ref="被注入对象id"></constructor>
//2.)注入普通属性
 <constructor name="属性名" value="属性值"></constructor>
//3.)注入list集合属性
<constructor name="属性名">   
<list>
<value>值1</value>
<value>值2</value>
<value>值3</value>
</list>
</constructor>
//4.)注入map集合属性
<constructor name="属性名">
<map>
<entry key="map集合的键" valueref="map集合的值"></entry>
<entry key="map集合的键" valueref="map集合的值"></entry>
<entry key="map集合的键" valueref="map集合的值"></entry>
</map>
</constructor>
//5.)注入properties集合属性
<constructor name="属性名">
<props>
<prop key="properties集合的键">值1</prop>
<prop key="properties集合的键">值2</prop>
<prop key="properties集合的键">值3</prop>
</props>
</constructor>
详细代码
①pom.xml中配置依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <!-- 设置jdk版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <!-- spring 版本号 -->
        <spring.version>5.2.8.RELEASE</spring.version>
    </properties>
    <dependencies>
        <!-- 此依赖会关联引用Spring中的所有基础jar包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

</project>

成功后是这种的且配置资源时会下载相关的spring东西

②配置service,dao,以及配置文件

目录结构xml文件代码(即xml文件需要扔进resources中去配置)

//通过构造器实例化bean,id和name属性都指定Bean对象的名称,方便从Spring容器中查找相应的Bean class属性用于指定Bean类型,会自动调用无参构造创建对象
//意义就是给class换个名字然后方便spring从中取出值获取
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageService" class="com.houpu.classn.service.MessageService"/>
    //这里的userDao是bean设置好了的
    //<bean id="userDao" class="com.neusoft.dao.impl.UserDaoImpl"></bean>
//<property name="userDao" ref="userDao"/>这里没使用这个,但是这个标签的意义将一个对象注入到一个属性中去,如这里的意义就是将userDao对象注入到userDao中去
</beans>

这里的一个点需要注意:spring实例化bean的三种方式 ①构造器进行实例化 上面的这种即是构造器实例化 ②静态方式实例化 xml文件配置方法

<bean id="personService1" class="cn.mytest.service.impl.PersonServiceFactory" factory-method="createPersonServiceBean">这里的factory-method是实现实例化类的静态方法。这里的类即如下package cn.mytest.service.impl;
public class PersonServiceFactory {   //创建静态方法
**            public** static PersonServiceBean createPersonServiceBean(){
//返回实例化的类的对象
return new PersonServiceBean();
}
}
然后调用获取方法和上面的一样即可 ③实例化工厂方法实例化 和上面的区别就是spring配置文件的区别 类和上面一样 但是xml文件中配置方式不同

<bean id="personServiceFactory" class="cn.mytest.service.impl.PersonServiceFactory"><bean id="personService2" factory-bean="personServiceFactory" factory-method="createPersonServiceBean1">
第一个bean使用构造器方式实例化类,第二个bean调用第一个实例化的类

service代码

package com.houpu.classn.service;

public class MessageService {
    public void printMessage(){
        System.out.println("HelloWrold!");
    }
}

class文件代码

package com.houpu.classn;

import com.houpu.classn.service.MessageService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyApplication {
    public static void main(String[] args) {
        //通过ApplicationContext实现注册bean组件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service.xml");
        MessageService messageService = (MessageService)applicationContext.getBean("messageService");
        messageService.printMessage();
    }
}

javaConfig方式

基础知识:
原理:

javaConfig是spring3.0后并入到spring中的,可以理解为一个用于完成bean装配的spring容器即spring配置文件。(只是该容器是用java实现的)

使用方法:

@Configuration和@Bean @Configuration的作用

跟@Component的功能含义差不多,即可以理解为一个类。

@Bean即和的原理差不多,每一个@Bean的方法都相当于提供了一个Bean的定义信息。

创建的具体代码

1.javaConfig创建代码

package com.neusoft;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.neusoft.dao.UserDao;
import com.neusoft.dao.impl.UserDaoImpl;
import com.neusoft.service.UserService;
import com.neusoft.service.impl.UserServiceImpl;
@Configuration
public class AppConfig {
    @Bean
    public UserDao userDao() {
        return new UserDaoImpl();
    }
    @Bean
    public UserService userService() {
        //这里不能声明接口类型
        UserServiceImpl userService = new UserServiceImpl();
        //配置依赖关系(需要set方法)
        userService.setUserDao(userDao());
        return userService;
    }
}

2.测试类

package com.houpu.classn;

import com.houpu.classn.service.MessageService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyApplication {
    public static void main(String[] args) {
ApplicationContext context = new  ClassPathXmlApplicationContext("spring.xml");
UserService service = (UserService)context.getBean("userService");
User user = service.getUser();
System.out.println(user);
    }
}

AOP

基础知识

即必备内容为

1、目标对象——这里的目标是一个类,你想给日志类多一个update的功能,这个日志类就是目标对象
2、连接点——比如日志类有一个add方法,这个add方法就是连接点,你可以
1、通知——给类增强的逻辑,
前置通知——在方法之前执行
后置通知——方法之后执行
异常通知——方法出现异常执行
最终通知
环绕通知
①动态代理和静态代理

静态代理:自己写代理对象。

动态代理:在运行期,生成一个代理对象。

②五种通知类型
意义:定义一个“切面”要实现的功能。
类型:
  1. 前置通知:在某连接点(JoinPoint 就是要织入的业务方法)之前执行的通知。

2.后置通知:当某连接点退出时执行的通知(不论是正常结束还是发生异常) 

3.返回通知:(最终通知,可以理解为获取返回值时获取到的通知)在这里可以得到业务方法的返回值。但在发生异常时无法得到返回值。

4.环绕通知:包围一个连接点的通知,也就是在业务方法执行前和执行后执行的通知。

5.异常通知:在业务方法发生异常时执行的通知。

实现代码:
package com.neusoft.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
    //定义通用Aspect表达式,下面通知方法就可以引用此方法的规则了
    @Pointcut("execution(* com.neusoft.service.impl.*.*(..))")
    private void anyMethod(){}
    @Before("anyMethod()")
    public void beforeMethod(JoinPoint joinpoint){
        System.out.println("【前置通知日志】" + joinpoint.toString());
    }
    @After("anyMethod()")
    public void afterMethod(JoinPoint joinpoint){
        System.out.println("后置通知日志" + joinpoint.toString());
    }
    @AfterReturning(pointcut="anyMethod()",returning="result")
    public void afterReturnning(JoinPoint joinpoint,Object result){
        System.out.println("返回通知日志" + joinpoint.toString());
    }
    @AfterThrowing(pointcut="anyMethod()",throwing="ex")
    public void afterThrowing(JoinPoint joinpoint,Exception ex){
        System.out.println("异常通知日志" + joinpoint.toString());
    }
    @Around("anyMethod()")
    public Object aroundMethod(ProceedingJoinPoint pjp) {
        Object obj = null;
        try{
            System.out.println("环绕通知日志" + pjp.toString());
            obj = pjp.proceed();
        }catch(Throwable e){
            e.printStackTrace();
        }
        return obj;
    }
}
③spring 动态代理两种实现方式:

自动化切换这两种代理的规则:

①如果目标对象实现了接口,采用jdk动态代理实现aop。
②如果目标对象没有实现接口,采用CGLib动态代理实现aop。
③如果目标对象实现了接口,但仍然想要使用CGLIB实现aop,可以手动进行配置。
①jdk动态代理:

概念:根据目标类接口获取代理类实现规则,生成代理对象。这个代理对象,也是目标类接口的一个实现类。

public static void main(String[] args) {
    ApplicationContext context = new  ClassPathXmlApplicationContext("spring.xml");
    long begin = System.currentTimeMillis();
    //使用接口 就是这里的区别
    UserService service = (UserService)context.getBean("userService");
    User user = service.getUser();
    long end = System.currentTimeMillis();
    System.out.println("执行时间:"+(end-begin));
}
②cglib动态代理:

概念:根据目标类本身获取代理类实现规则,生成代理对象。

这个代理对象,也是目标类的一个子类。(如果目标类为final,则不能使用CGLib实现动态代理)。

public static void main(String[] args) {
    ApplicationContext context = new  ClassPathXmlApplicationContext("spring.xml");
    long begin = System.currentTimeMillis();
    //不使用接口
    UserServiceImpl service = (UserServiceImpl)context.getBean("userService");
    User user = service.getUser();
    long end = System.currentTimeMillis();
    System.out.println("执行时间:"+(end-begin));
}
③注意点:

1.)service和dao层注意事项

  1. dao层不能再实现接口。
  2. service层不能再实现接口。
④AOP实现具体代码

1.导入相关坐标,如下图所示,导入下图POM依赖2.创建目标对象和切面对象,就是写两个普通的类,目标对象如下切面对象3.创建配置文件4.编写测试类,调用save方法,此时运算结果就是我们在调用save时,同时调用了myAspect5.输出结果如这里审计中出现了这个的含义即是如果调用了 com.whir.evo.weixin.actionsupport..(..)就去执行com.whir.evo.weixin.aop.WeixinAuthAspect

小tips

①Spring配置文件很多,因此可以将xml分块使用Import引入配置xml

spring的文件中去配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean name="service" class="service.userService2">
    <property name="userBean2" ref="userBean2"></property>
</bean>
<import resource="applicationContext-xxx.xml"></import>

</beans>

SpringMVC框架

基础知识:

1.执行原理以及spring配置基础:

image.png
①springmvc的几个配置文件

spring-servlet.xml文件配置解析器以及扫描包实现注解功能 当然解析器规则也可以写到spring-mvc.xml中去,spring-dao.xml配置数据库来源这些

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd"
>

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.shida.controller"/>
    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler />
    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而annotation-driven配置帮助我们自动完成上述两个实例的注入。
     -->
    <mvc:annotation-driven />
    <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
    <context:component-scan base-package="com.shida.controller"/>
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefixvalue="/WEB-INF/jsp/" />
        <!-- 后缀 -->
        <property name="suffixvalue=".jsp" />
    </bean>

</beans>

image.png
②创建controller
  • @Controller是为了让Spring IOC容器初始化时自动扫描到;
  • @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
  • 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
  • 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
package com.shida.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Description:
 *
 **/

@Controller
@RequestMapping("/HelloController")
public class HelloController {
    
    @RequestMapping("/hello")
    public String sayHello(Model model) {
        //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
        model.addAttribute("msg""hello,SpringMVC");
        //web-inf/jsp/hello.jsp
        return "hello";
    }
}

③配置解析

必要条件:起到能被扫描到的作用

//@Controller注解的类会自动添加到Spring上下文中
@Controller
public class ControllerTest2{

   //映射访问路径
   @RequestMapping("/t2")
   public String index(Model model){
       //Spring MVC会自动实例化一个Model对象用于向视图中传值
       model.addAttribute("msg""ControllerTest2");
       //返回视图位置
       return "hello";
  }

}

2.注解(相关的注解)

@Controller
@RequestMapping("/user")
public class HelloController {
    @ResponseBody
    @RequestMapping("/hello")
    public String hello() throws Exception {
        return "hello world";
    }
}
[email protected]

作用:将controller的方法返回的数据写入到response对象的body区,也就是直接将数据写入到输出流中,效果等同于使用 response.getWriter() 输出流对象向前端返回数据。

[email protected](路由跳转)

可以设置的参数:

//value:用于指定请求的URL。method:用于指定请求的方式。
@ResponseBody
@RequestMapping(value="/hello",method=RequestMethod.POST)
public String hello() throws Exception {
    return "hello world";
}

等同于的注解 @GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。

[email protected]参数

1、value——解决前后端开发不一致,如前端传参为name,后端参数为username 2、required——解决传参不规范报错问题 3、defaultValue——打开网页就进行默认传参

[email protected] 注解参数

接受的参数是来自requestBody中,一般用于接受处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。

3.处理器方法的参数请求

①处理器方法参数(即方法里面的参数)

可以进行注入的数据有

  1. HttpServletRequest对象。
  2. HttpServletResponse对象。
  3. HttpSession对象。(注意:ServletContext不会注入。)
  4. 简单数据类型。作用:获取客户端提交的单值参数。
public String hello(String userName,String password) throws Exception {}

注意:处理器方法的参数名必须与提交参数名一致。测试如下:http://localhost:8080/springmvc/user/hello?userName=zhangsan&password=123

5.数组类型。作用:获取客户端的多值参数

public String hello(Integer[] aihao) throws Exception {}

注意:处理器方法的参数名必须与提交参数名一致。测试:http://localhost:8080/springmvc/user/hello?aihao=1&aihao=2&aihao=3

6.对象类型。作用:获取客户端提交参数。

public String hello(User user) throws Exception {}

注意:处理器方法的参数名可以任意,但参数中的属性名必须与提交参数名一致。测试:http://localhost:8080/springmvc/user/hello?userId=1&userName=zhangsan&password=123

②使用@RequestParam匹配参数

作用:当处理器方法的参数与提交的参数不一样时,使用这种方式。

public String hello(@RequestParam("userName") String un, 
                    @RequestParam("password") String pw) throws Exception 
{}

注意:@RequestParam的value值必须与提交参数名一致。测试:http://localhost:8080/springmvc/user/hello?userName=zhangsan&password=123

③Ajax提交json数据(这种主要还是提交多个参数这块的)

前端

<button onclick="hello()">提交</button>
<script src="https://unpkg.com/axios/dist/axios.js"></script>
<script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>
<script>
    let user = {
        userId:1,
        userName:'zhangsan',
        password:'123'
    };
    function hello() {
        axios.post('http://localhost:8080/smvc/user/hello',Qs.stringify(user))
            .then(response=>{
                console.log(response.data);
            }).catch(error=>{
                console.log(error);
            });    
        /*
        axios.get('http://localhost:8080/smvc/user/hello',{params:user})
            .then(response=>{
                console.log(response.data);
            }).catch(error=>{
                console.log(error);
            });
        */

    }
</script>

后端:

//返回值设置为对象或者集合
@ResponseBody
@RequestMapping("/hello")
public User hello(User user) throws Exception {
System.out.println(user);
    return user;
}
/*
@ResponseBody
@RequestMapping("/hello")
public List<User> hello(User user) throws Exception {
    List<User> list = new ArrayList<>();
    list.add(user);
    list.add(user);
    list.add(user);
    return list;
}
*/

4.数据显示

区别:

Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;

ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;

ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

①通过modelandview
 @RequestMapping("/modelAndView")
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("hello");
        return mv;
    }
②通过modelmap
 @RequestMapping("/modelMap")
    public String hello(@RequestParam("username") String name, ModelMap model){
        //封装要显示到视图中的数据
        //相当于req.setAttribute("name",name);
        model.addAttribute("msg",name);
        System.out.println(name);
        return "hello";
    }
③通过Model
    @RequestMapping("/model")
    public String hello(@RequestParam("username") String name, Model model){
        //封装要显示到视图中的数据
        //相当于req.setAttribute("name",name);
        model.addAttribute("msg",name);
        System.out.println(name);
        return "hello";
    }
④restful(使用PathVariable结合name进行)

概念:如果一个互联网软件架构符合REST原则,就称它为RESTful架构。

使用格式:

1.映射器配置(必须为 “/” ,不能是 .do 或 .action 等后缀)

<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

2.客户端提交方式

http://localhost:8080/quick19/libai

3.处理器接受参数方式 使用@PathVariable+ /user/{id}进行占位符的匹配

⑤回写数据

直接返回字符串 1、response.getWrite().Print("xxxxxxxxxxxxxxxxxxx") 2、或者使用@ResponseBody+return "xxxx" 返回对象或集合

5.Spring MVC的一些tips

①获取请求头(获取请求头的相关值)

在spring MVC里使用@requestHeader  类似request.getHeader(name),如下图可获得agent的值@CookieValue 可以获得指定的Cookie得值

②静态资源放行(解决找不到资源的问题)
<mvc:default-servlet-handler>——找不到的默认使用tomcat来找资源
或者
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/img/**" location="/img/"/>
③文件上传

1、文件上传统用的类为commons-fileupload,在pom.xml写入 2、配置文件上传解析器(spring里通用)3、写文件上传代码(MyltipartFile后的内容即是上传传入的参数)

④Spring MVC拦截器配置(即集成handlerIntercepter,跟filter拦截器的拦截的差不多)

配置spring-mvc.xml,告诉spring我的拦截器在哪里,要匹配啥资源如下图所示,传入参数param=yes即可访问资源,在实际情况中,可以将其进行SESSION的匹配

Struts2框架

基础知识:

①目录结构与基础JAR包

目录结构
名称作用
apps用于存放官方提供的 Struts2 示例程序,这些程序可以作为学习者的参考资料。各示例均为 war 文件,可以通过 zip 方式进行解压。
docs用于存放官方提供的 Struts2 文档,包括 Struts2 的快速入门、Struts2 的文档,以及 API 文档等内容。
lib用于存放 Struts2 的核心类库,以及 Struts2 的第三方插件类库。
src用于存放该版本 Struts2 框架对应的源代码。
依赖的JAR包
文件名说   明
asm-3.3.jar操作 Java字节码的类库
asm-commons-3.3.jar提供了基于事件的表现形式
asm-tree-3.3.jar提供了基于对象的表现形式
struts2-core-2.3.37.jarStruts2 框架的核心类库
xwork-core-2.3.37.jarWeb Work 核心库,Struts2 的构建基础
ognl-3.0.6.jar对象图导航语言(Object Graph Navigation Language),Struts2 框架通过其读/写对象的属性
freemarker-2.3.22.jarStruts2 标签模板使用的类库
javassist-3.11.0.GA.jarJavaScript 字节码解释器
commons-fileupload-1.4.jarStruts2 文件上传组件依赖包
commons-io-2.2.jarStruts2 的输入/输出,传文件依赖的 JAR
commons-lang-2.4.jar包含一些数据类型工具,是对 java.lang 包的增强
log4j-api-2.2.jarStruts2 的日志管理组件依赖包的 API
log4j-core-2.2.jarStruts2 的日志管理组件依赖包

②struts2基础配置与执行流程

基础xml文件配置

web.xml 这里配置org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter即struts2的核心过滤器

<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">

<!-- 配置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>

然后基础配置action以及视图和struts.xml即可 struts.xml

  • 元素是文件的根元素,所有其他元素都放在中。
  • 元素用于进行常量配置。
  • 元素用于进行包配置,在 Struts2 框架中,包用于组织 Action 和拦截器等信息,每个包都是由零个或多个拦截器以及 Action 所组成的集合。
  • 元素用于在一个 struts.xml 配置文件中包含其他的配置文件。
<?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>元素用常量的配置-->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
//<!--<package>元素用于包配置-->作用就是多个action或者是多个拦截器的集合引用 
 <package name="default" namespace="/" extends="struts-default">
//<!--配置Action-->
<action name="index" class="Xxx"/>
//<!--配置Result-->
<result type="dispatcher">
<param name="location">/index.jsp</param>
</result>
</action>
</package>
//<!-- <include>元素用于包含配置,即当xml文件过大时的切割操作的作用 -->
<include file="example.xml"/>
</struts>

常量配置(常见的三种方式)

  • 1.在 struts.xml 文件中使用元素配置常量(常用方式)。
  • 2.在 struts.properties 文件中配置常量。
  • 3.在 web.xml 文件中通过元素配置常量。

通过配置的特点

<struts>
<!--设置默认编码集为UTF-8-->
<constant name="struts.il8n.encoding" value="UTF-8" />
<!--设置使用开发模式-->
<constant name="struts.devMode" value="true" />
</struts>

配置常类文件的顺序

1default.properties:该文件保存在 struts2-core-2.3.37.jar 中的 org.apache.struts2 包中。

2)struts-default.xml:该文件保存在 struts2-core-2.3.37.jar 文件中。

3)struts-plugin.xml:该文件保存在 struts-Xxx-2.3.37.jar 等 Struts2 插件 JAR 包中。

4)struts.xml:该文件是 Web 应用自身的 Struts2 配置文件。

5)struts.properties:该文件是 Web 应用默认的 Struts2 配置文件。

6)web.xml:该文件是 Web 应用的配置文件。

struts2执行流程

③Action实现与配置

Action实现
1.自写实现Action接口
public interface Action {
//定义Action接口中包含的一些结果字符串
public static final String SUCCESS="success";
public static final String NONE="none";
public static final String ERROR="error";
public static final String INPUT="input";
public static final String LOGIN="login";
//定义处理用户请求的execute()方法
public String execute() throws Exception;
}
2.继承ActionSupport类(一般都是这种方式)
public class LoginAction extends ActionSupport{
private static final long serialVersionUID = 1L;
     @Override
public String execute() throws Exception{
return super.execute();
 }
}
配置Action与通配符
配置Action

struts.xml

<action name="userAction" class="com.mengma.action.UserAction" method="add"></action>

action的三个常用属性

name和class和其他的差不多

这里就是method指定Action的调用方法,如果指定了method

即默认会调用action中method的方法 否则则调用execute()方法。

通配符

特点:method 属性值中的数字 1 表示匹配第 1 个 *。

当客户端发送 /user/userAction_login.action 这样的请求时,元素的 name 属性值就被设置成 userAction_login,method 属性值就被设置成 login。

当客户端发送 /user/userAction_register.action 这样的请求时,元素的 name 属性值就被设置为 userAction_register,method 属性值也被设置成 register。

<package name="user" namespace="/user" extends="struts-default">
<action name="userAction_*" class="com.mengma.action.UserAction" method="{1}">
<result>/index.jsp</result>//这里也可以用通配符来配置<result>/(1).jsp</result>
</action>
</package>
通过Action访问Servlet API的两种方式
通过 ActionContext 访问

典型的几个方法

方法声明功能描述
void put(String key, Object value)将 key-value 键值对放入 ActionContext 中,模拟 Servlet API 中的 HttpServletRequest 的 setAttribute() 方法
Object get(String key)通过参数 key 查找当前 ActionContext 中的值
Map<String, Object> get Application()返回一个 Application 级的 Map 对象
static ActionContext getContext()获取当前线程的 ActionContext 对象
Map<String, Object> getParameters()返回一个包含所有 HttpServletRequest 参数信息的 Map 对象
Map<String, Object> getSession()返回一个 Map 类型的 HttpSession 对象

具体代码

ActionContext context = ActionContext.getContext();
context.put("name","mengma");//这里的含义即是输出相关内容到页面上的含义
context.getApplication().put("name","mengma");
context.getSession().put("name","mengma");
通过 ServletActionContext 访问

涉及方法

方法声明功能描述
static PageContext getPageContext()获取 Web 应用的 PageContext 对象
static HttpServletRequest getRequest()获取 Web 应用的 HttpServletRequest 对象
static HttpServletResponse getResponse()获取 Web 应用的 HttpServletResponse 对象
static ServletContext getServletContext()获取 Web 应用的 ServletContext 对象

相关代码使用

在 WebContent 目录下创建一个名称为 message.jsp 的页面,通过 EL 表达式访问存放在 Request 对象中键值为 message 的值,其页面主体部分代码如下所示:
<div align="center">${requestScope.message }</div>

④参数与结果配置

参数配置
①利用get,set方式获取参数(此时name和massage可为外部传参),get/post均可
<form action="login" method="post" name="form1">
   用户名:<s:textfield name="username"/><br/>
   密 码:<s:password name="password"/><br/>
   <s:submit value="提交"/> 
</form>
public class TestAction extends ActionSupport{
     private String username;
     private String password;

     public String getUsername() {
      return username;
     }
     public void setUsername(String username) {
      this.username = username;
     }
     public String getPassword() {
      return password;
     }
     public void setPassword(String password) {
      this.password = password;
     }
 }

测试用例:testAction? name=admin

②利用DomainModel

jsp

<form action="login" method="post" name="form1">
 用户名:<s:textfield name="users.username"/><br/>
 密 码:<s:password name="users.password"/><br/>
 <s:submit value="提交"/> 
</form>

测试案例:testAction? resBananRc.name=admin

Action

public class TestAction extends ActionSupport{
//错误的写法,不能自己实例化,struts会自动实例化 private Users users = new Users();
private Users users;

public Users getUsers(){

return users;

}

public void setUsers(Users users){

this.users=users;

}

entity:

public class Users{
 private String username;
 private String password;

 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
}

DTO--数据传输对象

意义:接收参数和传递参数,并不是项目中的实体类。DTO:

public class UserDTO {
    private String name;
    private String password;
    private String confirm;

    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 getConfirm() {
        return confirm;
    }
    public void setConfirm(String confirm) {
        this.confirm = confirm;
    }
}

Action:

public class TestAction extends ActionSupport{
        private static final long serialVersionUID = -7463970150000893325L;
        private UserDTO userDTO;

        public UserDTO getUserDTO() {
            return userDTO;
        }
        public void setUserDTO(UserDTO userDTO) {
            this.userDTO = userDTO;
        }
        public void execeute() {
            System.out.println("姓名: " + userDTO.getName());
        }
    }

使用ModelDriven的接口进行参数获取

jsp

<form action="login" method="post" name="form1">
   用户名:<s:textfield name="username"/><br/>
   密 码:<s:password name="password"/><br/>
   <s:submit value="提交"/> 
</form>

testAction? name=admin

JAVA Action

public class sysAction extends ActionSupport implements ModelDriven<User>{
    private User user = new User();  //手动实例化

    public User getModel() {
        return user;  //返回实例
    }
}

Request对象方式进行获取

使用request. getParameter(“”)方法

public class TestAction extends ActionSupport{
     private static final long serialVersionUID = -7463970150000893325L;

     public void execeute() {
         String name = super.getRequest().getParameter("paraName");
         System.out.println("姓名:" + name);
     }
 }

结果类型
结果类型配置:

struts.xml文件中配置标签进行配置,且result存在两个参数值第一个是name(用于指定逻辑视图的名称),第二个是type(指定返回资源的类型) 里面内置的子元素含义

  • location:指定该逻辑视图所对应的实际视图资源。
  • parse:指定在逻辑视图资源名称中是否可以使用 OGNL(对象图导航语言)表达式。默认值为 true,表示可以使用,如果设为 false,则表示不支持。
<action name="loginAction" class="com.mengma.action.LoginAction">
<result name="success" type="dispatcher">
<param name="location">/success.jsp</param>
</result>
</action>

Result 配置中指定实际资源位置时,可以使用绝对路径,也可以使用相对路径。

预定义的结果类型配置含义
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
</result-types>

对应情况关系

属     性说     明
chain用于处理 Action 链,被跳转的 Action 中仍能获取上个页面的值,如 request 信息
dispatcher用于转向页面,通常处理 JSP,是默认的结果类型
freemarker用于整合 FreeMarker 模板结果类型
httpheader用于处理特殊的 HTTP 行为结果类型
redirect重定向到一个 URL,被跳转的页面中丢失传递的信息
redirectAction重定向到一个 Action,跳转的页面中丢失传递的信息
stream向浏览器发送 InputStream 对象,通常用于处理文件下载,还可用于 Ajax 数据
velocity用于整合 Velocity 模板结果类型
xslt用于整合 XML/XSLT 结果类型
plainText显示原始文件内容,如文件源代码
postback使当前请求参数以表单形式提交
Dispatcher结果类型(不改变地址栏的转发方式)

概念:dispatcher 是 Struts2 的默认结果类型,它用于表示转发到指定结果资源。

<result name="success">/1.jsp</result>  
默认为dispatcher转发,地址栏不会变
redirect
   <result name="success"  type="redirect">/1.jsp</result>  
   重定向,302,地址栏变化,当前请求的参数和数模默认在下个页面不能使用
redirctAction
   <result name="success"  type="redirctAction">/1.action/do</result>  
   和redirect类似  不过redirectAction是重定向到另外的Action类里

Dispatcher和redict的区别如下

chain
   <result name="success"  type="chain">/hello</result>  
     和redirctAction一样都是请求到另外的Action类里
     和dispatcher一样的都是进行转发,而不是重定向
     chain类型不用写后缀名,默认可携带参数进行传递
动态调用页面/转发

1.通过调用某个写好的类来进行转发,如page类 http://127.0.0.1/page=login  此时服务器直接转发login.jsp

<default-action-ref name="default"></default-action-ref>  (写在struts.xml前面点的为止)
<action name="default"  class="com.xxx">
 <result name="success">${page}.jsp</result>
</action>

2.利用通配符的方式

<action name="chapter_*" class="chapter4.action.ChapterAction" method="{1}">
    <result name="success">/WEB-INF/JspPage/chapter/chapter_{1}.jsp</result>
</action>

3.另外一种动态方式

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

调用方法:http://127.0.0.1/user/user!register.do http://127.0.0.1/user/user!login.do

4.默认调用方式(输入不存在的方法时,重定向到error.jsp页面)

<default-action-ref name="default"></default-action-ref>  (写在struts.xml前面点的为止)
<action name="default" class="com.xxxx">
 <result name="success">/error/xxxx/error.jsp</result>
</action>

拦截器

配置与使用
配置方法

元素的 name 属性用于指定拦截器的名称,class 属性用于指定拦截器的实现类。有时,在定义拦截器时需要传入参数,这时需要使用标签,其中 name 属性用于指定参数的名称,paramValue 表示参数的值 struts.xml文件配置 配置拦截器的东西+配置拦截栈+配置默认拦截器

<package name="default" namespace="/" extends="struts-default">
<!--声明拦截器-->
<interceptors>
<interceptor name="interceptor1" class="interceptorClass"/>
<interceptor name="interceptor2" class="interceptorClass"/>
<!--定义一个拦截器栈myStack,该拦截器栈中包含两个拦截器和一个拦截器栈-->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="interceptor1"/>
<interceptor-ref name="interceptor2"/>
</interceptor-stack>
</interceptors>
<!--配置包下的默认拦截器,既可以是拦截器,也可以是拦截器栈-->
<default-interceptor-ref name="myStack"/>
<action name="login" class="com.mengma.action.LoginAction">
<result name="input">/login.jsp</result>
</action>
</package>
内置拦截器
名   称说   明
alias在不同请求之间将请求参数在不同名称间转换,请求内容不变
autowiring用于实现 Action 的自动装配
chain让前一个 Action 的属性可以被后一个 Action 访问,现在和 chain 类型的 result() 结合使用
conversionError将错误从 ActionContext 中添加到 Action 的属性字段中
cookies使用配置的 Name 和 Value 指定 Cookies
cookieProvider该类是一个 Cookie 工具,方便开发者向客户端写 Cookie
clearSession用于清除一个 HttpSession 实例
createSession自动创建 HttpSession,用于为需要使用 HttpSession 的拦截器服务
debugging提供不同的调试用的页面展现内部的数据状况
execAndWait在后台执行 Action,同时将用户带到一个中间的等待页面
exception将异常定位到一个画面
fileUpload提供文件上传功能
il8n记录用户选择的 locale
logger输出 Action 的名称
model-driven如果一个类实现了 Model Driven,将 get Model 得到的结果放在 Value Slack 中
scoped-model-driven如果一个 Action 实现了 ScopedModelDriven,则这个拦截器会从相应的 Scope 中取 出 model 调用 Action 的 setModel 方法,将其放入 Action 内部
params将请求中的参数设置到 Action 中
actionMappingParams用于负责在 Action 配置中传递参数
prepare如果 Action 实现了 Preparable,则该拦截器调用 Action 类的 prepare 方法
staticParams将 struts.xml 文件中标签的参数内容设置到对应的 Action 中
scope将 Action 状态存入 session 和 application 范围
servletConfig提供访问 HttpServlet
Request 和 HttpServletResponse 方法,以 Map 方式访问
timer输岀 Action 执行的时间
token通过 Token 避免双击
tokenSession和 Token Interceptor 一样,不过双击时把请求的数据存储在 Session 中
validation使用 action-validation.xml 文件中定义的内容校验提交的数据
workflow调用 Action 的 validate 方法,一旦有错谋返回,则重新定位到 INPUT 画面
store存储或者访问实现 ValidalionAware 接口的 Action 类出现的消息、错误和字段错误等
checkbox添加了 checkbox 自动处理代码,将没有选中的 checkbox 的内容设定为 false,而 html 在默认情况下不提交没有选中的 checkbox
datetime日期拦截器
profiling通过参数激活 profile
roles确定用户是否具有 JAAS 指定的 Role,否则不予执行
annotationWorkflow利用注解代替 XML 配置,使用 annotationWorkflow 拦截器可以使用注解,执行流程为 before-execute-feforeResult-after
multiselect检测是否有像
deprecation当日志级别设置为调试模式(debug)并且没有特殊参数时,在 devMode 模式中,会检查应用程序使用过时或未知的常量,并且显示警告

使用方法:

<package name="struts-default" abstract="true">
2.     ...
<interceptors>
<!--系统内建拦截器部分,上一部分介绍的内容-->
<interceptor name="alias"
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring"
class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain"
class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
        ...
<!-- 定义Basic stack拦截器栈 -->
<interceptor-stack name="basicStack">
<!--引用系统定义的exception拦截器-->
<interceptor-ref name="exception"/>
            ...
</interceptor-stack>
        ...
<!-- 定义Sample model -driven stack -->
<interceptor-stack name="modelDrivenStack">
<!--引用系统定义的modelDriven拦截器-->
<interceptor-ref name="modelDriven"/>
<!--引用系统定义的basicStack拦截器栈-->
<interceptor-ref name="basicStack"/>
</interceptor-stack>
        ...
<!--定义defaultStack拦截器栈-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="il8n"/>
             ...
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
            ...
</interceptor-stack>
</interceptors>
<!--将defaulrStack拦截器栈配置为系统默认拦截器栈-->
<default-interceptor-ref name="defaultStack"/>
<!--默认action类是ActionSupport-->
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
</package>
自定义拦截器

原生的接口定义

public interface Interceptor extends Serializable{
void init();
void destroy();
String intercept(ActionInvocation invocation) throws Exception;
}

实现接口的类(这里进行配置实现接口即可)

public abstract class AbstractInterceptor implements Interceptor{
public void init(){}
public void destroy(){}
public abstract String intercept (ActionInvocation invocation) throws Exception;
 }

具体案例使用方法:https://www.yuque.com/dylan1314/tcqus2/tkbp4o

标签

基础知识:

标签分类:

具体:1.普通标签的主要功能是在页面生成时控制页面代码的执行流程;UI 标签的主要功能是以丰富且可复用的 HTML 文件显示数据。

2.控制标签用于完成条件逻辑和循环逻辑的控制,也可用于做集合的操作。数据标签用于输出后台的数据和完成其他数据访问功能。

3.UI 标签又分为表单标签(Form Tags)、非表单标签(Non-Form Tags)和 Ajax 标签。

表单标签主要用于生成 HTML 页面中的表单元素,非表单标签主要用于生成非表单的可视化元素,如输出 Action 中封装的信息等。Ajax 标签主要用于提供对 Ajax 技术的支持。

数据标签
<s:property>

参数与作用:<s:property> 标签的作用是输出指定的值,通常输出的是 value 属性指定的值,<s:property> 标签的属性及属性说明如下。

  • value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出 ValueStack 栈顶的值(关于值栈内容会在后面教程中进行讲解)。
  • id:可选属性,指定该元素的标识。
  • default:可选属性,如果要输出的属性值为 null,则显示 default属性的指定值。
  • escape:可选属性,指定是否忽略 HTML 代码。默认值是 true,即忽略输出值中的 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>property标签</title>
</head>
<body>
//    输出字符串:
<s:property value="'this is a string'"/><br/>
     输出默认值:
<s:property value="" default="default_value"/><br/>
    忽略HTML代码:
<s:property value="'<h2>www.w3school.com.cn</h2>'" escape="true"/><br/>
    不忽略HTML代码:
<s:property value="'<h2>www.w3school.com.cn</h2>'" escape="false"/><br/>
</body>
</html>
<s:a>

参数与作用:与 HTML 中的  标签类似,主要用于构造 HTML 页面中的超链接

属性是否必须类型描述
actionString指定超链接 Action 地址
hrefString超链接地址
namespaceString指定 Action 地址
idString指定其 id
methodString指定 Action 调用方法

<s:a> 标签的使用格式如下所示:

<s:a href="链接地址"></s:a> <s:a namespace="" action="">www.baidu.com</s:a>

<s:debug>

参数与作用:

<s:debug> 标签用于输出服务端对象(如 request、application、ValueStack 等)中的信息,该标签可用于辅助调试 Java Web 程序。

<s:include>

作用:标签用于在当前页面中包含另一个 Web 资源(如 HTML、JSP、Servlet 等)。该标签有两个属性 id 和 value。

其中 id 是可选属性,表示该标签的引用;value 是必填属性,用于指定被包含的 Web 资源文件。

1. <%@ page language="java" contentType="text/html; charset=utf-8"
2.     pageEncoding="utf-8"%>
3. <%@taglib prefix="s" uri="/struts-tags" %>
4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5. <html>
6. <head>
7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
8. <title>property标签</title>
9. </head>
10. <body>
11. <h2>这是被包含页面includefile.jsp</h2><br/>
12.     传递的参数为:<%out.print(request.getParameter("username")); %>
13. </body>
14. </html>
1. <%@ page language="java" contentType="text/html; charset=UTF-8"
2.     pageEncoding="UTF-8"%>
3. <%@taglib prefix="s" uri="/struts-tags"%>
4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5. <html>
6. <head>
7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8. <title>includeTags</title>
9. </head>
10. <body>
11. <h3>这是包含页面includeTags.jsp</h3><br/>
12. <s:include value="file.jsp">
13. <s:param name="username" value="'小韩'"/>
14. </s:include>
15. </body>
16. </html>
<s:param>

参数与作用:<s:param> 标签主要用于为其他标签提供参数,通常要与其他标签一起使用。

在上一部分使用 <s:include> 标签时,就使用了 <s:param> 标签给被包含的页面传递参数。

<s:param> 标签有两种用法代码方法:

<s:param name="color">red</s:param>
<s:param name="color" value="'red'"/>

注意点:1.在使用 value 属性设置参数值时,需要添加单引号,而使用标签体设置参数值时,不需要添加单引号。

2.在使用 value 属性指定参数时,如果不添加单引号,则表示该值为一个引用对象,如果该对象不存在,则为其属性赋值为 null。

控制标签
<s:if>

作用:和java中的if,else的用法差不多,但是这个可以单独使用

<s:if test="表达式1">
    标签体
</s:if>
<s:elseif>

作用:跟上面的差不多,不过后两者的区别是需要结合<s:if>标签使用

<s:elseif test="表达式2">
    标签体
</s:elseif>
<s:else>
<s:else>
    标签体
</s:else>
<s:iterator>标签
属性是否必须默认值类型描   述
begin0Integer迭代数组或集合的起始位置
end数组或集合的长度大小减 1,若 Step 为负,则为 0。Integer迭代数组或集合的结束位置
statusfalseBoolean迭代过程中的状态
step1Integer指定每一次迭代后索引增加的值
valueString迭代的数组或集合对象
varString将生成的 Iterator 设置为 page 范围的属性
idString指定了集合元素的 id,现已用 var 代替

stautus里面的方法具体使用:

方 法说 明
st.count返回当前已经遍历的集合元素的个数
st.first返回当前遍历元素是否为集合的第一个元素
st.last返回当前遍历元素是否为集合的最后一个元素
st.index返回遍历元素的当前索引值

具体代码使用:

<%@ 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>
<center>
<table border="1px" cellpadding="1">
<s:iterator var="name" value="{'apple','orange','pear','banana'}" status="st">
<s:if test="#st.odd">
<tr style="background-color:white;">
<td><s:property value="name"/></td>
</tr>
</s:if>
<s:else>
<tr style="background-color:grey;">
<td><s:property value="name"/></td>
</tr>
</s:else>
 </s:iterator>
</table>
</center>
 </body>
</html>
表单标签
表单标签的通用属性:
属性名主题数据类型说   明
titlesimpleString设置表单元素的 title 属性
disabledsimpleString设置表单元素是否可用
labelxhtmlString设置表单元素的 label 属性
labelPositionxhtmlString设置 label 元素的显示位置,可选值为 top 和 left(默认)
namesimpleString设置表单元素的 name 属性,与 Action 中的属性名对应
valuesimpleString设置表单元素的值
cssClasssimpleString设置表单元素的 class
cssStylesimpleString设置表单元素的 style 属性
requiredxhtmlBoolean设置表单元素为必填项
requiredpositionxhtmlString设置必填标记(默认为*)相对于 label 元素的位置,可选值为 left 和 right(默认)
tabindexsimpleString设置表单元素的 tabindex 属性

表单标签的 name 和 value 属性基本等同于 HTML 组件的 name 和 value,但也有所不同:表单标签在生成 HTML 时,如果标签没有设置 value 属性,则会从值栈中按照 name 获取相应的值,并把这个值设置成 HTML 组件的 value。

具体标签:

1.<s:form>作用:和from表单差不多

属性名是否必填类  型说  明
actionString指定提交时对应的 action,不需要 action 后缀
enctypeStringHTML 表单 enctype 属性
methodStringHTML 表单 method 属性
namespaceString所提交 action 的命名空间

2.<s:textfield>与<s:textarea>作用:创建文本框,区别是前者是单行文本框,后者是多行文本框。

<s:textfield> 标签的用法:
<s:textfield label="用户名" name="username"/>
<s:textarea> 标签的用法:
<s:textarea label="描述" name="description"/>

3.<s:passWord>标签作用:创建一个密码框,可以生成html中的标签。

属性名说   明
name用于指定密码输入框的名称
size用于指定密码输入框的显示宽度,以字符数为单位
maxlength用于限定密码输入框的最大输入字符串个数
showPassword是否显示初始值,即使显示也仍为密文显示,用掩码代替

4.<s:radio>标签作用:用于创建单选按钮,生成 HTML 中的标签。具体参数:

属性名是否必填类  型说  明
listCollection,Map Enmumeration,Iterator,Array用于生成单选框中的集合
listKeyString指定集合对象中的哪个属性作为选项的 value
listValueString指定集合对象中的哪个属性作为选项的内容

5.<s:reset>标签作用:创建一个重置按钮,会生成 HTML 中的标签,该标签的使用比较简单,其常用属性为 name 和 value。参数:

<s:reset value="reset"/>
<s:reset name="reset" value="重置"/>

6.<s:submit>标签作用:产生一个提交框的按钮。

属性名是否必填类型说明
actionString指定提交时对应的 Action
methodString指定 Action 中调用的方法

7.<s:checkboxlist>作用:一次性创建多个复选框,用户可以选择创建零到多个复选框,它可以产生一组标签 常见属性:

属性名是否必填类型说明
nameString指定该元素的 name
labelString指定复选框前显示的文本
listlist定义集合变量
listKeyString指定集合对象中的哪个属性作为选项的 value
listValueString指定集合对象中的哪个属性作为选项的内容

8.<s:select>作用:创建一个下拉列表框,它会生成 HTML 中的标签

属性名是否必填类型说明
nameString指定表单元素名
acceptString指定可接收的文件 MIME 类型,默认为input

使用方法:

<s:file name="uploadFile" accept="text/*"/>
<s:file name="otherUploadFile" accept="text/html,text/plain"/>

10.<s:hidden>作用:创建隐藏表单元素,它会生成 HTML 中的隐藏域标签方法:<s:hidden name="id" value="%{id}"/>

校验

数据校验

原理:

1.一个Action类里有vaildate()时,先执行该vaildate里的内容进行数据校验后,然后才会调用方法。

2.vaildate继承与ActionSupport类 当你写了一个Action类时,并通过struts.xml将主要的方法注册成功,且在该类里面写了一个validate方法,此时默认该类存在vaildate数据校验的功能,具体功能判断可自定义然后在struts.xml中进行配置在xxx.jsp里加上 <s:fielderror />即可回显报错errorMessage的信息

方法校验

概念:直接利用方法进行校验,即在前面加validate

框架校验

需要在Action类的同个包下创建xml文件,文件命名为Action类的类名-validation.xml 

如UserAction--validation.xml 如果你只想校验UserAction的login方法,那么就修改为UserAction-valLogin-validation.xml

文件操作

文件上传
特征:

①private File  Upload   有一个File类型的参数②ServletActionContext.getServletContext().getRealPath("/xxxx")** 一个获取绝对路径的实现**

③方法里有文件IO流FileInputStream以及FileoutputStream

具体代码:

https://blog.csdn.net/qq_33229669/article/details/80061475

文件下载
特征:

①private InputStream filename  有一个输出流参数

struts.xml配置文件里必须有的type=stream

代码

前端:

<s:a href="simpledownload?filename=test.txt" name="test">test.txt</s:a>

Action:

package com.mengma.action;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class SimpleDownLoadAction extends ActionSupport {
private String filename;

public String getFilename() {
  return filename;
 }
 public void setFilename(String filename) {
 this.filename = filename;
}

// 定义了返回InputStream的方法,该方法作为被下载文件的入口
public InputStream getDownloadFile() {
  // 获取下载文件名称
 String filename = ServletActionContext.getRequest().getParameter("filename");
// 定义下载文件路径
 String filePath = "/upload/" + filename;
  // 返回一个流对象
 return ServletActionContext.getServletContext().getResourceAsStream(
  filePath);
}
}

配置文件信息:

<action name="simpledownload" class="com.mengma.action.SimpleDownLoadAction">
<result type="stream">
<!--文件类型 -->
<param name="contentType">text/plain</param>
<!--指定文件名 -->
<param name="contentDisposition">
            attachment;filename=${filename}
</param>
<!--输入流 -->
<param name="inputName">downloadFile</param>
</result>
</action>

OGNL

基础概念

OGNL 的全称是“Object-Graph Navigation Language”,即对象图导航语言,它是一种功能强大的开源表达式语言。

使用这种表达式语言可以通过某种表达式语法存取 Java 对象的任意属性,调用 Java 对象的方法,以及实现类型转换等。

表达式%,#,$用法
①#符号

1.)访问非根对象的属性。

#相当于 ActionContext.getContext()。例如‘#session.user’表达式相当于 ActionContext.getContext().getSession().getAttribute("user"),‘#request.userName’表达式相当于 request.getAttribute("userName")。

2.)用于过滤和投影集合

 books.{?#this.price>25}

3.)构造MAP

 #{key1:value1,key2:value2},这种方式常用于给 radio 或 select、checkbox 等标签赋值。如果要在页面中取一个 Map 的值可以如下书写:<s:property value="#myMap['key']"/>。
②%符号

作用:%是在标签的属性值被理解为字符串类型时,告诉执行环境‘%{}’中的是 OGNL 表达式,并计算 OGNL 表达式的值。

③$符号

作用:用于在 Struts2 配置文件中引入 OGNL 表达式。

<action name="userAction_*" class="userAction" method="{1}">
<result name="add" type="redirect">
        userAction_findById?userId=${User.userId}
</result>
</action>
访问对象方法和静态方法
访问对象方法

调用方法:Ognl.getValue("方法名",对象名);

package com.mengma.ognl;
import ognl.OgnlException;
public class TestOgnl01 {
public static void main(String[] args) {
Person person = new Person();
       person.setName("admin");
try {
           System.out.println(ognl.Ognl.getValue("name", person));
catch (OgnlException e) {
            e.printStackTrace();
}
 }
}
静态方法和静态属性获取

设置:

@类的全路径名@属性名称
@类的全路径名@方法名称(参数列表)
需要注意的是,在低版本的 Struts2 中,已经默认开启了对访问类静态方法的支持,但是高版本的 Struts2 默认是关闭这项支持的,也就是说,要想访问类的静态方法,需要手动开启设置。开启设置的方法十分简单,只需要在 struts.xml 中进行如下配置即可。
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
在上述代码配置了一个名称为 struts.ognl.allowStaticMethodAccess 的常量,并将其值设置为 true,这就表示开启了访问静态方法的支持。接下来通过一个案例演示如何使用 OGNL 访问静态方法和静态属性。

具体代码:

1.测试类

package com.mengma.ognl;
public class TestOgnl02 {
public static String staticValue="这是静态属性值";
public static void testMethod(){
        System.out.println("这是静态方法");
}
}

2.配置文件 在配置文件 struts.xml 中,添加用于开启对静态方法访问的支持代码。

3.创建index.jsp

<%@ 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>OGNL访问静态属性和静态方法</title>
</head>
<body>
//    获取的静态属性值为:
<s:property value="@[email protected]"/><br/>
<hr/>
//   调用静态方法的结果请查看控制台
 <s:property value="@[email protected]()"/>
</body>
</html>

4.启动项目

https://www.yuque.com/neuedu/campus/zkd7cg#XIc95

https://www.yuque.com/iceqaq/fwz2q8/sgrol6

https://blog.csdn.net/m0_50890907/article/details/114900164

struts2资料

https://www.yuque.com/dylan1314/tcqus2/yy7moy


文章来源: http://mp.weixin.qq.com/s?__biz=MzI2NTc1ODY0Mw==&mid=2247485293&idx=1&sn=af1974b4a48e2ba86da364b7b4af9694&chksm=ea9935b1ddeebca7008c7afcb35df7cc9a9eb7990d3dbd4545751b5d62c2390a4c6122b40687#rd
如有侵权请联系:admin#unsafe.sh