【斗医】【4】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qingkechina.blog.51cto.com/5552198/1315778

在上面把日志文件打印到了D:\log下,考虑到Liunx服务器环境下,让最终用户修改可能不可接受,接下来完成三件事情:(1)应用程序指定输出路径(2)完善异常类的处理(3)完成页面跳转的封装处理

一、指定输出路径

由于Logback的<FILE>指定相对路径与Log4J存在差异,所以在修改日志输出路径之前,得让Eclipse能调试代码。

1、在http://www.eclipsetotale.com/tomcatPlugin.html#A3下载Tomcat插件,下载时确认自已的JDK、Eclipse、Tomcat与该插件是否配套。我曾见同事使用的插件不配套,导致Eclipse不能启动Tomcat

2、假如Eclipse的路径为%Eclipse%,在%Eclipse%下新建links\tomcatplugin\features和links\tomcatplugin\plugins文件夹,把下载的插件解压到links\tomcatplugin\plugins下,其目录结构如图:

3、在%eclipse%\links\下创建tomcat.ini文件,填写如下内容:

path=D:\\eclipse\\links\\tomcatplugin

其中D:\\eclipse即为%eclipse%,读者视自己环境更改。

4、若Eclipse打开则请关闭,然后删除%eclipse%\configuration\org.eclipse.update目录,重启Eclipse后应该在工具栏上看到小猫咪的图标,表明加载成功:

5、在Eclipse配置Tomcat。依次选择“Window > Preferences > Tomcat”,其中“Tomcat Version”选择“Version 7.x”,“Tomcat home”选择Tomcat放置路径。在前面说过我把Tomcat放置到了D盘下,如图:

6、确认后点击小猫咪图标,应该能看到Tomcat在Eclisps的启动信息了

接下来我们要修改logconfig.xml中的日志输出路径了。由于要修改XML,所以我们创建一个FrameXmlUtil.java类,该类用于解析XML内容、读取结点的属性集合、保存XML内容等。

1、创建FrameXmlUtil,由于涉及代码较多这里只粘贴出代码构造,具体代码见附件。读者也可以自已写此工具类:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

public class FrameXmlUtil

{

    /**

     * XML文档

     */

    private Document xmlDocument = null;

    /**

     * XML的根元素

     */

    private Element rootElement = null;                                                                                                                                  

    /**

     * 读取XML文件

     */

    public void readXmlFile(String filePath) throws FrameException

    {

        // 这里省略,具体见附件

    }                                                                                                                                                            

    /**

     * 获取结点属性集合

     */

    public Map<String, String> getAttrs(Node node)

    {

         // 这里省略,具体见附件

    }                                                                                                                                                           

    /**

     * 保存XML

     */

    public void saveXML() throws FrameException

    {

         // 这里省略,具体见附件

    }                                                                                                                                                             

    /**

     * 获取XML根元素

     */

    public Element getRootElement()

    {

        return rootElement;

    }

}



【备注】:关注解析XML在JAVA开发中有多种不同的解析方法,感兴趣的话可以在谷歌上搜索一下,有很多人写过这方面的贴子


2、 对FrameConfigUtil增加静态工厂方法modifyLogOutPath(),对D:\medical\war\etc\logconfig.xml中的<property name="LOG_HOME" value="D:\logs" />进行修改:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

/**

 * 修改D:/medical/war/etc/logconfig.xml文件中的日志输出路径

 */

public static void modifyLogOutPath(ServletContext context) throws FrameException

{

    String webPath = context.getRealPath("/");

    StringBuilder filePath = new StringBuilder(webPath);

    filePath.append(File.separator).append("etc");

    filePath.append(File.separator).append("logconfig.xml");

                                                                              

    // 载入D:\medical\war\etc\logconfig.xml文件

    FrameXmlUtil xmlUtil = new FrameXmlUtil();

    xmlUtil.readXmlFile(filePath.toString());                                                                             

    // 初步判断文件的合法性

    Element rootElement = xmlUtil.getRootElement();

    if (rootElement == null)

    {

        return;

    }                                                                                                                                                                   

    // 由logconfig.xml知日志输出路径宏定义就在根结点下,所以此处遍历根结点的孩子

    NodeList childNodeList = rootElement.getChildNodes();

    for (int index = 0; index < childNodeList.getLength(); index++)

    {

        Node childNode = childNodeList.item(index);

        if (Node.ELEMENT_NODE != childNode.getNodeType())

        {

            continue;

        }

                                                                                     

        // 判断孩子结点是否为<property name="LOG_HOME" value="D:\logs" />

        Element childElement = (Element) childNode;

        String elementName = childElement.getNodeName();

        String logHome = childElement.getAttribute("name");

        if (FrameConstant.LOG_PROPERTY.equals(elementName) && FrameConstant.LOG_HOME.equals(logHome))

        {

            StringBuilder path = new StringBuilder(webPath);                      path.append(File.separator).append("var").append(File.separator).append("logs");                          childElement.setAttribute(FrameConstant.LOG_VALUE, path.toString());

            break;

         }

    }                                                                                                                                                             

    // 保存修改后的XML文件

    xmlUtil.saveXML();

}

3、若使用logback则在加载logconfig.xml之后调用FrameConfigUtil.modifyLogOutPath()方法,所以修改FrameLauncher的init()方法,修改后如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

@Override

public void init() throws ServletException

{

    ServletContext context = getServletContext();

    try

    {

        FrameConfigUtil.modifyLogOutPath(context);

        FrameConfigUtil.initLogConfig(context);

    }

    catch (FrameException e)

    {

        throw new ServletException("[FrameLauncher] init error.", e);

    }

}

好了,在Eclipse中点击小猫咪图标启动Tomcat服务,在浏览器中输入http://localhost:8080/medical,理论上应该在D:\medical\war\var\logs下生成日志文件,但理想与现实之间往往存在差距。这是什么原因呢?细心观察在Tomcat目录下多出一个medicalwarvarlogs文件夹,里面的日志文件正是我们想要的!!

这说明什么?

说明我们修改logconfig.xml之后的<property name="LOG_HOME" value="D:\medical\war\var\logs"/>存在问题。

那是什么问题呢?想想什么是转义字符?\n是什么?\b是什么?明白了吧:value="D:\medical\war\var\logs"是错误的,应该对\再进行转义。修改FrameConfigUtil.modifyLogOutPath()方法中输出路径代码处增加如下处理:


1

String realPath = path.toString().replaceAll("\\\\""/");              childElement.setAttribute(FrameConstant.LOG_VALUE, realPath);

再重启Tomcat服务,在浏览器中输入http://localhost:8080/medical,点击下图所示的超链接,此时会发现日志文件能按您的预期输出了。

二、完善异常类

在上面日志文件输出搞定之后,让我们回到第二天的异常类封装问题上,当时说异常的描述应该从中英文资源中读取,随着我们的想法自然地前行吧。

1、在D:\medical\war\etc\下新建local文件夹,然后在local下分别创建en、zh文件夹,再在en、zh下分别创建resource.properties文件,其目录结构如下:

2、向resource.properties中填写信息,由于我们这个斗医系统是给中国人看的,外国人不懂中医是什么,所以只填写zh下的resource.properties内容即可。这里暂时把前面所涉及的错误码填写上:

#UTF-8

1=创建XML生成器时异常

5=SAX解析XML文件时异常

10=解析XML时出现IO异常

15=解析XML时参数设置异常

20=生成XML翻译器失败

25=翻译XML失败

100=HTTP请求动作跳转异常

3、考虑到异常信息只要从一个地方读取,这里新建一个FrameCache.java文件,专门用于缓存全局数据


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

public class FrameCache

{

    private static FrameCache instance = new FrameCache();                                                                                                    

    /**

     * 全局资源文件缓存

     */

    private Properties resourceProp = new Properties();

                     

    private FrameCache()

    {

    }

                                                            

    public static FrameCache getInstance()

    {

        return instance;

    }                                                                                                                                                     

    public void setResourceProp(Properties resourceProp)

    {

        this.resourceProp = resourceProp;

    }                                                                                                                                                    

    public String getResourceValue(String resourceKey)

    {

        return resourceProp.getProperty(resourceKey, resourceKey);

    }

}

4、在Servlet加载时需要把这些资源信息读入内存,这样才能根据错误码读取到异常描述信息,所以需要

(1)在FrameConfigUtil中定义loadResource(),用于加载Properties文件


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public static void loadResource(ServletContext context) throws FrameException

{

    // 获取中文资源文件路径

    StringBuilder resourcePath = new StringBuilder(context.getRealPath("/"));

        resourcePath.append(File.separator).append("etc").append(File.separator).append("local");

        resourcePath.append(File.separator).append("zh").append(File.separator).append("resource.properties");

                                                                                                            

    // 具体加载动作

    Properties resourceProp = new Properties();

    try

    {

        InputStream in new BufferedInputStream(new FileInputStream(resourcePath.toString()));

        resourceProp.load(in); 

    }

    catch (IOException e)

    {

        throw new FrameException(FrameErrorCode.Prop_ERROR_LOAD, e);

    }                                                                                                

    // 设置到全局缓存中

    FrameCache.getInstance().setResourceProp(resourceProp);

}

(2)在FrameLauncher的init()方法中调用loadResource()方法


1

2

3

4

5

6

7

8

9

10

11

12

13

ServletContext context = getServletContext();

try

{

    // 加载logback配置

    FrameConfigUtil.modifyLogOutPath(context);

    FrameConfigUtil.initLogConfig(context);                                                                   

    // 加载中文资源配置

    FrameConfigUtil.loadResource(context);

}

catch (FrameException e)

{

    throw new ServletException("[FrameLauncher] init error.", e);

}

5、为了测试,我们在FrameLauncher.doGet()方法中打印一句话


1

System.out.println(FrameCache.getInstance().getResourceValue("1"));

6、在Eclipse中启动Tomcat服务,在浏览器中输入http://localhost:8080/medical,点击“Test Logback”超链接,可以看到有类似如下输出:



【备注】:这里的乱码是由于字符的编码问题,在此处我们只要能加载即可,具体的可读性遗留到后面界面展示时处理。


7、完善FrameException读取异常描述的遗留,把原来标注“// errorDesc应该从中英文资源文件中根据errorCode读取”的地方,使用errorDesc = FrameCache.getInstance().getResourceValue(String.valueOf(errorCode));代替。

三、页面跳转封装

接下来我们做一件系统较为重要的事情:页面跳转封装。比如在系统导航菜单上点击了“话题”菜单项,那么希望系统能进入“话题”页面,站在纯HTML角度来看只需要<a>标签即可,但有时候还需要处理一些逻辑,所以此封装还是较有意义的。封装之后的XML类似如下:


1

2

3

4

5

6

<business name="topic" mustlogin="false" business-class="com.medical.FrameTopic">

    <forward>

        <path name="success"  path="/module/topic.html" />

        <path name="failure"  path="/module/topic.html" />

    </forward>

</business>

从这个XML上很容易看出,这个业务是进入topic页面,在进入之前用户可以不登录,同时进入页面之前的逻辑部分由FrameTopic处理,无论处理结果如何都最终进入topic.html。下面封装FrameBusiness类来对应这个业务实体:

1、创建com.medical.frame.config.FrameForward类,它包括successPath(成功时跳转路径)、failurePath(失败时跳转路径),然后再对外提供get和set方法


1

2

3

4

5

6

7

8

9

10

11

12

public class FrameForward

{

    /**

     * 成功跳转路径

     */

    private String successPath = null;                                                                    

    /**

     * 失败跳转路径

     */

    private String failurePath = null;

                                                                                             // 省略相关的get&set方法 

}

2、创建com.medical.frame.config.FrameBusiness类,里面有name、mustLogin、businessClass和FrameForward对象,然后再对外提供get和set方法


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public class FrameBusiness

{

    /**

     * 业务名称

     */

    private String name = null;                                                               

    /**

     * 是否必须登录

     */

    private boolean mustLogin = false;                                                      

    /**

     * 业务逻辑处理类

     */

    private String businessClass = null;                                                      

    /**

     * 业务跳转路径

     */

    private FrameForward forward = null;

                                                                                             // 省略相关的get&set方法

}

3、假如系统有多个业务,我们不希望所有业务的配置都放到一个XML,同时不同业务的XML又希望按业务文件夹放置,如下:

(1)在运行环境D:\medical\war\WEB-INF下创建config文件夹

(2)在config下创建sm和test两个文件夹

(3)在sm和test下分别创建system-action.xml和test-action.xml

(4)在system-action.xml中填充如下内容:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<?xml version="1.0" encoding="UTF-8"?>

<business-config>

    <business name="index" mustlogin="false">

        <forward>

            <path name="success"  path="/main.html"/>     

            <path name="failure"  path="/main.html"/>

        </forward>

    </business>

    <business name="login" mustlogin="">

        <forward>

            <path name="success"  path="/login.html"/>        

            <path name="failure"  path="/login.html"/>

        </forward>

    </business>

</business-config>



【备注】:后面若无特殊说明,文件均以UTF-8编码



(5)的test-action.xml中填充如下内容:


1

2

3

4

5

6

7

8

9

<?xml version="1.0" encoding="UTF-8"?>

<business-config>

    <business name="test" mustlogin="true" business-class="com.medical.frame.Demo">

        <forward>

            <path name="success"  path="/main.html"/>      

            <path name="failure"  path="/main.html"/>

        </forward>

    </business>

</business-config>

4、前面说过action这个Servlet,现在我们希望该Servlet在启动时把上面的业务配置文件(xxx-action.xml)里的业务配置加载到内存

(1)在FrameLauncher.init()方法中调用FrameConfigUtil.loadBusiness(),加载业务配置


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public void init() throws ServletException

{

    ServletContext context = getServletContext();

    try

    {

        // 加载logback配置

        FrameConfigUtil.modifyLogOutPath(context);

        FrameConfigUtil.initLogConfig(context);                                           

        // 加载中文资源配置

        FrameConfigUtil.loadResource(context);                                              

        // 加载业务配置文件

        FrameConfigUtil.loadBusiness(context);

    }

    catch (FrameException e)

    {

        throw new ServletException("[FrameLauncher] init error.", e);

    }

}

(2)在FrameConfigUtil中定义一个公共静态方法loadBusiness(),用于加载D:\medical\war\WEB-INF\config下的所有业务配置


1

2

3

4

5

public static void loadBusiness(ServletContext context) throws FrameException

{

    findActFile(context, "/WEB-INF/config");

    parseBusiness(context);

}

(3)上面的loadBusiness()方法中的findActFile()作用是查找出"/WEB-INF/config"下的所有以-action.xml结尾的文件,并把文件名保存到全局缓存中

I、在FrameCache中定义文件集合,并提供get()/add()方法


1

2

3

4

5

6

7

8

9

10

11

12

/**

 * 系统业务配置文件路径集合

 */

private Set<String> busActFileSet = new HashSet<String>();

public Set<String> getBusinessActFile()

{

    return busActFileSet;

}                                                                                                                              

public void addBusinessActFile(String businessActFile)

{

    this.busActFileSet.add(businessActFile);

}

II、在FrameConfigUtil.findActFile()中查找-action.xml文件,并保存在全局缓存中


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

private static void findActFile(ServletContext context, String path)

{

    Set<String> businessSet = context.getResourcePaths(path);

    if (businessSet == null)

    {

        return;

    }

    for (String item : businessSet)

    {

        if (item == null)

        {

            continue;

        }

        if (item.endsWith(FrameConstant.BUS_CONF_POSTFIX))

        {

            FrameCache.getInstance().addBusinessActFile(item);

        }

        else

        {

            findActFile(context, item);

        }

    }

}

(4)FrameConfigUtil.parseBusiness()是真正的解析过程,也是本文的重点,所以请读者重点关注。下面把其逻辑分别列举出:

I、从全局缓存中读取XXX-action.xml文件集合,判断是否为空,若为空则返回


1

2

3

4

5

Set<String> actionFileSet = FrameCache.getInstance().getBusinessActFile();

if (actionFileSet == null || actionFileSet.isEmpty())

{

    return;

}

II、若集合不为空,则把XXX-action.xml文件用FrameXMlUtil工具解析


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// 遍历XXX-action.xml文件

for (String fileName : actionFileSet)

{

    InputSource in = null;

    try

    {

        URL url = context.getResource(fileName);

        in = new InputSource(url.toExternalForm());

    }

    catch (MalformedURLException e)

    {

        throw new FrameException(FrameErrorCode.XML_ERROR_GET_PATH);

    }

    try

    {

        FrameXmlUtil xmlUtil = new FrameXmlUtil();

        xmlUtil.readXmlFile(in);

        //.......

    }

    catch (FrameException e)

    {

        throw e;

    }

}

III、真正解析结点形成FrameBusiness对象,并缓存到全局变量中


1

2

3

4

5

6

7

8

9

10

11

12

13

14

FrameCache.java部分代码:

/**

 * 系统配置业务

 */

private Map<String, FrameBusiness> businessMap = new HashMap<String, FrameBusiness>();

public FrameBusiness getBusiness(String businessName)

{

    return businessMap.get(businessName);

}

                                                                                         

public void addBusiness(FrameBusiness business)

{

    businessMap.put(business.getName(), business);

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

FrameConfigUtil.parseBusiness(ServletContext)部分代码:

FrameXmlUtil xmlUtil = new FrameXmlUtil();

xmlUtil.readXmlFile(in);

Element rootElement = xmlUtil.getRootElement();

NodeList busNodeList = rootElement.getElementsByTagName(FrameConstant.BUS_KEY);

if (busNodeList == null || busNodeList.getLength() == 0)

{

    continue;

}

// 开始解析

for (int i = 0; i < busNodeList.getLength(); i++)

{

    Node busNode = busNodeList.item(i);

    Map<String, String> busNodeAttributs = xmlUtil.getAttrs(busNode);

    FrameBusiness business = new FrameBusiness();

    business.setName(busNodeAttributs.get(FrameConstant.BUS_NAME));

    business.setBusinessClass(busNodeAttributs.get(FrameConstant.BUS_CLASS));

    String mustLogin = busNodeAttributs.get(FrameConstant.BUS_MUST_LOGIN);

    mustLogin = mustLogin == null "false" : mustLogin;

    business.setMustLogin("TRUE".equalsIgnoreCase(mustLogin));

    // 解析<forward>属性

    NodeList forwardNodeList = ((Element) busNode).getElementsByTagName(FrameConstant.BUS_FORWARD);

    if (forwardNodeList == null || forwardNodeList.getLength() != 1)

    {

        continue;

    }

    Element forwardElement = (Element) forwardNodeList.item(0);

    NodeList pathNodeList = forwardElement.getElementsByTagName(FrameConstant.BUS_PATH);

    if (pathNodeList == null || pathNodeList.getLength() == 0)

    {

        continue;

    }

    FrameForward forward = new FrameForward();

    for (int j = 0; j < pathNodeList.getLength(); j++)

    {

        Node fowardNode = pathNodeList.item(j);

        Map<String, String> forwardAttrMap = xmlUtil.getAttrs(fowardNode);

        String forwardName = forwardAttrMap.get(FrameConstant.BUS_FORWARD_NAME);

        if (FrameConstant.BUS_FORWARD_SUCCESS.equals(forwardName))

        {

            forward.setSuccessPath(forwardAttrMap.get(FrameConstant.BUS_PATH));

        }

        else if (FrameConstant.BUS_FORWARD_FAILURE.equals(forwardName))

        {

            forward.setFailurePath(forwardAttrMap.get(FrameConstant.BUS_PATH));

        }

    }

    business.setForward(forward);

    // 添加到全局缓存中

    FrameCache.getInstance().addBusiness(business);

}



【备注】:上面的代码是该封装的关键代码,限于篇幅问题,这里只把较为关键的代码粘贴出,其中涉及FrameXmlUtil.readXmlFile(InputSource in)、FrameConstant接口常量值定义等都没有列出,具体可参见附件。

若读者有兴趣运行的话,强烈建议读者亲身写一下。


本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1315778

时间: 2025-01-19 12:12:17

【斗医】【4】Web应用开发20天的相关文章

【斗医】【17】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1543919     细心的读者可能已发现"Web应用开发50天"改为了"Web应用开发20天",之所以这样调整是因为当时想前20篇只讲解Web基础知识,中间10篇讲解我一直想要封装的Web框架,后20篇将该应用转换为Android应用.但由于最近女儿出生,业余时间都被她占用了,

【斗医】【7】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1330647 现在想想一下首页放置哪些内容?由于该WEB应用的聚集点在"斗"上,也就是对医术的探讨方面,个人认为应该是对展示较新的或评价较好的病症药方的展示方面.这里包含两部分:(1)数据的获取,即动态读取较好或评价较好的药方数据:(2)页面的展示,即静态页面布局和数据显示. 对于第一个问题会涉及到

【斗医】【9】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1377044 一.调试<[斗医][8]Web应用开发50天>数据表映射方法    本来想把数据库配置.Hibernate连接封装和映射配置一块写的,但由于个人时间问题时断时续,思路也多次被打断,所以在此对其进行弥补.    若读者把上篇的附件下载下来运行,会发现运行失败,下面随着异常分析并解决. 1.截止目

【斗医】【11】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1386941 本文在上文的基础上完成用户登录验证功能. 四.获取数据请求业务处理封装 1.配置数据读取方式,它的作用是使用FrameDataGainer响应以.data结尾的请求,并把处理后的数据返回给客户端.打开D:\medical\war\WEB-INF\web.xml文件,填充如下内容: 1 2 3 4

【斗医】【12】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1390410 在上文中有意埋了几个安全彩蛋,以便后面在聊网络安全时使用. 书接前言,对上文做过实践的朋友肯定会发现:当用户注册/登录成功后页面跳转到了系统首页,但首页的导航菜单并没有显示用户名.本文重点实现这个特性,同时也谈谈系统的编码问题. 六.注册/登录成功后导航菜单显示当前用户名    与JSP不同之处

【斗医】【6】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1322419 对于一个网站来讲均会存在公共页面,如异常页面.系统菜单等等,本章针对斗医系统菜单做一下介绍.可以想一想常见网站的系统菜单形式,一般都是菜单项在每个页面的内容不变,区别是菜单的选择状态不同. JSP可以使用<%@ include file="">语句把公共系统菜单页面引进来,

【斗医】【5】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1317441 三.页面跳转封装 [接上]在< 接下来要完成如下功能: Web容器(Tomcat)接受到HTTP请求后,Web容器把HTTP转换为HttpServletRequest对象,然后根据请求名称匹配规则找到相应的Servlet,调用servlet-class对应类的doGet()或doPost()方法

【斗医】【3】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1308932 在上面提及异常的中英文从资源文件中读取,若读取失败需要日志记录,所以使用网上正在闹腾的Logback来记录.关于Logback与Log4j这里不做评判和说明,所有疑问可以请教谷歌. 一.Logback的使用前期准备 1.在官网http://logback.qos.ch/download.html

【斗医】【1】Web应用开发20天

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://qingkechina.blog.51cto.com/5552198/1303925 从哪里开始呢? 还是从前段认识的朋友开始吧. 前段在圈里认识了一个朋友,当他聊到他用SSH开发了一套系统时,我思想意识中想到SSH应该是一个通讯协议,他用不可置否的语气说:大叔,你从事这一行业也这么多年了,难道不知道SSH? 说来惭愧,从事这行业时间真的不短了,好像没有真的从事过WEB方面的开发