Article catalogue
I http server
1. Preparation
- Modify four places
Httpresponse - > constant web_ APP_ The value of path is consistent with the current module
In the httpserver - > main method, the port is changed to 80
Httpresponse - > add a write method and a construction method with parameters
Httpresponse - > add a contentType member variable to generate the corresponding set/get method
- Sample code
// 1. Httpresponse - > constant web_ APP_ The value of path is consistent with the current module public class HttpResponse { ... public static final String WEB_APP_PATH = "http-dynamic-server\\webapp"; ... } // 2. In the httpserver - > main method, the port is changed to 80 public class HttpServer { public static void main(String[] args) throws IOException { ... //2. Bind this channel to a port serverSocketChannel.bind(new InetSocketAddress(80)); ... } } // 3. Httpresponse - > add a write method and a construction method with parameters public class HttpResponse { ... // The selectionKey has been provided, so the previous method that receives this parameter can be removed and can be used directly // HttpRequest is also optimized in this way, defining member variables, assigning values in the construction method, and other methods can be used directly private SelectionKey selectionKey; public HttpResponse(SelectionKey selectionKey) { this.selectionKey = selectionKey; } //The method of responding data to the browser ---- the method by which the browser responds to data when requesting dynamic resources //Content: the content of the response public void write(String content){ } ... } public class HttpServer { public static void main(String[] args) throws IOException { ... //Response data / / parameters to be passed in the modified construction method HttpResponse httpResponse = new HttpResponse(selectionKey); ... } } // 4. Httpresponse - > add a contentType member variable to generate the corresponding set/get method public class HttpResponse { ... private String contentType;//MIME type public String getContentType() { return contentType; } public void setContentTpye(String contentType) { this.contentType = contentType; //Add to map collection hm.put("Content-Type",contentType); } ... }
2. Browser requests dynamic resources
- Two small problems
How does the server determine whether the browser requests static resources or dynamic resources?
We can specify that if the uri in the browser address bar starts with "/ servlet", it means that dynamic resources are requested
There are many classes and methods in a project. After the request comes, which method will be executed?
Write a UserServlet class and write the service method in the class
We can specify that if dynamic resources are requested, this class object will be created and the service method will be called to indicate that the server has processed the current request
- Implementation steps
Parsing http requests
Processing browser requests
Define a UserServlet class in which the service method is defined to handle the dynamic resources requested by the browser
After parsing the http request, determine whether the uri starts with / servlet
response
- Sample code
public class UserServlet{ public void service(){ //Simulate business processing -- you can judge and verify the mobile phone number System.out.println("UserServlet The user's request was processed..."); } } public class HttpServer { public static void main(String[] args) throws IOException { ... //Response data HttpResponse httpResponse = new HttpResponse(selectionKey); httpResponse.setHttpRequest(httpRequest); if(httpRequest.getRequestURI().startsWith("/servlet")){ //Dynamic resources requested this time //handle UserServlet userServlet = new UserServlet(); userServlet.service(); //response httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("ok,UserServlet This request has been processed...."); }else{ //Static resources requested this time httpResponse.sendStaticResource(); } ... } } public class HttpResponse { ... //The method of responding data to the browser ---- the method by which the browser responds to data when requesting dynamic resources //Content: the content of the response public void write(String content){ //Prepare response line data this.version = "HTTP/1.1"; this.status = "200"; this.desc = "ok"; //Splice the response lines together String responseLine = this.version + " " + this.status + " " + this.desc + "\r\n"; //Prepare response header StringBuilder sb = new StringBuilder(); Set<Map.Entry<String, String>> entries = hm.entrySet(); for (Map.Entry<String, String> entry : entries) { //entry represents each key value pair object in turn //Key --- the name of the response header //Value --- the value of the response header sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n"); } //Processing response blank lines String emptyLine = "\r\n"; //Splice response line, response header, response blank line String result = responseLine + sb.toString() + emptyLine; try { //Give the browser a response line, a response header, and a blank response line ByteBuffer byteBuffer1 = ByteBuffer.wrap(result.getBytes()); SocketChannel channel = (SocketChannel) selectionKey.channel(); channel.write(byteBuffer1); //Give browser response body ByteBuffer byteBuffer2 = ByteBuffer.wrap(content.getBytes()); channel.write(byteBuffer2); //Release resources channel.close(); } catch (IOException e) { System.out.println("Response data failed...."); e.printStackTrace(); } } ... }
3.main method and Servlet optimization
main method optimization
- demand Extract the code requesting dynamic resources into a separate class and method to simplify the code in main
- code implementation
public class DynamicResourceProcess { //Executes the service method of the specified dynamic resource //Parameter one //Because the corresponding processing may be made according to the uri requested by the user in the later stage //Parameter two //To respond data to users, you need to use httpResponse public void process(HttpRequest httpRequest,HttpResponse httpResponse) { // Create a UserServlet object and call the service method for processing UserServlet userServlet = new UserServlet(); userServlet.service(); //Respond to browser httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("ok,UserServlet This request has been processed...."); } } public class HttpServer { public static void main(String[] args) throws IOException { ... //Response data HttpResponse httpResponse = new HttpResponse(selectionKey); httpResponse.setHttpRequest(httpRequest); if(httpRequest.getRequestURI().startsWith("/servlet")){ //Dynamic resources requested this time DynamicResourceProcess drp = new DynamicResourceProcess(); drp.process(httpRequest,httpResponse); }else{ //Static resources requested this time httpResponse.sendStaticResource(); } ... } }
Servlet optimization
- demand Write the code that responds to the browser to the Servlet
- code implementation
public class UserServlet implements HttpServlet{ //Method of processing browser request //Parameter one //Because the corresponding processing may be made according to the uri requested by the user in the later stage //Parameter two //To respond data to users, you need to use httpResponse public void service(HttpRequest httpRequest, HttpResponse httpResponse){ //Simulate business processing -- you can judge and verify the mobile phone number System.out.println("UserServlet The user's request was processed..."); //Respond to browser httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("ok,UserServlet This request has been processed...."); } } public class DynamicResourceProcess { //Executes the service method of the specified dynamic resource //Parameter one //Because the corresponding processing may be made according to the uri requested by the user in the later stage //Parameter two //To respond data to users, you need to use httpResponse public void process(HttpRequest httpRequest,HttpResponse httpResponse) { // Create a UserServlet object and call the service method for processing UserServlet userServlet = new UserServlet(); userServlet.service(httpRequest,httpResponse); } }
4. Multiple dynamic resources
- Multiple dynamic resources For each business operation, we will define a corresponding Servlet to complete it. Many servlets will be generated on the server

- Implementation steps
- Define an interface HttpServlet, and define the service method in the interface.
- For each service, a servlet class is defined corresponding to it, which implements the HttpServlet interface
- Get the uri of the request, make a judgment, and call the service method in different servlet classes
- code implementation
// 1. Define an interface HttpServlet, and define the service method in the interface public interface HttpServlet { //Define the method of business processing public abstract void service(HttpRequest httpRequest, HttpResponse httpResponse); } // 2. For each service, define a servlet class corresponding to it, which implements the HttpServlet interface public class UserServlet implements HttpServlet{ //Method of processing browser request //Parameter one //Because the corresponding processing may be made according to the uri requested by the user in the later stage //Parameter two //To respond data to users, you need to use httpResponse public void service(HttpRequest httpRequest, HttpResponse httpResponse){ //Simulate business processing -- you can judge and verify the mobile phone number System.out.println("UserServlet The user's request was processed..."); //Respond to browser httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("ok,UserServlet This request has been processed...."); } } public class LoginServlet implements HttpServlet{ @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) { //handle System.out.println("LoginServlet Login request processed"); //response httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("Login succeeded"); } } public class RegisterServlet implements HttpServlet{ @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) { //handle System.out.println("RegisterServlet Registration request processed"); //response httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("login was successful"); } } public class SearchServlet implements HttpServlet{ @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) { //handle System.out.println("SearchServlet Search item request processed"); //response httpResponse.setContentTpye("text/html;charset=UTF-8"); httpResponse.write("Responded to some product information"); } } // 3. Obtain the uri of the request, make judgment, and call the service method in different servlet classes public class DynamicResourceProcess { public void process(HttpRequest httpRequest,HttpResponse httpResponse){ //Gets the uri of the request String requestURI = httpRequest.getRequestURI(); //Judge according to the requested uri if("/servlet/loginservlet".equals(requestURI)){ //Login request LoginServlet loginServlet = new LoginServlet(); loginServlet.service(httpRequest,httpResponse); }else if("/servlet/registerservlet".equals(requestURI)){ //Registration request RegisterServlet registerServlet = new RegisterServlet(); registerServlet.service(httpRequest,httpResponse); }else if("/servlet/searchservlet".equals(requestURI)){ //Search for product requests SearchServlet searchServlet = new SearchServlet(); searchServlet.service(httpRequest,httpResponse); }else{ //Indicates the default processing method //Create a UserServlet object and call the service method for processing UserServlet userServlet = new UserServlet(); userServlet.service(httpRequest,httpResponse); } } }
5. Optimize through reflection and configuration file
- Optimization steps
- Write the Servlet information to the properties configuration file
Format: servlet info = / servlet / userservlet, full class name/ servlet/loginServlet, full class name
- Define an interface ServletConcurrentHashMap. The interface defines ConcurrentHashMap. This collection stores all servlet information
- Define an interface, ParseServletConfig, in which a method (parse) is defined
- Define the implementation class of ParseServletConfig, parse the configuration file, and save the Servlet information in the configuration file into the map collection
- In the first line of the main method, start a thread to execute the code that parses the configuration file
- Modify the process method in the DynamicResourceProcess

- code implementation
// 1. Write the Servlet information into the properties configuration file // In webapp \ config \ servlet info In the properties file, write the following servlet-info=/servlet/loginservlet,com.itheima.myservlet.LoginServlet;/servlet/registerservlet,com.itheima.myservlet.RegisterServlet;/servlet/searchservlet,com.itheima.myservlet.SearchServlet;/servlet/lostpasswordservlet,com.itheima.myservlet.LostPasswordServlet // 2. Define an interface ServletConcurrentHashMap. The interface defines ConcurrentHashMap, which stores all servlet information public interface ServletConcurrentHashMap { //A map collection that stores the request path and the corresponding servlet //Key: requested uri //Value: the corresponding Servlet object public static final ConcurrentHashMap<String, HttpServlet> map = new ConcurrentHashMap<>(); } // 3. Define an interface ParseServletConfig, in which a method (parse) is defined public interface ParseServletConfig { //Method of parsing data public abstract void parse(); } // 4. Define the implementation class of ParseServletConfig, parse the configuration file, and save the Servlet information in the configuration file into the map set public class PropertiesParseServletConfig implements ParseServletConfig { @Override public void parse() { try { //1. Read the data in the configuration file Properties properties = new Properties(); FileReader fr = new FileReader("http-dynamic-server/webapp/config/servlet-info.properties"); properties.load(fr); fr.close(); //2. Get the attribute value of servlet info in the collection String properValue = (String) properties.get("servlet-info"); // uri, full class name; uri, full class name //3. Analysis String[] split = properValue.split(";"); for (String servletInfo : split) { String[] servletInfoArr = servletInfo.split(","); String uri = servletInfoArr[0]; String servletName = servletInfoArr[1]; //We need to create his object through servletname (full class name) Class clazz = Class.forName(servletName); HttpServlet httpServlet = (HttpServlet) clazz.newInstance(); //4. Add uri and httpServlet to the map set ServletConcurrentHashMap.map.put(uri,httpServlet); } } catch (Exception e) { System.out.println("Parsing data exception....."); e.printStackTrace(); } } } public class LoaderResourceRunnable implements Runnable { @Override public void run() { //Execute parse method ParseServletConfig parseServletConfig = new PropertiesParseServletConfig(); parseServletConfig.parse(); } } // 5. In the first line of the main method, start a thread to execute the code for parsing the configuration file public class HttpServer { public static void main(String[] args) throws IOException { //Start a thread to parse the configuration file new Thread(new LoaderResourceRunnable()).start(); ... } } // 6. Modify the process method in dynamic resourceprocess public class DynamicResourceProcess { public void process(HttpRequest httpRequest,HttpResponse httpResponse){ //Gets the uri of the request String requestURI = httpRequest.getRequestURI(); //Directly find the corresponding servlet object in the map collection according to the requested uri HttpServlet httpServlet = ServletConcurrentHashMap.map.get(requestURI); //Call the service method to process the request and respond httpServlet.service(httpRequest,httpResponse); } }
7. The servlet forgot to implement HttpServlet interface processing
- Occurrence
When writing a Servlet, I forgot to implement the HttpServlet interface
- Result
After the reflection creates an object, a type conversion exception will be reported when it is strongly converted to HttpServlet
- Solution
After the reflection object is created, judge before strong conversion to HttpServlet
If the HttpServlet interface is implemented, perform forced conversion
Otherwise, an exception is thrown
- code implementation
public class PropertiesParseServletConfig implements ParseServletConfig { @Override public void parse() { try { //1. Read the data in the configuration file Properties properties = new Properties(); FileReader fr = new FileReader("http-dynamic-server/webapp/config/servlet-info.properties"); properties.load(fr); fr.close(); //2. Get the attribute value of servlet info in the collection String properValue = (String) properties.get("servlet-info"); // uri, full class name; uri, full class name //3. Analysis String[] split = properValue.split(";"); for (String servletInfo : split) { String[] servletInfoArr = servletInfo.split(","); String uri = servletInfoArr[0]; String servletName = servletInfoArr[1]; //We need to create his object through servletname (full class name) Class clazz = Class.forName(servletName); //Get all the interface information implemented by this class and get an array Class[] interfaces = clazz.getInterfaces(); //Define a variable of boolean type boolean flag = false; //Traversal array for (Class clazzInfo : interfaces) { //Judge whether the bytecode object of the currently traversed interface is the same as the bytecode file object of HttpServlet if(clazzInfo == HttpServlet.class){ //If it is the same, you need to change the flag value End cycle flag = true; break; } } if(flag){ //true indicates that the current class has implemented the HttpServlet interface HttpServlet httpServlet = (HttpServlet) clazz.newInstance(); //4. Add uri and httpServlet to the map set ServletConcurrentHashMap.map.put(uri,httpServlet); }else{ //false means that the current class has not implemented the HttpServlet interface throw new NotImplementsHttpServletException(clazz.getName() + "Not Implements HttpServlet"); } } } catch (NotImplementsHttpServletException e) { e.printStackTrace(); }catch (Exception e) { System.out.println("Parsing data exception....."); e.printStackTrace(); } } }
8. Response 404
- Occurrence
The client browser requested a dynamic resource that does not exist in the server
- Result
The code in the server is abnormal and the program stops
- Solution
If the requested dynamic resource does not exist, and the server finds the corresponding Servlet according to the requested uri, it will be null. If you continue to call the method, an exception will appear
Add a non null judgment. If it is not null, continue to process the request and call the method
If null, response 404
- code implementation
public class DynamicResourceProcess { //Executes the service method of the specified dynamic resource //Parameter one //Because the corresponding processing may be made according to the uri requested by the user in the later stage //Parameter two //To respond data to users, you need to use httpResponse public void process(HttpRequest httpRequest,HttpResponse httpResponse){ //Gets the uri of the request String requestURI = httpRequest.getRequestURI(); //Directly find the corresponding servlet object in the map collection according to the requested uri HttpServlet httpServlet = ServletConcurrentHashMap.map.get(requestURI); if(httpServlet != null){ //Call the service method to process the request and respond httpServlet.service(httpRequest,httpResponse); }else{ //The dynamic resource requested by the browser does not exist //Response 404 response404(httpResponse); } } //The browser requests that the dynamic resource does not exist and responds to 404 private void response404(HttpResponse httpResponse) { try { //Prepare response line String responseLine = "HTTP/1.1 404 NOT FOUND\r\n"; //Prepare response header String responseHeader = "Content-Type: text/html;charset=UTF-8\r\n"; //Prepare response blank line String emptyLine = "\r\n"; //Spliced together String result = responseLine + responseHeader + emptyLine; //Send the response line, response header and empty response line to the browser SelectionKey selectionKey = httpResponse.getSelectionKey(); SocketChannel channel = (SocketChannel) selectionKey.channel(); ByteBuffer byteBuffer1 = ByteBuffer.wrap(result.getBytes()); channel.write(byteBuffer1); //Content of response body to browser ByteBuffer byteBuffer2 = ByteBuffer.wrap("404 NOT FOUND....".getBytes()); channel.write(byteBuffer2); //Release resources channel.close(); } catch (IOException e) { e.printStackTrace(); } } }