SSH随手记

SSH是Spring + Struts + Hibernate,Struts是对Servlet的一个封装,通过配置文件来达到对Web请求做处理;SpringMVC是对系统的设计,使用轻量级、最小侵入的原则,通过配置文件使得程序员可以更专注逻辑/业务处理;Hibernate是对jdbc的优化处理,可以使用Hibernate直接操作bean,使用hibernate中的Session来操作数据库,支持事务处理。

Struts

一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。

主要配置struts.xml

<package name="default" namespace="" extends="struts-default">
  <action name="action" class="com.test.demo.Action" method="sayHello">
    <result name="success" value="">some.jsp</result>
  </action>
</package>

注解方式:

@ParentPackage("struts-default")// 与package中的extends功能一样
@Namespace("/user")// package中的namespace一样,指定上级请求
public class UserAction extends ActionSupport implements ServletRequestAware, ServletResponseAware {
    
    private static final long serialVersionUID = 1L;
    private HttpServletRequest req;
    private HttpServletResponse resp;
    
    @Action("/login")
    public void login() throws Exception { // do login }
}

上面的示例代码中有实现 ServletRequestAware 和 ServletResponseAware 接口,这两个接口可以让我们获取到对应的 HttpServletRequest、HttpServletResponse 。

获取其参数也可以通过Context:

ServletActionContext.getRequest();
ServletActionContext.getServletContext();
ServletActionContext.getContext().getParameters();

需要注意的是获取post中的JSON数据时需要通过流的形式读取,我这里使用的是 BufferedReader 读取其字符,并相应解码:

    private String parseReq() throws IOException {
        BufferedReader br = this.request.getReader();
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null) {
            sb.append(line);
        }
        JSONObject json = JSON.parseObject(sb.toString());
        return json.toJSONString();
    }

Struts也可以实现输入验证及国际化,具体的请百度。可能listener这个配置我们开发中会用到,可以用来实现在线人数的统计,通过实现 HttpSessionListener  来监听

// 会话被创建
default public void sessionCreated(HttpSessionEvent se) {}
// 会话被销毁
default public void sessionDestroyed(HttpSessionEvent se) {}

如果需要实现其他的功能,可以设置其他的Listener,并获取相应的数据,这里就不说了。

Hibernate

1、配置文件:配置一些数据库需要的基本数据,数据库引擎、url、driver、用户名、密码等基本配置,还有就是hibernate的参数配置,能使性能更佳。

2、创建持久化对象

public class Bean {
  private int userId;
private String name; // ...... }

使用hibernate应该使用xml配置,获取对应文件的获取,文档上介绍的是xml获取效率更高

<hibernate-mapping>
    <class name="com.test.user.User" table="USER">
        <id name="userId" type="int">
            <column name="USERID" />
            <generator class="increment" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
    </class>
</hibernate-mapping>

3、获取Configuration  new StandardServiceRegistryBuilder().configure() 

4、获取SessionFactory

    private static void getSessionFactory() {
        final StandardServiceRegistry sr = new StandardServiceRegistryBuilder().configure().build();
        try {
            sf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
        } catch (Exception e) {
            e.printStackTrace();
            StandardServiceRegistryBuilder.destroy(sr);
        }
    }

5、获取Session接口操作数据库  

getSessionFactory();
s = sf.openSession();
session.set(s);

6、获取事务接口Transaction 

session.beginTransaction();
// some operations ;
transaction.commit()

7、通过 session.createQuery("HQL"); session.createSQLQuery("原生的sql语句"); 获取Query实例

关于HQL语句

与原生SQL类似, from、select、where以及其他的运算符 ,HQL可以直接使用对象进行操作。Hibernate中的映射关系需要注意,

有一对一双/单向、一对多单/双、多对多单/双向的配置问题,下面是一对一双向的配置示例:

<!-- Person.hbm.xml -->
<
hibernate-mapping> <class name="Person" table="PERSON" lazy="true"> <id name="id" type="int"><column name="ID"/><generator class="native"/></id> <property name="name"/> <one-to-one name="idCard" class="IdCard" fetch="join" cascade="all"></one-to-one> </class> </hibernate-mapping>
<!-- IdCard.hbm.xml --> <hibernate-mapping> <calss name="IdCard" table="ID_CARD" lazy="true"> <id name="id" type="int"> <column name="ID"/> <!-- 引用person的主键作为IdCard的主键和外健 --> <generator class="foreign"> <param name="property">person</param> </generator> <id> <property name="cardNo"/> <!-- 表示IdCard引用了person的主键作为了外健 --> <one-to-one name="person" class="Person" constrained="true"></one-to-one> </class> </hibernate-mapping>

其相应的Java类

public class Person {
    private IdCard idCard;
    private String name;
    private int id;
    // get setter....
}

public class IdCard {
    private Person person;
    private String cardNo;
    private int id;
    // get setter....
}

Spring

IoC/DI

控制反转/依赖注入,简单来说就是由一个类(也就是Context)去创建bean对象,然后通过注入的方式产生使用类对bean的引用,bean的生命周期由Context控制。

示例:

class ADemo { public void methodA() { //...... } }
class BDemo { public void methodB() { //...... } }

如果在ADemo中需要使用到BDemo对象,那么我们可以使用Context创建,就跟main函数一样:

class ADemo {
    private BDemo b;
    public void setB(BDemo b) { this.b = b; }
    public void methodA() { b.methodB(); //...... }
}

class BDemo {
    public void methodB() { //...... }
}

class ExampleContext {
    public static void main(String[] args) {
        ADemo a = new ADemo();
        BDemo b = new BDemo();
        // 将b注入到使用者a中,这样a只对b产生了引用,并没有实际拥有
        // 一般想到的方法是向a中声明一个属性,然后通过set方法注入
        a.setB(b);
    }
}

当然也是可以使用构造器注入,接口注入(其实相当于方法注入)等等,最主要的思想是将a对b的一个强引用变成弱引用,使得使用者无需考虑其声明周期及内存管理问题,同时还能将这个对象复用,减少多个重复对象的创建。

在Spring中通过 AnnotationConfigApplicationContext  ClassPathXmlApplicationContext 读取相关的配置,利用Java的反射机制获取相关类并创建实例对象,在需要的时候注入到相关的类中。

AOP

AOP为Aspect Oriented Programming的缩写,面向切面编程,在不改动原来代码情况下插入需要执行的代码,可以很好的处理日志打印。简单的理解就是在指定的规则下筛选出符合规定的方法,aop有before、after、around,可以在方法之前、之后、环绕的时候织入代码。说到织入代码,分为两种:静态织入、动态织入,静态织入是需要借助 execution 表达式,表达式的格式为:

execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
// 比如:
@Before("execution(* com.demo.aop.BDemo.methodB(..))")
    public void methodA(JoinPoint jp) {
    // do something
}

动态织入我理解为做标记,由Spring容器发现需要织入的PointCut,首先需要定义一个注解,这个注解就是一个标记符,在告诉Spring 这是一个标记

// 只能方法使用
@Target(ElementType.METHOD)
// 运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface ExampleAop {
    String name();
}

定义好了标记之后,就需要指定方法需要被关注,直接使用@ExampleAop("some info")来标记

@ExampleAop(name="注解式拦截的methodA")
public void methodA() {
    // do something
}

做完这些之后,我们需要对这个标记附上意义,就犹如你定义一个“œ”操作符,如果你没规定这个符号代表什么,也就无法使用它,就像我们使用“+”表示两个数的相加一样,那么我们将ExampleAop作为一个筛选的规则,所有打上这个标记的方法都需要执行某段代码。如:

    // 注解式拦截
    @Pointcut("@annotation(com.demo.aop.ExampleAop)")
    public void annotionPointcut() {}    
    
    @Before("annotionPointcut()")
    public void methodBefore(JoinPoint jp) {
        System.out.println("上帝啊,竟然在一个切面里添加多个Before,使用不同的方式拦截");
    }

所有由标记的方法都会在执行前加上一句打印。

在Spring MVC中,如果我们使这些打印实现的话,还需要配置文件,这里我贴上代码,就不详细介绍了

@Configuration
@ComponentScan("com.demo.aop")
@EnableAspectJAutoProxy// 开启对AspectJ代理的支持
public class ConfigAop {

}

需要了解更多的可以阅读相关文档(Spring家族文档)

由于是接触不久,很多地方无法详细展开,希望能与大家一起探讨。

写在最后

以前觉得SSH项目太难搭建,在学习的过程中不断的摸索,走过不少的弯路,很多的概念都是模糊的,现在想起来这些弯路给了我不少的经验,至少让我明白,知识是一点点攻破的,从Servlet到Struts,再到Spring MVC,兼顾JDBC、MySQL、Hibernate,了解了技术的不断进步,编程思想的不断成熟,看到不少大神们的不断努力,也明白其实编程就是一种思想,不同的语言有着不同的规则/思想,只是为了更加的方便解决问题,组织起相应的功能。

猜你喜欢

转载自www.cnblogs.com/meilj/p/9563784.html