zoukankan      html  css  js  c++  java
  • SSH案例--入门级

    1.项目功能展示

    (1)注册

      

    (2)修改地址与级别信息,点击修改

       

    (3)再添加一位成员,进行删除

    点击第二行的删除

    (4)登录模块测试

    输入数据库中没有的信息:

    输入数据库中存在的信息:

      

    2. Web.xml

      Spring提供了ContextLoaderListener,该监听器实现了ServletContextListener接口,他在Web应用程序启动时被触发。当他创建时会自动查找WEB-INF/下的applicationContext.xml,所以当只有一个配置文件且文件名为applicationContext.xml时,则只需要在web.xml文件中配置ContextLoaderListener监听器即可.当有多个配置文件需要载入,则应该使用<context-param>元素指定配置文件的文件名,ContextLoaderListener加载时,会查找名为contextConfigLocation的初始化参数。当Web应用程序启动时先读取web.xml文件,然后创建spring容器,之后根据配置文件内容,装配Bean实例。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
      <display-name>ssh</display-name>
      <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>
      
      
     <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/applicationContext.xml</param-value>
      </context-param>
    
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
    </web-app>
    View Code

    3. 实体类与其映射文件

    (1)Member.java

    package com.entity;
    
    public class Member {
        private long id;
        private String name;
        private String password;
        private String address;
        private String email;
        private int level;
        public Member(){}
        public Member(String name,String password,String address,String email,int level){
            this.name = name;
            this.password = password;
            this.address = address;
            this.email = email;
            this.level = level;
        }
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        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 getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
        public int getLevel() {
            return level;
        }
        public void setLevel(int level) {
            this.level = level;
        }
        
    }
    View Code

    (2)Member.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.entity.Member" table="MEMBER">
            <id name="id" type="long">
                <column name="ID" />
                <generator class="identity" />
            </id>
            <property name="name" type="java.lang.String">
                <column name="NAME" />
            </property>
            <property name="password" type="java.lang.String">
                <column name="PASSWORD" />
            </property>
            <property name="address" type="java.lang.String">
                <column name="ADDRESS" />
            </property>
            <property name="email" type="java.lang.String">
                <column name="EMAIL" />
            </property>
            <property name="level" type="int">
                <column name="LEVEL" />
            </property>
        </class>
    </hibernate-mapping>
    View Code

    4.DAO层

    (1)接口MemberDAO.java

    package com.dao;
    
    import java.util.List;
    
    import com.entity.Member;
    
    public interface MemberDAO {
        public void add(Member member);
        public void update(Member member);
        public void delete(long id);
        public Member findByName(String name,String password);
        public Member findById(long id);
        public List<Member> findAll();
    
    }
    View Code

    (2)实现类MemberDAOImpl.java(sessionFactory通过构造方法注入,使其可以操作数据库)

    package com.dao;
    
    import java.util.List;
    
    import com.entity.Member;
    import org.hibernate.*;
    import org.springframework.beans.factory.annotation.Autowired;
    public class MemberDAOImpl implements MemberDAO {
        
        private SessionFactory sessionFactory;
        
        //构造方法注入SessionFactory对象
        public MemberDAOImpl(SessionFactory sessionFactory) {
            this.sessionFactory=sessionFactory;
        }
        
        //使用SessionFactory对象返回Session对象
        public Session currentSession(){
            return sessionFactory.openSession();
        }
        @Override
        public void add(Member member) {
            Session session=null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                session.save(member);
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
    
        }
    
        @Override
        public void update(Member member) {
            Session session=null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                session.update(member);
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
    
        }
    
        @Override
        public void delete(long id) {
            Session session=null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                Member mb = (Member)session.get(Member.class, id);
                session.delete(mb);
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
    
        }
    
        @Override
        public Member findByName(String name, String password) {
            Session session=null;
            Member result = null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                String hsql = " from Member m where m.name = :mname and m.password = :mpassword";
                Query query = session.createQuery(hsql);
                query.setParameter("mname", name);
                query.setParameter("mpassword", password);
                result = (Member)query.uniqueResult();
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
            return result;
        }
    
        @Override
        public Member findById(long id) {
            Session session=null;
            Member result = null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                String hsql = " from Member m where m.id = :id";
                Query query = session.createQuery(hsql);
                query.setParameter("id",id);
                result = (Member)query.uniqueResult();
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
            return result;
        }
    
        @Override
        public List<Member> findAll() {
            Session session=null;
            List<Member> list = null;
            try {
                session=currentSession();
                Transaction tx = session.beginTransaction();
                String hsql = " from Member";
                Query query = session.createQuery(hsql);
                list = query.list();
                tx.commit();
            } catch (HibernateException e) {
                e.printStackTrace();
            }finally{
                session.close();
            }
            return list;
        }
    
    }
    View Code

    5.业务逻辑层

    (1)接口MemberService.java

    package com.service;
    import java.util.List;
    import com.entity.Member;
    public interface MemberService {
        public void add(Member member);
        public void update(Member member);
        public void delete(long id);
        public Member findByName(String name,String password);
        public Member findById(long id);
        public List<Member> findAll();
    }
    View Code

    (2)实现类MemberServiceImpl.java(设值注入DAO层组件)

    package com.service;
    
    import java.util.List;
    
    import com.dao.MemberDAO;
    import com.entity.Member;
    
    public class MemberServiceImpl implements MemberService {
        private MemberDAO memberDao;
        //设值注入DAO对象
        public void setMemberDao(MemberDAO memberDao) {
            this.memberDao = memberDao;
        }
    
        @Override
        public void add(Member member) {
            if(memberDao.findById(member.getId())==null)
                memberDao.add(member);
    
        }
    
        @Override
        public void update(Member member) {
            if(memberDao.findById(member.getId())!=null)
                memberDao.update(member);
    
        }
    
        @Override
        public void delete(long id) {
            if(memberDao.findById(id)!=null)
                memberDao.delete(id);
    
        }
    
        @Override
        public Member findByName(String name, String password) {
            return memberDao.findByName(name, password);
        }
    
        @Override
        public Member findById(long id) {
            return memberDao.findById(id);
        }
    
        @Override
        public List<Member> findAll() {
            return memberDao.findAll();
        }
    
    }
    View Code

    6. Action类

    (1)注册MemberRegisterAction.java(设值注入业务逻辑组件)

    package com.action;
    
    import com.entity.Member;
    import com.opensymphony.xwork2.ActionSupport;
    import com.service.MemberService;
    
    public class MemberRegisterAction extends ActionSupport {
        private Member member;
        private MemberService memberService;
        public Member getMember() {
            return member;
        }
        public void setMember(Member member) {
            this.member = member;
        }
        //注入业务逻辑组件
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
        public String execute(){
            memberService.add(member);
            return SUCCESS;
        }
        
    }
    View Code

    (2)删除MemberDeleteAction.java(设置注入业务逻辑组件,注意传入参数id的相应getter和setter方法)

    package com.action;
    
    import com.opensymphony.xwork2.ActionSupport;
    import com.service.MemberService;
    
    public class MemberDeleteAction extends ActionSupport {
        private MemberService memberService;
    
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
        
        private long id;
    
    
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
    
        public String execute(){
            memberService.delete(getId());
            return SUCCESS;
        }
    }
    View Code

    (3)查询MemberQueryAction.java(用于查看所有会员信息)

    package com.action;
    
    import java.util.List;
    
    import org.apache.struts2.ServletActionContext;
    
    import com.entity.Member;
    import com.opensymphony.xwork2.ActionSupport;
    import com.service.MemberService;
    
    public class MemberQueryAction extends ActionSupport {
        private MemberService memberService;
    
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
        public String execute(){
            List<Member> list = memberService.findAll();
            ServletActionContext.getRequest().setAttribute("memberList", list);
            return SUCCESS;
        }
    }
    View Code

    (4)修改MemberUpdateAction.java(有两个方法,execute()和showMember(),当需要修改时,showMember()方法转向update.jsp.并设置好需要修改的对象,修改完成之后,由spring托管的memberUpdateAction组件执行execute方法进行update操作)

    package com.action;
    
    import com.entity.Member;
    import com.opensymphony.xwork2.ActionSupport;
    import com.service.MemberService;
    
    public class MemberUpdateAction extends ActionSupport {
        private MemberService memberService;
        private Member member;
        private long id;
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
        public Member getMember() {
            return member;
        }
        public void setMember(Member member) {
            this.member = member;
        }
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public String showMember(){
            Member mb = memberService.findById(getId());
            setMember(mb);
            return SUCCESS;
        }
        public String execute(){
            memberService.update(member);
            return SUCCESS;
        }
    }
    View Code

    (5)登录MemberLoginAction.java(将输入的信息与数据库中进行比较)

    package com.action;
    
    import com.entity.Member;
    import com.opensymphony.xwork2.ActionSupport;
    import com.service.MemberService;
    
    public class MemberLoginAction extends ActionSupport {
        private Member member;
        private MemberService memberService;
        public Member getMember() {
            return member;
        }
        public void setMember(Member member) {
            this.member = member;
        }
        //注入业务逻辑组件
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
        
        public String execute(){
            Member mb =memberService.findByName(member.getName(), member.getPassword());
            if(mb!=null)
                return SUCCESS;
            else
                return ERROR;
        }
    }
    View Code

    7.struts.xml

      spring托管将Struts2中的Action的实例化工作交由Spring容器统一管理,同时使Struts2中的Action实例能够访问Spring提供的业务逻辑资源,spring容器依赖注入的优势也可以体现,Struts2提供的spring插件struts2-spring-plugin-2.3.16.3.jar配合<constant name="struts.objectFactory" value="spring">使得Struts2的action由Spring来负责进行实例化.

    <?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 name="struts.devMode" value="true" />
        
        <constant name="struts.objectFactory" value="spring"></constant>
        
        <package name="default" namespace="/" extends="struts-default">
            <!-- class属性值是spring定义的Bean,当执行execute()返回success时,控制转到另一个动作memberQuery -->
            <action name="memberRegister" class="memberRegisterAction">
                <result name="success" type="redirectAction">/memberQuery</result>
            </action>
            
            <action name="memberLogin" class="memberLoginAction">
                <result name="success">/welcome.jsp</result>
                <result name="error">/register.jsp</result>
            </action>
            
            <action name="memberQuery" class="memberQueryAction">
                <result name="success">/displayAll.jsp</result>
            </action>
            
            <action name="memberDelete" class="memberDeleteAction">
                <result name="success" type="redirectAction">/memberQuery</result>
            </action>
            
            <action name="memberShow" class="memberUpdateAction" method="showMember">
                <result name="success">/update.jsp</result>
            </action>
            
            <action name="memberUpdate" class="memberUpdateAction">
                <result name="success" type="redirectAction">/memberQuery</result>
            </action>
        </package>
    </struts>
    View Code

    8.applicationContext.xml

      spring 框架提供了多种数据源类,可以使用spring提供的DriverManagerDataSource类还可以使用第三方数据源,如C3P0的ComboPooledDataSource数据源类,注意相应的两个jar包c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar.

      Hibernate4已经完全实现自己的事物管理,所以spring4不提供HibernateDaoSupport和HibernateTemplete的支持。可以在应用程序的spring上下文中,像配置其他bean那样来配置HibernateSession工厂。如果要使用XML文件定义对象与数据库之间的映射,则需要在spring中配置LocalSessionFactoryBean。hibernateProperties属性配置了Hibernate如何进行操作的细节。"hibernate.current_session_context_class"是为当前Session提供一个策略,Session由org.springframework.orm.hibernate4.SpringSessionContext.currentSession得到。将sessionFactory注入到其他Bean中,如注入到DAO组件中,使其获得SessionFactory的引用后,就可以实现对数据库的访问。

    <?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/zzh?useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="user" value="root"/>
            <property name="password" value="root"/>
            <property name="maxPoolSize" value="40"/>
            <property name="minPoolSize" value="1"/>
            <property name="initialPoolSize" value="2"/>
            <property name="maxIdleTime" value="20"/>
        </bean>
        
        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mappingResources">
                <list>
                    <value>com/entity/Member.hbm.xml</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
                    <prop key="hibernate.current_session_context_class">
                        org.springframework.orm.hibernate4.SpringSessionContext
                    </prop>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                </props>
            </property>
        </bean>
        
        
        <bean id="memberDao" class="com.dao.MemberDAOImpl">
        <!-- 构造方法注入会话工厂组件sessionFactory -->
            <constructor-arg>
                <ref bean="sessionFactory"/>
            </constructor-arg>
        </bean>
        
        
        <bean id="memberService" class="com.service.MemberServiceImpl">
        <!-- 设值注入DAO组件 -->
            <property name="memberDao" ref="memberDao"></property>
        </bean>
        
        
        <bean id="memberRegisterAction" class="com.action.MemberRegisterAction">
        <!-- 设值注入业务逻辑组件 -->
            <property name="memberService" ref="memberService"></property>
        </bean>
        
        <bean id="memberLoginAction" class="com.action.MemberLoginAction">
            <property name="memberService" ref="memberService"></property>
        </bean>
        
        <bean id="memberQueryAction" class="com.action.MemberQueryAction">
            <property name="memberService" ref="memberService"></property>
        </bean>
        
        <bean id="memberDeleteAction" class="com.action.MemberDeleteAction">
            <property name="memberService" ref="memberService"></property>
        </bean>
        
        <bean id="memberUpdateAction" class="com.action.MemberUpdateAction">
            <property name="memberService" ref="memberService"></property>
        </bean>
    </beans>
    View Code

    9.jsp

    (1)注册register.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>会员注册页面</title>
    </head>
    <body>
        <s:form action="memberRegister" method="post">
            <h4><s:text name="欢迎注册会员"></s:text></h4>
            <s:property value="exception.message"/>
            <s:textfield name="member.name" label="会员姓名" tooltip="Enter your name!" required="true"></s:textfield>
            <s:password name="member.password" label="会员口令" tooltip="Enter your password!"></s:password>
            <s:textfield name="member.address" label="会员地址"></s:textfield>
            <s:textfield name="member.email" label="会员邮箱"></s:textfield>
            <s:textfield name="member.level" label="会员级别"></s:textfield>
            <s:submit value="提交"/>
        </s:form>
    </body>
    </html>
    View Code

    (2)所有会员信息displayAll.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>显示会员信息</title>
    </head>
    <body>
        <h4>会员信息</h4>
        <table border='1'>
            <tr>
                <td>会员id</td><td>会员名</td><td>密码</td><td>地址</td><td>邮箱</td><td>级别</td><td>删除</td><td>修改</td>
            </tr>
                <s:iterator value="#request.memberList" id="mb">
                    <tr>
                        <td><s:property value="#mb.id"/></td>
                        <td><s:property value="#mb.name"/></td>
                        <td><s:property value="#mb.password"/></td>
                        <td><s:property value="#mb.address"/></td>
                        <td><s:property value="#mb.email"/></td>
                        <td><s:property value="#mb.level"/></td>
                        
                        <td>
                            <a href="<s:url action="memberDelete"><s:param name="id"><s:property value="#mb.id"/></s:param>
                            </s:url>">删除</a>
                        </td>
                        <td>
                            <a href="<s:url action="memberShow"><s:param name="id"><s:property value="#mb.id"/></s:param>
                            </s:url>">修改</a>
                        </td>
                    </tr>
                </s:iterator>
        </table>
        <a href="register.jsp">返回注册页面</a>
    </body>
    </html>
    View Code

    (3)修改页面update.jsp

      注意:不允许修改会员id,当需要将会员id传递给更新会员动作,所以使用隐藏表单域标签来接收显示会员页面传递来的会员id在update.jsp页面提交时再传递给更新会员的动作memberUpdate。

    <%@ 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>
        <s:form action="memberUpdate" method="post">
            <h4><s:text name="修改会员信息"></s:text></h4>
            <s:actionerror/>
            
            <s:hidden name="member.id" value="%{member.id}"></s:hidden>
            <s:textfield name="member.name" label="会员姓名" required="true"></s:textfield>
            <s:textfield name="member.password" label="会员口令"></s:textfield>
            <s:textfield name="member.address" label="会员地址"></s:textfield>
            <s:textfield name="member.email" label="会员邮箱"></s:textfield>
            <s:textfield name="member.level" label="会员级别"></s:textfield>
            <s:submit value="提交"/>
        </s:form>
    </body>
    </html>
    View Code

    (4)登录login.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>会员登录</title>
    </head>
    <body>
        <s:form action="memberLogin" method="post">
            <s:textfield name="member.name" label="会员姓名"></s:textfield>
            <s:password name="member.password" label="会员口令"></s:password>
            <s:submit value="提交"></s:submit>
        </s:form>
    </body>
    </html>
    View Code

    (5)welcome.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!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>
        合法成员
    </body>
    </html>
    View Code

    10. END

      github地址:(https://github.com/byzhaozihan/s2sh_entry-level)

      本篇案例算是最简单的ssh整合,注入形式也都一目了然,如果对你有帮助,请点赞或关注我,谢谢观看!

  • 相关阅读:
    POJ 3672 水题......
    POJ 3279 枚举?
    STL
    241. Different Ways to Add Parentheses
    282. Expression Add Operators
    169. Majority Element
    Weekly Contest 121
    927. Three Equal Parts
    910. Smallest Range II
    921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/zhaozihan/p/5893785.html
Copyright © 2011-2022 走看看