好像已经很久没发过文章了,水一篇吧,最近在回头恶补java web的一些东西还有研究链条和内存马的一些东西,有些东西还没整明白,怕误人子弟,所以暂时就不发了。
后面等学明白了在发吧,先发一篇java审计需要的一些基础知识点吧,也能算是开发吧(也是笔者基于javaweb学习过程中自己基于自己的理解的一些学习笔记,所以可能存在一些问题,若有问题,希望批评指教),也希望能给入坑审计java审计的人一些参考吧。而至于实战审计的一些文章,最近一段时间应该是不会打算发的,倒不是说没相关的素材,最近也确实审计了不少的系统,水了不少的cnvd证书和奖金。
但是从自己本身而言还是不是特别喜欢写相关的东西。
写基于系统本身的一些漏洞的代码审计吧,在某种角度而言其实就是路由+source+sink+trick,而基于这种漏洞本身而言,其实可能遇到的绕过技巧本身不会太多,最多也就是几个组合拳或者几个特性导致的一些问题。
而基于组件和链条相关的漏洞挖掘吧,能力仍有不足,所以基于这种角度还不如安心分享自己的一些知识笔记。
最后:虚心进步,慢慢成长。
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;
view(视图层)->controller层(控制值)-->server层(服务层)-->dao层(持久层)-->entity(实体层)
具体的几种方法
①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");
能够实现方法拦截器和切入点完全分离的代码。
提供了数据访问,事务,对象关系映射等功能的集成
即将要学习的Springmvc框架包含其中,两外还包括了spring5新增的支持响应式编程的Web开发框架
组合Junit或TestNG来实现单元测试和集成测试等功能
DI:依赖注入(Dependency Injection),作用:去除组件之间的依赖关系,实现解耦合。含义:所谓依赖注入,是指工程中需要的组件无须自己创建,而是依赖于外部环境注入。AOP:面向切面编程(filter以及代理问题即通过这个实现)
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> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> 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);
}
概念:应用上下文(org.springframework.context.ApplicationContext),继承自BeanFactory。作用:提供了更多面向应用的功能,比如国际化支持、框架事件体系,更易于创建实际应用。(实际应用一般是用它)
概念:控制反转(Inversion of Control):它是一种控制权的转移。即组件与组件之间的依赖由主动变为被动。也就是说:应用程序本身不再负责组件的创建、维护等,而是将控制权移交出去。从这一点来说,几乎所有的框架都是IOC框架。
依赖注入(Dependency Injection):依赖其他容器(比如spring)来创建和维护所需要的组件,并将其注入到应用程序中。
<!--开启注解扫描,设置需要扫描的包 -->
<context:component-scan base-package="com.neusoft"/>
//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>
<?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东西
目录结构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是spring3.0后并入到spring中的,可以理解为一个用于完成bean装配的spring容器即spring配置文件。(只是该容器是用java实现的)
使用方法:
@Configuration和@Bean @Configuration的作用
跟@Component的功能含义差不多,即可以理解为一个类。
@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);
}
}
即必备内容为
1、目标对象——这里的目标是一个类,你想给日志类多一个update的功能,这个日志类就是目标对象
2、连接点——比如日志类有一个add方法,这个add方法就是连接点,你可以
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;
}
}
自动化切换这两种代理的规则:
①如果目标对象实现了接口,采用jdk动态代理实现aop。
②如果目标对象没有实现接口,采用CGLib动态代理实现aop。
③如果目标对象实现了接口,但仍然想要使用CGLIB实现aop,可以手动进行配置。
概念:根据目标类接口获取代理类实现规则,生成代理对象。这个代理对象,也是目标类接口的一个实现类。
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));
}
概念:根据目标类本身获取代理类实现规则,生成代理对象。
这个代理对象,也是目标类的一个子类。(如果目标类为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层注意事项
dao层不能再实现接口。 service层不能再实现接口。
1.导入相关坐标,如下图所示,导入下图POM依赖2.创建目标对象和切面对象,就是写两个普通的类,目标对象如下切面对象3.创建配置文件4.编写测试类,调用save方法,此时运算结果就是我们在调用save时,同时调用了myAspect5.输出结果如这里审计中出现了这个的含义即是如果调用了 com.whir.evo.weixin.actionsupport..(..)就去执行com.whir.evo.weixin.aop.WeixinAuthAspect
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>
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="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean></beans>
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";
}
}
@Controller
@RequestMapping("/user")
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello() throws Exception {
return "hello world";
}
}
作用:将controller的方法返回的数据写入到response对象的body区,也就是直接将数据写入到输出流中,效果等同于使用 response.getWriter() 输出流对象向前端返回数据。
可以设置的参数:
//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)的缩写。
1、value——解决前后端开发不一致,如前端传参为name,后端参数为username 2、required——解决传参不规范报错问题 3、defaultValue——打开网页就进行默认传参
接受的参数是来自requestBody中,一般用于接受处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。
可以进行注入的数据有
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
作用:当处理器方法的参数与提交的参数不一样时,使用这种方式。
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
前端
<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;
}
*/
区别:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
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;
}
@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";
}
@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";
}
概念:如果一个互联网软件架构符合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" 返回对象或集合
在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.xml,告诉spring我的拦截器在哪里,要匹配啥资源如下图所示,传入参数param=yes即可访问资源,在实际情况中,可以将其进行SESSION的匹配
名称 | 作用 |
---|---|
apps | 用于存放官方提供的 Struts2 示例程序,这些程序可以作为学习者的参考资料。各示例均为 war 文件,可以通过 zip 方式进行解压。 |
docs | 用于存放官方提供的 Struts2 文档,包括 Struts2 的快速入门、Struts2 的文档,以及 API 文档等内容。 |
lib | 用于存放 Struts2 的核心类库,以及 Struts2 的第三方插件类库。 |
src | 用于存放该版本 Struts2 框架对应的源代码。 |
文件名 | 说 明 |
---|---|
asm-3.3.jar | 操作 Java字节码的类库 |
asm-commons-3.3.jar | 提供了基于事件的表现形式 |
asm-tree-3.3.jar | 提供了基于对象的表现形式 |
struts2-core-2.3.37.jar | Struts2 框架的核心类库 |
xwork-core-2.3.37.jar | Web Work 核心库,Struts2 的构建基础 |
ognl-3.0.6.jar | 对象图导航语言(Object Graph Navigation Language),Struts2 框架通过其读/写对象的属性 |
freemarker-2.3.22.jar | Struts2 标签模板使用的类库 |
javassist-3.11.0.GA.jar | JavaScript 字节码解释器 |
commons-fileupload-1.4.jar | Struts2 文件上传组件依赖包 |
commons-io-2.2.jar | Struts2 的输入/输出,传文件依赖的 JAR |
commons-lang-2.4.jar | 包含一些数据类型工具,是对 java.lang 包的增强 |
log4j-api-2.2.jar | Struts2 的日志管理组件依赖包的 API |
log4j-core-2.2.jar | Struts2 的日志管理组件依赖包 |
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>
配置常类文件的顺序
1)default.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 应用的配置文件。
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;
}
public class LoginAction extends ActionSupport{
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception{
return super.execute();
}
}
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 这样的请求时,
<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>
典型的几个方法
方法声明 | 功能描述 |
---|---|
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");
涉及方法
方法声明 | 功能描述 |
---|---|
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>
<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
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:
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());
}
}
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. 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文件中配置
<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 是 Struts2 的默认结果类型,它用于表示转发到指定结果资源。
<result name="success">/1.jsp</result>
默认为dispatcher转发,地址栏不会变
<result name="success" type="redirect">/1.jsp</result>
重定向,302,地址栏变化,当前请求的参数和数模默认在下个页面不能使用
<result name="success" type="redirctAction">/1.action/do</result>
和redirect类似 不过redirectAction是重定向到另外的Action类里
Dispatcher和redict的区别如下
<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>
<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 文件中 |
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> 标签的作用是输出指定的值,通常输出的是 value 属性指定的值,<s:property> 标签的属性及属性说明如下。
使用代码:
<%@ 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>
参数与作用:与 HTML 中的 标签类似,主要用于构造 HTML 页面中的超链接
属性 | 是否必须 | 类型 | 描述 |
---|---|---|---|
action | 否 | String | 指定超链接 Action 地址 |
href | 否 | String | 超链接地址 |
namespace | 否 | String | 指定 Action 地址 |
id | 否 | String | 指定其 id |
method | 否 | String | 指定 Action 调用方法 |
<s:a> 标签的使用格式如下所示:
<s:a href="链接地址"></s:a> <s:a namespace="" action="">www.baidu.com</s:a>
参数与作用:
<s:debug> 标签用于输出服务端对象(如 request、application、ValueStack 等)中的信息,该标签可用于辅助调试 Java Web 程序。
作用:标签用于在当前页面中包含另一个 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:include> 标签时,就使用了 <s:param> 标签给被包含的页面传递参数。
<s:param> 标签有两种用法代码方法:
<s:param name="color">red</s:param>
<s:param name="color" value="'red'"/>
注意点:1.在使用 value 属性设置参数值时,需要添加单引号,而使用标签体设置参数值时,不需要添加单引号。
2.在使用 value 属性指定参数时,如果不添加单引号,则表示该值为一个引用对象,如果该对象不存在,则为其属性赋值为 null。
作用:和java中的if,else的用法差不多,但是这个可以单独使用
<s:if test="表达式1">
标签体
</s:if>
作用:跟上面的差不多,不过后两者的区别是需要结合<s:if>标签使用
<s:elseif test="表达式2">
标签体
</s:elseif>
<s:else>
标签体
</s:else>
属性 | 是否必须 | 默认值 | 类型 | 描 述 |
---|---|---|---|---|
begin | 否 | 0 | Integer | 迭代数组或集合的起始位置 |
end | 否 | 数组或集合的长度大小减 1,若 Step 为负,则为 0。 | Integer | 迭代数组或集合的结束位置 |
status | 否 | false | Boolean | 迭代过程中的状态 |
step | 否 | 1 | Integer | 指定每一次迭代后索引增加的值 |
value | 否 | 无 | String | 迭代的数组或集合对象 |
var | 否 | 无 | String | 将生成的 Iterator 设置为 page 范围的属性 |
id | 否 | 无 | String | 指定了集合元素的 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>
属性名 | 主题 | 数据类型 | 说 明 |
---|---|---|---|
title | simple | String | 设置表单元素的 title 属性 |
disabled | simple | String | 设置表单元素是否可用 |
label | xhtml | String | 设置表单元素的 label 属性 |
labelPosition | xhtml | String | 设置 label 元素的显示位置,可选值为 top 和 left(默认) |
name | simple | String | 设置表单元素的 name 属性,与 Action 中的属性名对应 |
value | simple | String | 设置表单元素的值 |
cssClass | simple | String | 设置表单元素的 class |
cssStyle | simple | String | 设置表单元素的 style 属性 |
required | xhtml | Boolean | 设置表单元素为必填项 |
requiredposition | xhtml | String | 设置必填标记(默认为*)相对于 label 元素的位置,可选值为 left 和 right(默认) |
tabindex | simple | String | 设置表单元素的 tabindex 属性 |
表单标签的 name 和 value 属性基本等同于 HTML 组件的 name 和 value,但也有所不同:表单标签在生成 HTML 时,如果标签没有设置 value 属性,则会从值栈中按照 name 获取相应的值,并把这个值设置成 HTML 组件的 value。
1.<s:form>作用:和from表单差不多
属性名 | 是否必填 | 类 型 | 说 明 |
---|---|---|---|
action | 否 | String | 指定提交时对应的 action,不需要 action 后缀 |
enctype | 否 | String | HTML 表单 enctype 属性 |
method | 否 | String | HTML 表单 method 属性 |
namespace | 否 | String | 所提交 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 中的标签。具体参数:
属性名 | 是否必填 | 类 型 | 说 明 |
---|---|---|---|
list | 是 | Collection,Map Enmumeration,Iterator,Array | 用于生成单选框中的集合 |
listKey | 否 | String | 指定集合对象中的哪个属性作为选项的 value |
listValue | 否 | String | 指定集合对象中的哪个属性作为选项的内容 |
5.<s:reset>标签作用:创建一个重置按钮,会生成 HTML 中的标签,该标签的使用比较简单,其常用属性为 name 和 value。参数:
<s:reset value="reset"/>
<s:reset name="reset" value="重置"/>
6.<s:submit>标签作用:产生一个提交框的按钮。
属性名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
action | 否 | String | 指定提交时对应的 Action |
method | 否 | String | 指定 Action 中调用的方法 |
7.<s:checkboxlist>作用:一次性创建多个复选框,用户可以选择创建零到多个复选框,它可以产生一组标签 常见属性:
属性名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
name | 否 | String | 指定该元素的 name |
label | 否 | String | 指定复选框前显示的文本 |
list | 是 | list | 定义集合变量 |
listKey | 否 | String | 指定集合对象中的哪个属性作为选项的 value |
listValue | 否 | String | 指定集合对象中的哪个属性作为选项的内容 |
8.<s:select>作用:创建一个下拉列表框,它会生成 HTML 中的标签
属性名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
name | 否 | String | 指定表单元素名 |
accept | 否 | String | 指定可接收的文件 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 的全称是“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