一 空Servlet类模板

import java.io.IOException;
mport java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo1 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

}

}

二 web.xml配置

<servlet>
     <servlet-name>ServletDemo1</servlet-name>
     <servlet-class>xxx.yyy.zzz.ServletDemo1</servlet-class>
   </servlet>
 
   <servlet-mapping>
     <servlet-name>ServletDemo1</servlet-name>
     <url-pattern>/servlet/ServletDemo1</url-pattern>
   </servlet-mapping>

<servlet-mapping>
     <servlet-name>ServletDemo1</servlet-name>
     <url-pattern>/*</url-pattern>
   </servlet-mapping>

/abc/* 
/* 
/abc 
*.do

<servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。 
凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,
  <servlet>
     <servlet-name>ServletDemo2</servlet-name>
     <servlet-class>xxx.yyy.zzz.ServletDemo2</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>
   
   <!-- 将ServletDemo2配置成缺省Servlet -->
   <servlet-mapping>
     <servlet-name>ServletDemo2</servlet-name>
     <url-pattern>/</url-pattern>
   </servlet-mapping>

在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

三 Servlet的线程安全问题

  当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。

不存在线程安全问题的代码:

public class ServletDemo3 extends HttpServlet {
 
     
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         
         /**
          * i变量被多个线程并发访问,但是没有线程安全问题,因为i是doGet方法里面的局部变量,
          * 当有多个线程并发访问doGet方法时,每一个线程里面都有自己的i变量,
          * 各个线程操作的都是自己的i变量,所以不存在线程安全问题
          * 多线程并发访问某一个方法的时候,如果在方法内部定义了一些资源(变量,集合等)
          * 那么每一个线程都有这些东西,所以就不存在线程安全问题了
          */
         int i=1;
         i++;
         response.getWriter().write(i);
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

存在线程安全问题的代码:
 public class ServletDemo3 extends HttpServlet {
 
     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
        
         i++;
         try {
             Thread.sleep(1000*4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         response.getWriter().write(i+"");
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

  把i定义成全局变量,当多个线程并发访问变量i时,就会存在线程安全问题了;同时开启两个浏览器模拟并发访问同一个Servlet,本来正常来说,第一个浏览器应该看到2,而第二个浏览器应该看到3的,结果两个浏览器都看到了3。
    如何解决?

public class ServletDemo3 extends HttpServlet {
 
     int i=1;
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         /**
          * 加了synchronized后,并发访问i时就不存在线程安全问题了,
          * 假如现在有一个线程访问Servlet对象,那么它就先拿到了Servlet对象的那把锁
          * 等到它执行完之后才会把锁还给Servlet对象,由于是它先拿到了Servlet对象的那把锁,
          * 所以当有别的线程来访问这个Servlet对象时,由于锁已经被之前的线程拿走了,后面的线程只能排队等候了
          * 
          */
         synchronized (this) {//在java中,每一个对象都有一把锁,这里的this指的就是Servlet对象
             i++;
             try {
                 Thread.sleep(1000*4);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             response.getWriter().write(i+"");
         }
         
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 
 }

  现在这种做法是给Servlet对象加了一把锁,保证任何时候都只有一个线程在访问该Servlet对象里面的资源,这样就不存在线程安全问题了
    这种做法虽然解决了线程安全问题,但是编写Servlet却不能用这种方式处理线程安全问题,假如有9999个人同时访问这个Servlet,那么这9999个人必须按先后顺序排队轮流访问。

  针对Servlet的线程安全问题,Sun公司提供有解决方案的:让Servlet去实现一个SingleThreadModel接口,如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  查看Sevlet的API可以看到,SingleThreadModel接口中没有定义任何方法和常量,在Java中,把没有定义任何方法和常量的接口称之为标记接口,经常看到的一个最典型的标记接口就是"Serializable",这个接口也是没有定义任何方法和常量的,标记接口在Java中有什么用呢?主要作用就是给某个对象打上一个标志,告诉JVM,这个对象可以做什么,比如实现了"Serializable"接口的类的对象就可以被序列化,还有一个"Cloneable"接口,这个也是一个标记接口,在默认情况下,Java中的对象是不允许被克隆的,就像现实生活中的人一样,不允许克隆,但是只要实现了"Cloneable"接口,那么对象就可以被克隆了。

  让Servlet实现了SingleThreadModel接口,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。  
  对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
  实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

四 常用功能代码

1 hello world

public void init() throws ServletException
  {
      message = "Hello World";
  }

public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {

response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println("<h1>" + message + "</h1>");
  }

2 在客户端输出一个html文档

response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");
        out.print("    This is ");
        out.print(this.getClass());
        out.println(", using the GET method");
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();

3 处理用户登陆的servlet实现方法

Login.java

package com.bai;
 
import javax.servlet.http.*; 
import java.io.*;
 
public class Login extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
         try{req.setCharacterEncoding("gb2312");
         res.setContentType("text/html;charset=gb2312");
             PrintWriter pw=res.getWriter();
             pw.println("<html>");
             pw.println("<body>");
             pw.println("<h1>登陆界面</h1>");
             pw.println("<form action=logincl method=post>");
             pw.println("用户名:<input type=text name=username><br>");
             pw.println("密码:<input type=password name=passwd><br>");
             pw.println("<input type=submit value=login><br>");
             pw.println("</form>");
             pw.println("</body>");
             pw.println("</html>");
         }
         catch(Exception e){
             e.printStackTrace();
         }
     }
     
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }
 
LoginCl.java

package com.bai;
 
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
 
public class LoginCl extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
         
         Connection conn=null;
         Statement stmt=null;
         ResultSet rs=null;
         String sql = "select username,passwd from users where username = ? and passwd = ?";
         try{//req.setCharacterEncoding("gb2312");
             String user=req.getParameter("username");
             String password=req.getParameter("passwd");
             
            Class.forName("com.mysql.jdbc.Driver");
             conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/sqdb","root","root");
 //            stmt=conn.createStatement();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             pstmt.setString(1, user);
             pstmt.setString(2, password);
             rs = pstmt.executeQuery();
 //            rs=stmt.executeQuery("select top 1 * from users where username='"+user
 //                +"' and passwd='"+password+"'");
             if(rs.next())
             {
                 HttpSession hs=req.getSession(true);
                 hs.setMaxInactiveInterval(60);
                 hs.setAttribute("name",user);
                 res.sendRedirect("welcome?&uname="+user+"&upass="+password);
             }
             else{
                 res.sendRedirect("login"); //url
             }
             
        }
         catch(Exception e){
             e.printStackTrace();
         }finally{
             try{
                 if(rs!=null){
                 rs.close();
                 }
                 if(stmt!=null){
                     stmt.close();
                 }
                 if(conn!=null){
                     conn.close();
                 }    
            }catch(Exception e){
                 e.printStackTrace();
             }        
        }
     }
     
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }
 
注:
上面这个处理用户名密码带有明显注入漏洞,可以根据用户名从数据库取密码,用取出的密码和用户输入的密码比较

sql=select passwd from users where username = ?  limit 1
if(rs.next())
 {
     String passwd=rs.getString(1);
     if(passwd.equals(password))
             //密码正确
     else //密码错误
 }

Welcome.java

package com.bai;
 
import javax.servlet.http.*;
import java.io.*;
 
public class Welcome extends HttpServlet{
     public void doGet(HttpServletRequest req,HttpServletResponse res){
         
        HttpSession hs=req.getSession();
         String val=(String)hs.getAttribute("pass");
         
        if(val==null){
             try{
                 System.out.print(1);
                 res.sendRedirect("login");
             }catch(Exception e){
                 e.printStackTrace();
             }
             
        }        
            
        String u=req.getParameter("uname");
         String p=req.getParameter("upass");
         
        try{//req.setCharacterEncoding("gb2312");
             PrintWriter pw=res.getWriter();
             pw.println("welcome! "+u+"&pass="+p);
         }
         catch(Exception e){
             e.printStackTrace();
         }
     }
     
    public void doPost(HttpServletRequest req,HttpServletResponse res){
         this.doGet(req,res);
     }
 }

4 servlet中session

在servlet中,session是封装在javax.servlet.http.HttpSession这个接口中的,这个接口是构建在cookie或者URL重写的基础上,要得到一个HttpSession的实例,就可以通过HttpServletRequest的getSession()方法来获得
HttpServletRequest有两个重载的getSession()方法,一个接受一个boolean的类型的值,另一个不带任何参数,getSession()方法和getSession(true)方法功能一样,就是如果对应的客户端已经产生过一个session,那么就会返回这个旧的session,否则,这个方法将会产生一个session ID并且和对应的客户端绑定在一起,而如果getSession(false)表示如果对应的客户端已经有对应的session,那么返回这个旧的session,否则不会产生新的session。可以使用HttpSession对象上的isNow()方法来判定这个session是否为新建的
 
HttpSession常用方法
 
public void setAttribute(String name,Object value)
将value对象以name名称绑定到会话

public object getAttribute(String name)
取得name的属性值,如果属性不存在则返回null

public void removeAttribute(String name)
从会话中删除name属性,如果不存在不会执行,也不会抛处错误.

public Enumeration getAttributeNames()
返回和会话有关的枚举值

public void invalidate()
使会话失效,同时删除属性对象

public Boolean isNew()
用于检测当前客户是否为新的会话

public long getCreationTime()
返回会话创建时间

public long getLastAccessedTime()
返回在会话时间内web容器接收到客户最后发出的请求的时间

public int getMaxInactiveInterval()
返回在会话期间内客户请求的最长时间为秒

public void setMaxInactiveInterval(int seconds)
允许客户客户请求的最长时间

ServletContext getServletContext()
返回当前会话的上下文环境,ServletContext对象可以使Servlet与web容器进行通信

public String getId()
返回会话期间的识别号
 
一个保存信息到session的例子
 
sessionlogin.html

<meta name="keywords" content="keyword1,keyword2,keyword3" />
<meta name="description" content="this is my page" />
<meta name="content-type" content="text/html; charset=UTF-8" />

<!--    <link rel="stylesheet" type="text/css" href="./styles.css">--></pre>
<form action="servlet/saveinfo" method="post">
 用户名:
 <input type="text" name="username" /> <input type="submit" />
 密码:
 <input type="password" name="userpasswd" />
 </form>
<pre>
</pre>
</div>
<div>

package xxx;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class saveinfo extends HttpServlet {

public saveinfo() {
 super();
 }

public void destroy() {
 super.destroy(); // Just puts "destroy" string in log
 // Put your code here
 }

public void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

//如果用户输入过了用户名 则将其放在session中
 if(request.getParameter("username")!=null);
 {
 HttpSession session = request.getSession();
 session.setAttribute("username",request.getParameter("username"));
 }
 response.setContentType("text/html;charset=GBK");
 PrintWriter out = response.getWriter();
 out.println("session已经创建");
 out.println("
");
 out.println("跳转到其他<a>页面</a>");

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

doGet(request,response);
 }

public void init() throws ServletException {
 // Put your code here
 }

}

package xxx;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class getsession extends HttpServlet {

public getsession() {
 super();
 }

public void destroy() {
 super.destroy(); // Just puts "destroy" string in log
 // Put your code here
 }

public void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

response.setContentType("text/html;charset=GBK");
 PrintWriter out = response.getWriter();

String username = "";
 //此处不是创建session 而是去取已经创建的session
 HttpSession session = request.getSession();
 //如果已经取到,说明已经登录
 if(session!=null)
 {
 username = (String)session.getAttribute("username");
 out.println("获得创建的Session");
 out.println("
");
 out.println("登录名:"+username);
 }
 else
 {
 response.sendRedirect("../sessionlogin.html");
 }
 }

public void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request,response);
 }

public void init() throws ServletException {
 // Put your code here
 }

}

5 获得客户端IP和url

可以配合实现IP白名单控制,

import javax.servlet.http.HttpServletRequest;
 
public class ClientInfoUtil{
 
/**
* 获得客户端的IP地址
* @param request
* @return
*/
static public String getIP(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
    }
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
    }
    return ip;
}

/**
* 获得客户端访问服务器的url地址
* @param request
* @return
*/
static public String getURL(HttpServletRequest request) {
    String url = request.getScheme()+"://";   
    url+=request.getHeader("host");   
    url+=request.getRequestURI();   
    if(request.getQueryString()!=null)  {
        url+="?"+request.getQueryString();   
    }
    return url;
}
}

6 JSP+Servlet+JavaBean实现登录

登录页面:login.html
登录成功欢迎页面:login_success.jsp
登录失败页面:login_failure.jsp
Servlet处理文件:LoginServlet.java
 
登录页面:login.html

<!-- 一个简单的登录界面 --><!-- 该JSP程序是用来测试与MySQL数据库的连接, 需要一个数据库:LearnJSP,和其中一个表:userinfo 表中有两个字段分别为:UserName varchar (20) not null,UserPwd varchar (20) not null--><html> <head>  <title>登录</title>  <meta http-equiv="content-type" content="text/html; charset=UTF-8">  <meta http-equiv="Content-Language" content="ch-cn"> </head> <body> <!-- Form 用来提取用户填入并提交的信息--> <form method="post" name="frmLogin" action="LoginServlet">  <h1 align="center">用户登录</h1><br>  <div align="center">用户名:   <input type="text" name="txtUserName" value="Your name"    size="20" maxlength="20"    οnfοcus="if(this.value=='Your name')this.value='';"><br>密码:   <input type="password" name="txtPassword" value="Your password"    size="20" maxlength="20"    οnfοcus="if(this.value=='Your password')this.value='';"><br>   <input type="submit" name="Submit" value="提交" onClick="validateLogin();" >             <input type="reset" name="Reset" value="重置"><br>  </div> </form> <!-- javaScript 函数 validateLogin(),用来验证用户名和密码是否为空 -->  <script language="javaScript">   function validateLogin()   {   var sUserName = document.frmLogin.txtUserName.value;   var sPassword = document.frmLogin.txtPassword.value;   if( sUserName=="" )   {    alert("请输入用户名!");    return false;   }   if( sPassword=="" )   {    alert("请输入密码!");    return false;   }   }  </script> </body></html>

登录成功欢迎页面:login_success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'login_failure.jsp' starting page</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <%  String userName = (String)session.getAttribute ( "UserName" ); %> <div align=center>  <%=userName%>  欢迎您,登录成功! </div> </body></html>

登录失败页面:login_failure.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'login_failure.jsp' starting page</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <% String userName = (String)session.getAttribute ( "UserName" ); %> <div align=center>  <%=userName%>  对不起,登录失败! </div> </body></html>

Servlet处理文件:LoginServlet.java
/** * 该JSP程序是用来测试与MySQL数据库的连接, * 需要一个数据库:LearnJSP,和其中一个表:userinfo * 表中有两个字段分别为:UserName varchar (20) not null,UserPwd varchar (20) not null */package zieckey.login.servlet;import java.sql.Statement;import java.io.IOException;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import javax.servlet.Servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginServlet extends HttpServlet implements Servlet{ public LoginServlet () { // TODO Auto-generated constructor stub } /* * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void doGet ( HttpServletRequest arg0, HttpServletResponse arg1 )  throws ServletException, IOException { } /* * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void doPost ( HttpServletRequest request, HttpServletResponse response )  throws ServletException, IOException { response.setContentType ( "text/html" ); String result = ""; // 获取用户名 String sUserName = request.getParameter ( "txtUserName" ); if ( sUserName == "" || sUserName == null || sUserName.length ( ) > 20 ) {  try  {  result = "请输入用户名(不超过20字符)!";  request.setAttribute ( "ErrorUserName", result );  response.sendRedirect ( "login.html" );  } catch ( Exception e )  {  } } // 获取密码 String sPasswd = request.getParameter ( "txtPassword" ); if ( sPasswd == "" || sPasswd == null || sPasswd.length ( ) > 20 ) {  try  {  result = "请输入密码(不超过20字符)!";  request.setAttribute ( "ErrorPassword", result );  response.sendRedirect ( "login.html" );  } catch ( Exception e )  {  } } // 登记JDBC驱动程序 try {  Class.forName ( "org.gjt.mm.mysql.Driver" ).newInstance ( ); } catch ( InstantiationException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("InstantiationException"); } catch ( IllegalAccessException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("IllegalAccessException"); } catch ( ClassNotFoundException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( );  System.out.println ("ClassNotFoundException"); } // 连接参数与Access不同 String url = "jdbc:mysql://localhost/LearnJSP"; // 建立连接 java.sql.Connection connection = null; Statement stmt = null; ResultSet rs = null; try {  connection = DriverManager.getConnection ( url, "root", "011124" );  stmt = connection.createStatement ( );  // SQL语句  String sql = "select * from userinfo where username='" + sUserName   + "' and userpwd = '" + sPasswd + "'";  rs = stmt.executeQuery ( sql );// 返回查询结果 } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } try {  if ( rs.next ( ) )// 如果记录集非空,表明有匹配的用户名和密码,登陆成功  {  // 登录成功后将sUserName设置为session变量的UserName  // 这样在后面就可以通过 session.getAttribute("UserName") 来获取用户名,  // 同时这样还可以作为用户登录与否的判断依据  request.getSession ( ).setAttribute ( "UserName", sUserName );  response.sendRedirect ( "login_success.jsp" );  } else  {  // 否则登录失败  //response.sendRedirect ( "MyJsp.jsp" );  response.sendRedirect ( "login_failure.jsp" );  } } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } try {  if ( null!=rs )  {  rs.close ( );  }  if ( null!=stmt )  {  stmt.close ( );  }  if ( null!=connection )  {  connection.close ( );  } } catch ( SQLException e ) {  // TODO Auto-generated catch block  e.printStackTrace ( ); } } /** * */ private static final long serialVersionUID = 1L;}

7 java servlet页面跳转

response.sendRedirect("/a.jsp");
response.sendRedirect("http://www.jb51.net");

RequestDispatcher dispatcher = request.getRequestDispatcher("/a.jsp");
dispatcher .forward(request, response);

response.setHeader("Location","");

8 java中Servlet处理乱码

1)从页面获取数据的servlet出现乱码,在servlet中已经把request.setCharacterEncoding("GB2312");加入到代码中去,
JAVA是Unicode编码,先转换成ISO8859-1,然后再转换成GBK或是GB2312.

request.setCharacterEncoding("ISO8859-1");    
ad=request.getParameter("name");    
byte[] temp3 = ad.getBytes("GBK");    
String str = new String(temp3);

这样就是中文啦

2)直接在服务器里设置编码转换
在Tomcat的conf目录里找到SERVER.XML文件,设置如下: 
里面增加一个属性,URIEncoding="GBK"

3)JSP页面上是中文,但是看的后是乱码
解决的办法就是在JSP页面的编码的地方,因为Jsp转成Java文件时的编码问题,默认的话有的服务器是ISO-8859-1,如果一个JSP中直接输入了中文,Jsp把它当作 ISO8859-1来处理是肯定有问题的,这一点,我们可以通过查看Jasper所生成的Java中间文件来确认
 
4)当用Request对象获取客户提交的汉字代码的时候,会出现乱码
解决的办法是:要配置一个filter,也就是一个Servelet的过滤器,

代码如下:

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)throws IOException, ServletException {

request.setCharacterEncoding("GBK");
// 传递控制到下一个过滤器

chain.doFilter(request, response);
}

配置web.xml
<filter></filter>
<filter-name></filter-name>Set Character Encoding
<filter-class></filter-class>SetCharacterEncodingFilter
 
<filter-mapping></filter-mapping>
<filter-name></filter-name>Set Character Encoding
<url-pattern></url-pattern>/*

如果还是出现这种情况的话就往下看看是不是出现了第四种情况,Form提交的数据是不是用get提交的,一般来说用post提交的话是没有问题的,如果是的话,看第四种解决的办法。

还有就是对含有汉字字符的信息进行处理,处理的代码是:
public String toUni(String gbStr){
String uniStr = "";
if(gbStr == null){
gbStr = "";
}
try{
byte[] tempByte = gbStr.getBytes("GB2312");
uniStr = new String(tempByte,"ISO8859_1");
}catch(Exception ex){
}
return uniStr;
}
}

也可以在直接的转换,首先将获取的字符串用ISO-8859-1进行编码,然后将这个编码存放到一个字节数组中,然后将这个数组转化成字符串对象就可以了,
String str=request.getParameter(“girl”);
Byte B[]=str.getBytes(“ISO-8859-1”);
Str=new String(B);
通过上述转换的话,提交的任何信息都能正确的显示。

5)在 Form get请求在服务端用request. getParameter(“name”)时返回的是乱码
按tomcat的做法设置Filter也没有用或者用 request.setCharacterEncoding("GBK");也不管用问题是出在处理参数传递的方法上:如果在servlet中用 doGet(HttpServletRequest request, HttpServletResponse response)方法进行处理的话前面即使是写了:

request.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");

也是不起作用的,返回的中文还是乱码.
如果把这个函数改成doPost(HttpServletRequest request, HttpServletResponse response)一切就OK了。
同样,在用两个JSP页面处理表单输入之所以能显示中文是因为用的是post方法传递的,改成get方法依旧不行。
由此可见在servlet中用doGet()方法或是在JSP中用get方法进行处理要注意。这毕竟涉及到要通过浏览器传递参数信息,很有可能引起常用字符集的冲突或是不匹配。
这个地方理解为request.setCharacterEncoding("GBK");set的是request中的body,而不是header部分,get请求时把参数放在url后边,不是放在body中,所以这个时候request.setCharacterEncoding("GBK")就没有起到作用,换到post提交就没有问题了,
解决的办法是:
1) 打开tomcat的server.xml文件,找到区块,加入如下一行:
URIEncoding=”GBK”

完整的应如下:
<connector uriencoding="GBK" maxthreads="150" debug="0" redirectport="8443" port="8080" enablelookups="false" maxsparethreads="75" minsparethreads="25" connectiontimeout="20000" disableuploadtimeout="true" acceptcount="100"></connector>

重启tomcat,一切OK。

6)JSP页面上有中文,按钮上面也有中文,但是通过服务器查看页面的时候出现乱码
解决的办法是:首先在JSP文件中不应该直接包含本地化的消息文本,而是应该通过<bean:message>标签从Resource Bundle中获得文本。应该把中文文本放到Application.properties文件中,这个文件放在WEB-INF/classes/* 下,例如页面里有姓名,年龄两个label,首先就是要建一个Application.properties,里面的内容应该是name=”姓名” age=”年龄”,然后把这个文件放到WEB-INF/classes/properties/下,接下来根据 Application.properties文件,对他进行编码转化,创建一个中文资源文件,假定名字是 Application_cn.properties。在JDK中提供了native2ascii命令,能够实现字符编码的转换。在DOS环境中找到你放置Application.properties的这个文件的目录,在DOS环境中执行一下命令,将生成按GBK编码的中文资源文件 Application_cn.properties:native2ascii ?encoding gbk Application.properties Application_cn.properties执行以上命令以后将生成如下内容的Application_cn.properties文件: name=u59d3u540d age=u5e74u9f84,在Struts-config.xml中配置:<message-resources parameter="properties.Application_cn"></message-resources>。到这一步,基本上完成了一大半,接着就要在JSP页面上写,到名字的那个label是要写<bean:message key="”name”">,这样的化在页面上出现的时候就会出现中文的姓名,年龄这个也是一样,按钮上汉字的处理也是同样的。
 
7)写入到数据库是乱码
解决的方法:要配置一个filter,也就是一个Servelet的过滤器,代码如同第二种时候一样。
如果是通过JDBC直接链接数据库的时候,配置的代码如下:jdbc:mysql://localhost:3306/workshopdb? useUnicode=true&characterEncoding=GBK,这样保证到数据库中的代码是不是乱码。
如果是通过数据源链接的话不能按照这样的写法了,首先就要写在配置文件中,

<context debug="0" path="/workshop" docbase="workshop"></context>reloadable="true" >
 
<resource name="jdbc/WorkshopDB"></resource>auth="Container"
type="javax.sql.DataSource" />
 
<resourceparams name="jdbc/WorkshopDB"></resourceparams>
<parameter></parameter> 
<name></name>factory
<value></value>org.apache.commons.dbcp.BasicDataSourceFactory
 
<parameter></parameter> 
<name></name>maxActive
<value></value>100
 
<parameter></parameter> 
<name></name>maxIdle
<value></value>30
 
<parameter></parameter> 
<name></name>maxWait
<value></value>10000
 
<parameter></parameter> 
<name></name>username
<value></value>root
 
<parameter></parameter> 
<name></name>password
<value></value>
 
<parameter></parameter> 
<name></name>driverClassName
<value></value>com.mysql.jdbc.Driver
 
<parameter></parameter> 
<name></name>url
<value></value>

8)servlet分页

Oracle数据库,获取SCOTT用户EMP表中的数据,

创建一个对象 UserData,用以保存从数据库中获取的数据。

package com.tool;
 
import java.math.BigDecimal;
import java.util.Date;
 
public class UserData {
 
    /**
     * EMP表中的数据属性
     */
    private String ename;
    private String job;
    private BigDecimal empno;
    private BigDecimal mgr;
    private Date hireDate;
    private BigDecimal sal;
    private BigDecimal comm;
    private BigDecimal deptno;
 
    public BigDecimal getEmpno() {
        return empno;
    }
 
    public void setEmpno(BigDecimal empno) {
        this.empno = empno;
    }
 
    public BigDecimal getMgr() {
        return mgr;
    }
 
    public void setMgr(BigDecimal mgr) {
        this.mgr = mgr;
    }
 
    public Date getHireDate() {
        return hireDate;
    }
 
    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }
 
    public BigDecimal getSal() {
        return sal;
    }
 
    public void setSal(BigDecimal sal) {
        this.sal = sal;
    }
 
    public BigDecimal getComm() {
        return comm;
    }
 
    public void setComm(BigDecimal comm) {
        this.comm = comm;
    }
 
    public BigDecimal getDeptno() {
        return deptno;
    }
 
    public void setDeptno(BigDecimal deptno) {
        this.deptno = deptno;
    }
 
    public String getEname() {
        return ename;
    }
 
    public void setEname(String ename) {
        this.ename = ename;
    }
 
    public String getJob() {
        return job;
    }
 
    public void setJob(String job) {
        this.job = job;
    }
}

创建一个 DBHelper 对象用以与数据库进行交互

package com.dao;
 
import com.tool.UserData;
 
import java.math.BigDecimal;
import java.sql.*;
import java.util.*;
import java.util.Date;
 
public class DBHelper {
 
    Connection conn;  //数据库连接对象
    PreparedStatement pt;  //SQL语句预处理对象
    ResultSet rs;  //结果集对象
 
    public  DBHelper(){
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");  //装载驱动
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 获取当前页的数据
     * @param curPage
     * @param rowsPerPage
     * @return
     */
    public List<UserData> getData(int curPage, int rowsPerPage) {
 
        List<UserData> dataList = new ArrayList<>();
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        try {
            conn = DriverManager.getConnection(url,"scott","tiger");
            String sql = "select * from emp where rownum <= ((? - 1) * "+rowsPerPage+" + "+rowsPerPage+") minus " +
                    " select * from emp where rownum <= (? - 1) * "+rowsPerPage+" ";
            pt = conn.prepareStatement(sql);
            pt.setInt(1,curPage);
            pt.setInt(2,curPage);
            rs = pt.executeQuery();
            while (rs.next()){
                /**
                 * 从结果集中取得数据
                 */
                UserData userData = new UserData();
                BigDecimal empno = rs.getBigDecimal("empno");
                String ename = rs.getString("ename");
                String job = rs.getString("job");
                BigDecimal mgr = rs.getBigDecimal("mgr");
                Date hireDate = rs.getDate("hiredate");
                BigDecimal sal = rs.getBigDecimal("sal");
                BigDecimal comm = rs.getBigDecimal("comm");
                BigDecimal deptno = rs.getBigDecimal("deptno");
                /**
                 * 设置对象属性
                 */
                userData.setEmpno(empno);
                userData.setEname(ename);
                userData.setJob(job);
                userData.setMgr(mgr);
                userData.setHireDate(hireDate);
                userData.setSal(sal);
                userData.setComm(comm);
                userData.setDeptno(deptno);
                dataList.add(userData);  //把对象添加集合中
            }
            rs.close();
            pt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataList;
    }
 
    /**
     * 返回总页数
     * @return
     */
    public int getMaxPage(int rowsPerPage) {
        int maxPage;
        int maxRowCount = 0;
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        try {
            conn = DriverManager.getConnection(url,"scott","tiger");  //创建数据库连接
            String sql = "select count(*) from emp";
            pt = conn.prepareStatement(sql);
            rs = pt.executeQuery();
            if (rs.next()){
                maxRowCount = rs.getInt(1);  //总行数
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        maxPage = (maxRowCount + rowsPerPage - 1) / rowsPerPage;  //总页数
        return maxPage;
    }
}

创建 Servlet 对显示页面进行控制

package com.servlet;
 
import com.dao.DBHelper;
import com.tool.UserData;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
 
public class Servlet extends HttpServlet {
 
    public int rowsPerPage;  //每页显示的行数
    public int curPage;  //当前页页码
    public int maxPage;  //总共页数
    DBHelper db = new DBHelper();
    public Servlet(){
        rowsPerPage = 5;
    }
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String curPage1 = request.getParameter("page");  //获取当前页页码
        if (curPage1 == null){
            curPage = 1;
            request.setAttribute("curPage",curPage);  //设置curPage对象
        }else {
            curPage = Integer.parseInt(curPage1);
            if (curPage < 1){
                curPage = 1;
            }
            request.setAttribute("curPage",curPage);
        }
 
        List<UserData> dataList;
        dataList = db.getData(curPage,rowsPerPage);  //获取当前页的数据
        maxPage = db.getMaxPage(rowsPerPage);  //获取总页数
        request.setAttribute("dataList",dataList);
        request.setAttribute("maxPage", maxPage);
 
        RequestDispatcher rd = request.getRequestDispatcher("pagemain.jsp");  //将请求转发到pagemain.jsp页面
        rd.forward(request,response);
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

创建 JSP 页面,显示数据。

<%@ page import="java.util.List" %>
<%@ page import="com.tool.UserData" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>servlet数据分页</title>
    <link rel="stylesheet" type="text/css" href="css.css">
</head>
<body>
<div style="margin-top: 15%; margin-left: 25%">
    <table>
        <caption>SCOTT用户,EMP表中的数据</caption>
        <%! int curPage,maxPage; %>
        <% curPage =Integer.parseInt(request.getAttribute("curPage").toString()); %> <!--取得当前页-->
        <% maxPage =Integer.parseInt((String)request.getAttribute("maxPage").toString()); %> <!--取得总页数-->
        <%if (request.getAttribute("dataList") == null){
        %>
        <tr>
            <td colspan="8">没有数据</td>
        </tr>
        <%
        }else {
        %>
        <tr>
            <!--表头-->
            <th>EMPNO</th>
            <th>ENAME</th>
            <th>JOB</th>
            <th>MGR</th>
            <th>HIREDATE</th>
            <th>SAL</th>
            <th>COMM</th>
            <th>DEPTNO</th>
        </tr>
        <%
            List list = (List) request.getAttribute("dataList");
            for (Object aList : list) {
                UserData userData = (UserData) aList;
        %>
        <tr>
            <!--取得表中数据-->
            <td><%= userData.getEmpno() %></td>
            <td><%= userData.getEname() %></td>
            <td><%= userData.getJob() %></td>
            <td><%= userData.getMgr() %></td>
            <td><%= userData.getHireDate() %></td>
            <td><%= userData.getSal() %></td>
            <td><%= userData.getComm() %></td>
            <td><%= userData.getDeptno() %></td>
        </tr>
        <%
                }
            }
        %>
    </table>
</div>
<div style="margin-top: 8%; margin-left: 29%">
    第<%= curPage %>页,共<%= maxPage %>页  
    <%if (curPage > 1){
    %>
    <a href="Servlet?page=1">首页</a>
    <a href="Servlet?page=<%=curPage - 1%>">上一页</a>
    <%
    }else {
    %>
    首页 上一页
    <%
        }%>
    <%if (curPage < maxPage){
    %>  
    <a href="Servlet?page=<%=curPage + 1%>">下一页</a>
    <a href="Servlet?page=<%=maxPage %>">尾页</a>
    <%
    }else {
    %>
    下一页 尾页
    <%
        }%>
      转至第 <form name="form1" action="Servlet" method="get">
    <label>
        <select name="page" οnchange="document.form1.submit()">
            <%for ( int i = 1; i <= maxPage; i++){
                if (i == curPage){
            %>
            <!--当前页页码默认选中-->
            <option selected value="<%= i%>"><%= i %></option>
            <%
            }else {
            %>
            <option value="<%= i %>"><%= i %></option>
            <%
                    }
                }%>
        </select>
    </label>
</form> 页
</div>
</body>
</html>
 
web.xml
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.servlet.Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/Servlet</url-pattern>
    </servlet-mapping>

Java Servlet 开发常用代码、模板、问题相关推荐

  1. java 静态代码块有什么用,java编程开发静态代码块的使用方法都有哪些

    代码块是程序员在学习java编程开发的时候会接触到的一个代码,而今天我们就通过案例分析来了解一下,java编程开发静态代码块的使用方法都有哪些. (一)java静态代码块静态方法区别 一般情况下,如果 ...

  2. 科普:Java 后端开发常用的 10 种第三方服务

    严格意义上说,所有软件的第三方服务都可以自己开发,不过从零到一是需要时间和金钱成本的.就像我们研发芯片,投入了巨大的成本,但仍然没有取得理想的成绩,有些事情并不是一朝一夕,投机取巧就能完成的. Jav ...

  3. Java 后端开发常用的第三方服务 TOP10

    严格意义上说,所有软件的第三方服务都可以自己开发,不过从零到一是需要时间和金钱成本的.就像我们研发芯片,投入了巨大的成本,但仍然没有取得理想的成绩,有些事情并不是一朝一夕,投机取巧就能完成的. Jav ...

  4. 金蝶GUI开发常用代码

    金蝶GUI开发常用代码 获取控制单元并且设置组织隔离 CtrlUnitCollection ctUnitColls = CtrlUnitFactory.getLocalInstance(ctx).ge ...

  5. as3 java 交互_AS3常用代码(三):AS3与HTML的交互

    老实说,对AS3与HTML的交互实际上了解的不多,也很少运用. 其实HTML在嵌入SWF时使用的OBJECT标签也有很多可以挖掘的地方,那我们就来研究一下··· codebase="http ...

  6. Maven简介,java高级开发研发简历模板

    前言 在Java项目开发中,项目的编译.测试.打包等是比较繁琐的,属于重复劳动的工作,浪费人力和时间成本.以往开发项目时,程序员往往需要花较多的精力在引用jar包搭建项目环境上,跨部门甚至跨人员之间的 ...

  7. 第三方服务 “TOP10”Java 后端开发常用的

    严格意义上说,所有软件的第三方服务都可以自己开发,不过从零到一是需要时间和金钱成本的.就像我们研发芯片,投入了巨大的成本,但仍然没有取得理想的成绩,有些事情并不是一朝一夕,投机取巧就能完成的. Jav ...

  8. java应用开发常用的中间件_Java开发常用的一些软件工具和插件以及开发中间件...

    总结一下自己在java开发中常用的一些软件工具,插件,容器,中间件等. 常用软件及插件 一.intellij idea(及好用的集成插件): 1.iBATIS/MyBatis mini-plugin: ...

  9. java servlet 开发_Java之基于Servlet的Web开发简介

    由于学习的过程中,接触到了这部分内容,所以特别的在这进行整理,分享给大家. 1.定义 Servlet是Java Servlet的简称,称为小服务程序或服务连接器: 2.原理 从原理上讲,Servlet ...

最新文章

  1. 八、LaTex中的表格
  2. 大数据,只是为了赚钱么?
  3. Flask项目常见面试问题
  4. 牛客网-剑指offer 第二题(字符替换)
  5. 数据类型字符串得索引及切片
  6. k2677场效应管参数引脚_共射极放大电路,场效应管放大电路,运算放大电路
  7. ZZULIOJ069:向z同学学习
  8. clob大数据转换为多行数据
  9. SIP Servlet开发环境配置
  10. 2012中国软件业务收入百强企业发布 (zz.IS2120)
  11. scrum敏捷开发流程介绍和心得
  12. 怎样在html中加入计数器?(2),html如何实现计数器以及时钟的功能代码
  13. 配置IKAnalyzer扩展词库
  14. chrome查看请求加载时间
  15. 基础的拉普拉斯金字塔融合用于改善图像增强中易出现的过增强问题(一)
  16. Head First C - C语言入门
  17. c++ 连接mysql数据库
  18. 宿主机使用wifi时虚拟机如何连网
  19. 电子合同与纸质合同法律效力一样吗?
  20. STM32——程序的启动过程

热门文章

  1. js简单的条件语句判断
  2. DIV CSS left right top bottom定位
  3. CSS3文本居中显示、圆形圆角绘制、立体阴影效果设置实例演示
  4. CTFshow php特性 web108
  5. windows的键盘输入重定向
  6. 第八周实践项目3 顺序串一些算法操作
  7. [YTU]_2619 (B 友元类-计算两点间距离)
  8. DIP第三章习题解答
  9. jQuery快速入门专题
  10. P4719 【模板】动态dp